Google Cloud Messaging Communication Issues

I am trying to configure the Xamarin Forms application to use Google Cloud Messaging (GCM) and I am encountering very strange behavior. I am currently using Xamarin Studio on Windows and following the passage of remote notifications .

For some reason, it GCMPubSub.Subscribe()works only on cellular, not Wi-Fi. I tried different Wi-Fi networks with the same result. Is it possible that the development scenario uses several different ports or network behavior that are not in production settings? There has never been a problem with my Android phone on these different networks receiving push notifications.

Any thoughts?

Edit

The error I am currently getting is IOExceptionwith the message "Invalid Parameters" when Subscribe()called on GcmRegistrationService, but only on a Wi-Fi network. I tried to compare what I did with the Android GCM examples and they behave similarly

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;
        }
    }

}

The purpose of registering 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
source share
1 answer

I did not encounter this problem in my case when using GCM. Compare my implementation with your current code to see if there is anything relevant. Try to try to use the application context to get instances, to make sure that all instances are in the same context.

For 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");

, .

+1

Source: https://habr.com/ru/post/1622102/


All Articles