Robin
Robin

Reputation: 709

java.io.IOException: SERVICE_NOT_AVAILABLE in GCM Client

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)

Upvotes: 26

Views: 34174

Answers (8)

Aditya Singh
Aditya Singh

Reputation: 107

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.

Upvotes: 1

Ali80
Ali80

Reputation: 8626

also make sure you have internet on your phone!

Upvotes: 0

Martin Zeitler
Martin Zeitler

Reputation: 76569

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

Upvotes: 3

sishuo yang
sishuo yang

Reputation: 3

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.

Upvotes: 0

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.

Upvotes: 6

Tom Susel
Tom Susel

Reputation: 3437

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.

Upvotes: 16

Robin
Robin

Reputation: 709

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!

Upvotes: 0

Nickolai Astashonok
Nickolai Astashonok

Reputation: 2888

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

Upvotes: 37

Related Questions