我尝试设置Xamarin Forms应用程序以使用Google Cloud Messaging(GCM),并且我遇到了一种非常奇怪的行为。我目前在Windows上使用Xamarin Studio并关注remote notification walkthrough。
出于某种原因,GCMPubSub.Subscribe()
仅适用于蜂窝连接而非wifi。我尝试过不同的wifi网络,效果相同。开发方案是否可能使用生产设置不具备的某些不同端口或网络行为?在接收推送通知的这些不同网络上,我的Android手机从未出现问题。
有什么想法吗?
修改
我目前收到的错误是IOException
,消息为"无效参数"在Subscribe()
中调用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>
答案 0 :(得分:1)
在使用GCM时,我没有遇到过这个问题。一直在比较我的实现与您当前的代码,看看是否找到相关的东西。将建议尝试使用应用程序上下文来获取实例以确保所有实例都在相同的上下文中。
对于InstanceID:
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");
如果有帮助,请告诉我。