java.io.IOException: SERVICE_NOT_AVAILABLE in GCM Client
C

8

26

I want to implement an gcm client into an existing android app. So, by following this tutorial I wrote following code:

public class RegisterForGCMAsyncTask extends AbstractSecureOperationTask {

...

@Override
protected Boolean doInBackground(String... params) {
    String token = authenticate();
    getRegId();
    if (TextUtils.isEmpty(registrationId)) {
        return false;
    }
    //
    try {
        URL url = convertToURLEscapingIllegalCharacters(String.format(Constants.REGISTER_URL,
                registrationId, userId, token));
        URLConnection connection = url.openConnection();
        InputStreamReader streamReader = new InputStreamReader(connection.getInputStream());
        JSONParser parser = new JSONParser();
        JSONObject rootObj = (JSONObject) parser.parse(streamReader);
        String status = rootObj.get("status").toString();
        if (status.equals("OK")) {
            return true;
        }
    } catch (ParseException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return false;
}

private void getRegId() {
    try {
        if (gcm == null) {
            gcm = GoogleCloudMessaging.getInstance(context);
        }
        registrationId = gcm.register(PROJECT_ID);
    } catch (IOException e) {
        Log.e(LOG_TAG, e.getMessage(), e);
    }
}
}

AndroidMainfest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="de.xxxxxxxx.xxxxxxxx"
      android:versionCode="20140617"
      android:versionName="2.0.0">

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

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>

<permission
        android:name="de.xxxxxxxx.xxxxxxxx.permission.MAPS_RECEIVE"
        android:protectionLevel="signature"/>
<uses-permission android:name="de.xxxxxxxx.xxxxxxxx.permission.MAPS_RECEIVE"/>

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


<!-- Maps API needs OpenGL ES 2.0. -->
<uses-feature
        android:glEsVersion="0x00020000"
        android:required="true"/>

<application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">

    <activity
            android:name="de.retterapps.Handyalarm.views.activities.MainActivity"
            android:configChanges="orientation|screenLayout|screenSize|layoutDirection"
            android:label="@string/app_name"
            android:theme="@style/AppTheme">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>

            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>

    <receiver
            android:name=".helper.gcm.GcmBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND">
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
            <category android:name="de.xxxxxxxx.xxxxxxxx"/>
        </intent-filter>
    </receiver>
    <service android:name=".helper.gcm.GcmMessageHandler"/>

