How to fix Google Cloud Messaging Registration error: SERVICE_NOT_AVAILABLE?

82,785

Solution 1

This SERVICE_NOT_AVAILABLE error says that GCM Service is not available in current. Wait and try after some time.

This happens many time (As my experience), so don't worry about it.


See the GCMConstants class of GCM Lib.

/**
     * The device can't read the response, or there was a 500/503 from the
     * server that can be retried later. The application should use exponential
     * back off and retry.
     */
    public static final String ERROR_SERVICE_NOT_AVAILABLE =
            "SERVICE_NOT_AVAILABLE";

For more investigation see handleRegistration() of GCMBaseIntentService

private void handleRegistration(final Context context, Intent intent) {
        String registrationId = intent.getStringExtra(EXTRA_REGISTRATION_ID);
        String error = intent.getStringExtra(EXTRA_ERROR);
        String unregistered = intent.getStringExtra(EXTRA_UNREGISTERED);
        Log.d(TAG, "handleRegistration: registrationId = " + registrationId +
                ", error = " + error + ", unregistered = " + unregistered);

        // registration succeeded
        if (registrationId != null) {
            GCMRegistrar.resetBackoff(context);
            GCMRegistrar.setRegistrationId(context, registrationId);
            onRegistered(context, registrationId);
            return;
        }

        // unregistration succeeded
        if (unregistered != null) {
            // Remember we are unregistered
            GCMRegistrar.resetBackoff(context);
            String oldRegistrationId =
                    GCMRegistrar.clearRegistrationId(context);
            onUnregistered(context, oldRegistrationId);
            return;
        }

        // last operation (registration or unregistration) returned an error;
        Log.d(TAG, "Registration error: " + error);
        // Registration failed
        if (ERROR_SERVICE_NOT_AVAILABLE.equals(error)) {
            boolean retry = onRecoverableError(context, error);
            if (retry) {
                int backoffTimeMs = GCMRegistrar.getBackoff(context);
                int nextAttempt = backoffTimeMs / 2 +
                        sRandom.nextInt(backoffTimeMs);
                Log.d(TAG, "Scheduling registration retry, backoff = " +
                        nextAttempt + " (" + backoffTimeMs + ")");
                Intent retryIntent =
                        new Intent(INTENT_FROM_GCM_LIBRARY_RETRY);
                retryIntent.putExtra(EXTRA_TOKEN, TOKEN);
                PendingIntent retryPendingIntent = PendingIntent
                        .getBroadcast(context, 0, retryIntent, 0);
                AlarmManager am = (AlarmManager)
                        context.getSystemService(Context.ALARM_SERVICE);
                am.set(AlarmManager.ELAPSED_REALTIME,
                        SystemClock.elapsedRealtime() + nextAttempt,
                        retryPendingIntent);
                // Next retry should wait longer.
                if (backoffTimeMs < MAX_BACKOFF_MS) {
                  GCMRegistrar.setBackoff(context, backoffTimeMs * 2);
                }
            } else {
                Log.d(TAG, "Not retrying failed operation");
            }
        } else {
            // Unrecoverable error, notify app
            onError(context, error);
        }
    }

Solution 2

The problem is answered, in my case it was little more complicated.

  1. Check you have an active internet connection
  2. Check that you have Internet permission in your manifest
  3. Make sure the package name is correct as Eran mentioned
  4. The device time is correctly setup. Even if everything is perfect, it will fail if device clock is not set correctly.

Wrong clock caused problem for me. :)

Solution 3

SERVICE_NOT_AVAILABLE is one of the most frustrating problems with Google Cloud Messaging. It is an exception thrown by GoogleCloudMessaging.register(SENDER_ID), the function call that registers the device for push notifications and returns a registration ID.

  1. SERVICE_NOT_AVAILABLE might mean that the user’s device can’t read the response to the registration request or a 500/503 error code was returned from the server. Developers have no way to fix this error because it is on Google’s end, so we can blindly suggest that the user should try again in a few hours.
  2. SERVICE_NOT_AVAILABLE may occur on some devices even though the registration succeeded. This can be fixed by implementing a workaround broadcast receiver to catch the token when the call fails. I implemented this workaround and it may have fixed the problem for some users, but still I received many other SERVICE_NOT_AVAILABLE complaints.
  3. SERVICE_NOT_AVAILABLE may occur because of an outdated or missing Google Play Services library on the device. In this case, the app could theoretically notify the user to update Google Play Services by opening the respective Google Play app listing. However, the app has no idea that this is why SERVICE_NOT_AVAILABLE was thrown, so it cannot blindly redirect the user to the Google Play Services app page on Google Play.
  4. SERVICE_NOT_AVAILABLE may occur when the device’s clock is not synchronized with the network. Again, developers have no way of knowing that this is the exact problem, so we can blindly suggest to the user to check their system clock synchronization, hoping they are one of the very few whose clocks are not synchronized.
  5. SERVICE_NOT_AVAILABLE may occur when a rooted user has deleted the Hangouts/GTalk app from their device (because they considered it bloatware). GCM is implemented and handled by Hangouts/GTalk, so it is not possible to use GCM without it.
  6. SERVICE_NOT_AVAILABLE may occur if the user is running a device that does not have Google APIs installed (such as the Amazon Kindle). Nothing to do here, these users will never receive push notifications from your app.

Read more: http://eladnava.com/google-cloud-messaging-extremely-unreliable/

These issues alone were enough to get me to start looking for GCM alternatives. I’d get a 1-star review on my app every day or two, with a comment containing the error message displayed when a SERVICE_NOT_AVAILABLE was thrown. There was nothing I could do to help these users, because the majority of them were receiving it for reasons out of their control.

An Alternative to Google Cloud Messaging

Pushy (https://pushy.me/) is a standalone push notification gateway, completely independent of GCM. It maintains its own background socket connection, just like GCM, to receive push notifications. The underlying protocol is MQTT, an extremely light-weight pub/sub protocol, utilizing very little network bandwidth and battery.

A huge advantage of Pushy is that the code for sending a push notification (from the server), and registering the device for push notifications, is actually interchangeable between GCM and Pushy. This makes it super easy to switch to Pushy after implementing GCM and having to ditch it for its instability.

(Full disclosure: I founded Pushy for my own projects and realized many apps would benefit from such a service)

Solution 4

Make sure that you changed the package name in the permissions part of your manifest :

<permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />
<uses-permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE" />

I had a similar error due to an incorrect package name in that part.

Solution 5

For me - the device time wasn't correct. I changed the device settings to use "Automatic date & time", tried again and all good.

Cheers

Share:
82,785
MainstreamDeveloper00
Author by

MainstreamDeveloper00

Updated on June 02, 2020

Comments

  • MainstreamDeveloper00
    MainstreamDeveloper00 almost 4 years

    I encountered a strange problem - I've been using GCM in my application for quite a long time and everything works perfectly. However, before a release to Google Play I changed my application package name from com.android.testapp to com.android.recognition and after this GCM stopped working. At first I got en error GCM sender id not set on constructor and fixed it by overriding getSenderIds(Context context), but now I can't get a registration ID. Here are the messages from logcat: enter image description here

    How can I fix this? When I switched to a new package I changed everything in the manifest file to the new package:

    <receiver
            android:name="com.google.android.gcm.GCMBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
                <category android:name="com.android.recognition" />
            </intent-filter>
        </receiver>
    

    So what is the problem behind this? Can renaming the application package cause this or is there another reason?