blavi
blavi

Reputation: 531

GCM getToken() sends java.io.IOException: TIMEOUT

I am implementing push notifications, but I receive TIMEOUT exception when calling getToken.

I've set the app for GCM here and SENDER_ID is exactly the one provided. Also, Server API key was saved on the backend part.

Is there a limited number of getToken requests? I had no problems at first several attempts when testing push notifications.

new AsyncTask<Void, Void, Void>(){

        @Override
        protected Void doInBackground(Void... params) {
            try {

                InstanceID instance = InstanceID.getInstance(mContext);

                String registrationId = instance.getToken(Constants.GCM_SENDER_ID,
                        GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

                SharedPreferences sp = mContext.getSharedPreferences(Constants.TOKEN_DATA, Context.MODE_PRIVATE);
                SharedPreferences.Editor editor = sp.edit();
                editor.putString(Constants.REGISTRATION_ID, registrationId);
                editor.commit();

                NotificationsRegister.getInstance(mContext).register(registrationId);
            } catch(IOException e) {
                e.printStackTrace();
            }

            return null;
        }
    }.execute();

Android Manifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myexample" >

<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET"/>
<permission android:name="com.myexample.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />
<uses-permission android:name="com.myexample.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

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

    <receiver
        android:name="com.google.android.gms.gcm.GcmReceiver"
        android:exported="true"
        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.myexample" />
        </intent-filter>
    </receiver>
    <service
        android:name=".helper.TutoriaGcmListenerService"
        android:exported="false" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        </intent-filter>
    </service>
    <service
        android:name=".helper.TutoriaInstanceIDListenerService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.android.gms.iid.InstanceID"/>
        </intent-filter>
        </service> 
...

Dependencies added to Module's build.gradle:

Dependencies added to project's build.gradle:

Upvotes: 6

Views: 5103

Answers (4)

Javi AP
Javi AP

Reputation: 452

It's possible that Play Services are not available before registering, this class may help you:

public class PlayServicesValidator {


private static final String TAG = PlayServicesValidator.class.getSimpleName();
private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;


/**
 * Check the device to make sure it has the Google Play Services APK. If
 * it doesn't, display a dialog that allows users to download the APK from
 * the Google Play Store or enable it in the device's system settings.
 */
public static boolean areAvailable(Context context) {
    GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
    int resultCode = apiAvailability.isGooglePlayServicesAvailable(context);
    if (resultCode != ConnectionResult.SUCCESS) {
        return false;
    }
    return true;
}


/**
 * Only call if areAvailable was previously called and returned false
 * @param activity
 * @return
 */
public static boolean areRecoverable(Activity activity) {
    GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
    int resultCode = apiAvailability.isGooglePlayServicesAvailable(activity);
    if (resultCode != ConnectionResult.SUCCESS) {
        if (apiAvailability.isUserResolvableError(resultCode)) {
            return true;
        } else {
            return false;
        }
    }
    return true;
}


/**
 * Shows to the user a dialog to update play services
 * @param activity
 */
public static void recover(Activity activity) {
    GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
    int resultCode = apiAvailability.isGooglePlayServicesAvailable(activity);
    if (resultCode != ConnectionResult.SUCCESS) {
        if (apiAvailability.isUserResolvableError(resultCode)) {
            apiAvailability.getErrorDialog(activity, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST).show();
        }
    }
}
}

Upvotes: 0

David
David

Reputation: 150

Before the registration you must check if google api is available with this fragment of code or similar:

GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
    int resultCode = apiAvailability.isGooglePlayServicesAvailable(a);
    if (resultCode == ConnectionResult.SUCCESS) { //Do the getTokencall  } else { //check the code }

Probably you are not receiving the SUCCESS resultCode. For example if there is a pending update of google api.

Upvotes: 2

Zephyr
Zephyr

Reputation: 6351

I had this problem and got fixed after trying again.

Upvotes: 0

akousmata
akousmata

Reputation: 1043

I ran into this problem today and here's what I did to troubleshoot.

First, I also was using my own sender ID when attempting to get the token. So instead, I tried using the sender ID from the examples Google provides getString(R.id.gcm_defaultSenderId)

Once I did this, I started to get a different error message SERVICE_NOT_AVAILABLE

There are several SO questions that address this, but the one that helped me out was this one.

I turned off WiFi and used a 4G connection on my phone and it worked with both the gcm_defaultSenderId and my own sender ID.

Upvotes: 3

Related Questions