    <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version"/>
    <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="xxxxxxxx"/>
</application>

Yesterday everything worked fine and I could retrieve the registration id. But now, there's always an IOException saying SERVICE_NOT_AVAILABLE.

I tested it on my Samsung Galaxy S5 and in the Genymotion Emulator (Android 4.1.2), but I am getting always the same results. Has anyone an idea how to solve the problem?

Edit

Here's the full stacktrace:

java.io.IOException: SERVICE_NOT_AVAILABLE
    at com.google.android.gms.gcm.GoogleCloudMessaging.register(Unknown Source)
    at de.retterapps.Handyalarm.helper.tasks.RegisterForGCMAsyncTask.getRegId(RegisterForGCMAsyncTask.java:72)
    at de.retterapps.Handyalarm.helper.tasks.RegisterForGCMAsyncTask.doInBackground(RegisterForGCMAsyncTask.java:43)
    at de.retterapps.Handyalarm.helper.tasks.RegisterForGCMAsyncTask.doInBackground(RegisterForGCMAsyncTask.java:24)
    at android.os.AsyncTask$2.call(AsyncTask.java:287)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
    at java.lang.Thread.run(Thread.java:856)
Carditis answered 17/6, 2014 at 12:19 Comment(0)
W
37

Check the time of your device. Google cannot register your device with a wrong time

Whisler answered 17/6, 2014 at 16:53 Comment(10)
The time seems to be correct. The curious thing ist, that it worked yesterday - but now, it is not working ;( Either on real device, nor on the genymotion emulator.Carditis
Do you mean on the test device or another one? On the test device, yes.Carditis
Yes, google play servis is up-to-date on both test devices (real device and emulator). I use google play service 4.4.52.Carditis
Hm, have you tried fully remove application, re-install it and test again?Whisler
Yes, I already tried this. Well, the following discussions says "According to the Google GCM docs, SERVICE_NOT_AVAILABLE indicates the Google servers are busy at the moment and you should try again later". See more here: groups.google.com/forum/#!topic/android-gcm/Skhe3jG5DIg Can this be the problem?Carditis
Probably, but I think there is an issue on client-side, but I can't figure out what issue.. (Whisler
Okay, but I didn't changed anything since yesterday. The only thing I changed, is to reduce the minimum api level from 17 to 15 (but i tried it also with api level 17).Carditis
I've tried this demo - and it works: tausiq.wordpress.com/tag/gcm-client But I don't understand, why my solution doesn't work, it is nearly the same code ;-(Carditis
Yes of course. I've tried it with my sender id given by my client and created a new one - both of them are working well in the demo project, but not on my application ;(Carditis
Without internet you'll also get this exception. Given everything else is working.Careen
C
16

When I encountered this issue what worked for me was to open the Google Play application.

It seems that it must be started at least once after the device restarts before any GCM registration attempt.

Castra answered 18/8, 2014 at 8:53 Comment(1)
That was fine.I tried for two days nothing happens but this works.Great.Nava
R
6

This is a weird one. I solved it by moving the GCM code to the end of my onCreate() method.

My guess is the app Context was not fully created by the time I tried to register for CGM. It needs a valid Context.

Radices answered 2/9, 2014 at 8:7 Comment(1)
i solved problem by adding 10 seconds delay(for complete app loading) and then make GCM request.Fictionist
A
3

SERVICE_NOT_AVAILABLE might also mean, that the device is offline when executing a task:

com.google.android.gms.tasks.RuntimeExecutionException: java.io.IOException: java.util.concurrent.ExecutionException: java.io.IOException: SERVICE_NOT_AVAILABLE

at com.google.android.gms.tasks.zzw.getResult(com.google.android.gms:play-services-tasks@@17.2.1:3)

So this can be solved by not requesting eg. the FCM token, while the device is offline, for example:

@Override
public void onNetworkAvailable() {
    FirebaseMessaging.getInstance().getToken().addOnCompleteListener(task -> {
        Log.d(LOG_TAG, "FCM token: " + task.getResult());
    });
}
Audrit answered 23/10, 2021 at 9:11 Comment(0)
M
1

NativeFirebaseError: [messaging/unknown] java.io.IOException: java.util.concurrent.ExecutionException: java.io.IOException: SERVICE_NOT_AVAILABLE

I know it sounds weird but this error comes up when there's internet connectivity issue on the testing device.

Malenamalet answered 14/1, 2023 at 3:27 Comment(0)
C
0

Yesterday I solved the problem on my own. I followed the demo-application and changed the AsyncTask in the registerInBackground()-Method to a plain java thread. Here's the code:

private void registerInBackground() {
    final Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 0:
                    Toast.makeText(context, getString(R.string.txt_gcm_registered), Toast.LENGTH_LONG).show();
                    break;
                case 1:
                    Toast.makeText(context, getString(R.string.error_register_gcm), Toast.LENGTH_LONG).show();
                    break;
            }
            super.handleMessage(msg);
        }

    };
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            try {
                if (gcm == null) {
                    gcm = GoogleCloudMessaging.getInstance(context);
                }
                regId = gcm.register(Constants.SENDER_ID);

                if (sendRegistrationIdToBackend(regId)) {
                    handler.sendEmptyMessage(0);
                } else {
                    handler.sendEmptyMessage(1);
                }

                storeRegistrationId(context, regId);
            } catch (IOException ex) {
                handler.sendEmptyMessage(1);
                Log.e(LOG_TAG, ex.getMessage(), ex);
            }
        }
    };
    new Thread(runnable).start();
}

Now, it is working, but I don't know why. Can anybody explain the reason? Thanks for your help!

Carditis answered 20/6, 2014 at 15:25 Comment(0)
A
0

If you are running your app in emulator, you must install Google Play Service.

I recently switched to GenyMotion Emulator from Google native emulator and encountered this error. Later I realized GenyMotion image does not come with Google Play Service. After installation, problem solved.

Aliform answered 28/2, 2015 at 6:38 Comment(0)
R
0

also make sure you have internet on your phone!

Ranit answered 25/7, 2022 at 2:45 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.