2015-12-16 151 views
0

我試圖設置一個Xamarin Forms應用程序來使用Google Cloud Messaging(GCM),我遇到了一個非常奇怪的行爲。我目前在Windows上使用Xamarin Studio並遵循其remote notification walkthroughGoogle Cloud Messaging連接問題

由於某些原因,GCMPubSub.Subscribe()只適用於蜂窩連接而不適用於WiFi。我試過不同的wifi網絡,結果相同。開發場景是否可能使用生產設置不支持的一些不同的端口或網絡行爲?在接收推送通知的這些不同網絡上,我的Android手機從未出現過問題。

有什麼想法?

編輯

我目前接收與「無效參數」的消息的IOExceptionSubscribe()被稱爲GcmRegistrationService錯誤,但只有當連接到WiFi網絡。我試着比較我做了什麼給GCM Android的例子,他們的行爲類似

在MainActivity:

[Activity(Label = "MyApp", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] 
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity 
{ 
    protected override void OnCreate(Bundle bundle) 
    { 
     base.OnCreate(bundle); 

     global::Xamarin.Forms.Forms.Init(this, bundle); 
     LoadApplication(new App(DeviceType.Android)); 

     if (IsPlayServicesAvailable()) 
     { 
      var intent = GcmRegistrationService.GetIntent(this, "MyTopic"); 
      StartService(intent); 
     } 
    } 

    public bool IsPlayServicesAvailable() 
    { 
     var resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this); 
     if (resultCode != ConnectionResult.Success) 
     { 
      if (GoogleApiAvailability.Instance.IsUserResolvableError(resultCode)) 
       ToastHelper.ShowStatus("Google Play Services error: " + GoogleApiAvailability.Instance.GetErrorString(resultCode)); 
      else 
      { 
       ToastHelper.ShowStatus("Sorry, this device is not supported"); 
       Finish(); 
      } 
      return false; 
     } 
     else 
     { 
      ToastHelper.ShowStatus("Google Play Services is available."); 
      return true; 
     } 
    } 

} 

的GCM註冊意圖:

/// <summary> 
/// The background process that handles retrieving GCM token 
/// </summary> 
[Service(Exported = false)] 
public class GcmRegistrationService : IntentService 
{ 
    private static readonly object Locker = new object(); 

    public GcmRegistrationService() : base("GcmRegistrationService") { } 

    public static Intent GetIntent(Context context, string topic) 
    { 
     var valuesForActivity = new Bundle(); 
     valuesForActivity.PutString("topic", topic); 

     var intent = new Intent(context, typeof(GcmRegistrationService)); 

     intent.PutExtras(valuesForActivity); 

     return intent; 
    } 

    protected override void OnHandleIntent(Intent intent) 
    { 
     try 
     { 
      // Get the count value passed to us from MainActivity: 
      var topic = intent.Extras.GetString("topic", ""); 

      if (string.IsNullOrWhiteSpace(topic)) 
       throw new Java.Lang.Exception("Missing topic value"); 

      Log.Info("RegistrationIntentService", "Calling InstanceID.GetToken"); 
      lock (Locker) 
      { 
       var instanceId = InstanceID.GetInstance(this); 
       var projectNumber = Resources.GetString(Resource.String.ProjectNumber); 
       var token = instanceId.GetToken(projectNumber, GoogleCloudMessaging.InstanceIdScope, null); 

       Log.Info("RegistrationIntentService", "GCM Registration Token: " + token); 

       var applicationState = DataCacheService.GetApplicationState(); 

       // Save the token to the server if the user is logged in 
       if(applicationState.IsAuthenticated) 
        SendRegistrationToAppServer(applicationState.DeviceId, token); 

       Subscribe(token, topic); 
      } 
     } 
     catch (SecurityException e) 
     { 
      Log.Debug("RegistrationIntentService", "Failed to get a registration token because of a security exception"); 
      Log.Debug ("RegistrationIntentService", "Exception message: " + e.Message); 
      ToastHelper.ShowStatus("Google Cloud Messaging Security Error"); 
      return; 
     } 
     catch (Java.Lang.Exception e) 
     { 
      Log.Debug("RegistrationIntentService", "Failed to get a registration token"); 
      Log.Debug ("RegistrationIntentService", "Exception message: " + e.Message); 
      ToastHelper.ShowStatus("Google Cloud Messaging Error"); 
      return; 
     } 
    } 

    void SendRegistrationToAppServer(Guid deviceId, string token) 
    { 
     // Save the Auth Token on the server so messages can be pushed to the device 
     DeviceService.UpdateCloudMessageToken (deviceId, token); 

    } 

    void Subscribe(string token, string topic) 
    { 
     var pubSub = GcmPubSub.GetInstance(this); 

     pubSub.Subscribe(token, "/topics/" + topic, new Bundle()); 
     Log.Debug("RegistrationIntentService", "Successfully subscribed to /topics/" +topic); 
     DataCacheService.SaveCloudMessageToken(token, topic); 
    } 

} 

的AndroidManifest.xml中:

<manifest 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:installLocation="auto" 
    package="com.myapp" 
    android:versionCode="1" 
    android:versionName="1.0"> 

    <uses-sdk android:minSdkVersion="19" /> 

    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> 
    <uses-permission android:name="android.permission.WAKE_LOCK" /> 
    <uses-permission android:name="android.permission.INTERNET" /> 
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 

    <permission 
     android:name="com.myapp.permission.C2D_MESSAGE" 
     android:protectionLevel="signature" /> 

    <uses-permission 
     android:name="com.myapp.permission.C2D_MESSAGE" /> 

    <application 
     android:label="My App" 
     android:icon="@drawable/icon"> 

     <receiver 
      android:name="com.google.android.gms.gcm.GcmReceiver" 
      android:permission="com.google.android.c2dm.permission.SEND" 
      android:exported="true"> 

      <intent-filter> 
       <action android:name="com.google.android.c2dm.intent.RECEIVE" /> 
       <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> 
       <category android:name="com.myapp" /> 
      </intent-filter> 

     </receiver> 

     <service 
      android:name="com.myapp.XamarinMobile.Droid.Services.MyGcmListenerService" 
      android:exported="false"> 
      <intent-filter> 
       <action android:name="com.google.android.c2dm.intent.RECEIVE" /> 
      </intent-filter> 
     </service> 

    </application> 
</manifest> 

回答

1

我在使用GCM時遇到過這個問題。一直在比較我的實施與您當前的代碼,看看是否找到相關的東西。將建議嘗試使用應用程序上下文來獲取實例以確保所有實例處於相同的上下文中。

實例Id:

var instanceId = InstanceID.GetInstance(Android.App.Application.Context)); 

對於GcmPubSub:

GcmPubSub pubSub = GcmPubSub.GetInstance(Android.App.Application.Context); 

對於GcmRegistrationService:

GcmRegistrationService.GetIntent(Android.App.Application.Context, "MyTopic"); 

讓我知道是否有幫助。

+0

OMG謝謝!實際上,我可以調用'Subscribe()'方法,而不通過wifi給我一個例外。我仍然必須確認收到的消息,但這絕對是一個讓我覺得我很瘋狂的表演塞! –

+0

不幸的是,當我去使用令牌時,我收到一個未註冊的響應 –

+0

讓它工作!我試圖發送的消息格式不正確。再次感謝您的幫助 –