11

This is really annoying me. I have an app that uses GCM. I have people complaining they can't login due to an error. Let me show you how I am making the Login:

// Login Activity
//....
public void onClickLoginButton (View v) {

    // Do some stuff...

    new GCMRegister().execute(); //AsyncTask
}

private class GCMRegister extends AsyncTask<Void, Void, Integer> {

    @Override
    protected Integer doInBackground (Void... params) {
        ConnectivityManager connMgr = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();

        if (networkInfo != null && networkInfo.isConnected()) {
            try {
                //Get GCM Registration key
                registrationId = googleCloud.register(Settings.PROJECT_NUMBER);
            } catch (Exception e) {
                Log.e("GCMRegister", e.toString());
                return -1;
            }
            return 1;
        } else {
            return -3;
        }
    }

    @Override
    protected void onPostExecute(Integer result) {
        if (result == 1) {
            new LoginAsync().execute(); // Another AsyncTask to check in my database if user is valid and save its key
        } else {
            user.setEnabled(true);
            password.setEnabled(true);
            login.setEnabled(true);
            if (result == -1) {
                Toast.makeText(Login.this, "A problem occured login in", Toast.LENGTH_LONG).show();
            } else if (result == -3) {
                Toast.makeText(Login.this, "I need an internet connection", Toast.LENGTH_LONG).show();
            }
        }
    }

So a lot of people is complaining they can't login in because of "A problem occured login" error, which indicates that GCM is failing on register. Even myself with my device, Android 4.4.2, can't do it at first. I need to try to login 2 or 3 times until it works (and Im in a good connection). The error on my LogCat is:

08-04 21:29:10.922: E/GCMRegister(18182): java.io.IOException: SERVICE_NOT_AVAILABLE

So what is wrong with my code? This is driving me nuts.

ngrashia
  • 9,869
  • 5
  • 43
  • 58
João Menighin
  • 3,083
  • 6
  • 38
  • 80

4 Answers4

16

We faced the same issue, where users can't login the first time but can login after say the 2nd or 3rd time irrespective of the network speed.

We did a workaround by using Thread.sleep and retry for a number of times, till the GCM ID is recieved.

  int noOfAttemptsAllowed = 5;   // Number of Retries allowed
  int noOfAttempts = 0;          // Number of tries done
  bool stopFetching = false;     // Flag to denote if it has to be retried or not
  String regId = "";             


  while (!stopFetching) 
  {
       noOfAttempts ++;
       GCMRegistrar.register(getApplicationContext(), "XXXX_SOME_KEY_XXXX");
       try 
       {
          // Leave some time here for the register to be 
          // registered before going to the next line
          Thread.sleep(2000);   // Set this timing based on trial.
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
       try
       {
            // Get the registration ID
            regId = GCMRegistrar.getRegistrationId(LoginActivity.this);
       } catch (Exception e) {}


       if (!regId.isEmpty() || noOfAttempts > noOfAttemptsAllowed)
       {
            // If registration ID obtained or No Of tries exceeded, stop fetching
            stopFetching = true;
        }
        if (!regId.isEmpty())
        {
            // If registration ID Obtained, save to shared preferences
            saveRegIDToSharedPreferences(); 
        }


   }

Note: The Thread.sleep and noOfAttemptsAllowed can be played around with based on your design and other parameters. We had a sleep time of 7000 so that probability of getting registered at first attempt is higher. However, if it fails, the next attempt would consume another 7000ms. This might cause users to think your app is slow. So, play around intelligently with those two values.

ngrashia
  • 9,869
  • 5
  • 43
  • 58
  • Thanks for the answer. I will try this. Have you read some oficial google document on this or anything? I didn't see any official "posts" from google on this issue and it seems kinda common... :s – João Menighin Aug 08 '14 at 11:41
  • Have not gone thru official docs.. But when finding solution for our issue, we identified that a sleep time is required between the two lines of code. Probably because GCMRegistrar.register is an async method. When we implemented this solution, `GCM SERVICE UNAVAILABLE` error stopped occuring. – ngrashia Aug 08 '14 at 14:21
  • I still didnt have the chance to test, but I guess it will be the best workaround. Will mark as the right answer before bounty expires and if it doesn't work I come back. Thanks Nishanthi :) – João Menighin Aug 11 '14 at 11:42
5

I have came across this same issue. My issue was that I was doing it on the onCreate method of my activity. What I discovered was that the context was not fully implemented causing the gcm to not successfully register. I provided getApplicationContext() for obtaining the GCM instance and this was able to resolve my issue.

Example:

Using context of activity caused an issue

GoogleCloudMessaging.getInstance(ActivityName.this)

Using application context resolved my issue

GoogleCloudMessaging.getInstance(getApplicationContext())
shug
  • 134
  • 1
  • 6
0
GoogleCloudMessaging gcm;
String regId;    

private String setGCMModule() {

    if (TextUtils.isEmpty(regId)) {
        regId = registerGCM();
        Log.d("regId", "GCM RegId: " + regId);
    } else {
        Log.e(getApplicationContext() + "",
                "Already Registered with GCM Server!");
    }
    return regId;
}

public String registerGCM() {

    gcm = GoogleCloudMessaging.getInstance(this);
    regId = getRegistrationId(getContext());

    if (TextUtils.isEmpty(regId)) {

        registerInBackground();

        Log.d("RegisterActivity",
                "registerGCM - successfully registered with GCM server - regId: "
                        + regId);
    } else {
        Log.i(getApplicationContext() + "",
                "RegId already available. RegId: " + regId);

    }
    return regId;
}

private String getRegistrationId(Context context) {

    String registrationId = settings.getString(REG_ID, "");
    if (registrationId.isEmpty()) {
        Log.i(TAG, "Registration not found.");
        return "";
    }
    int registeredVersion = settings.getInt(APP_VERSION, Integer.MIN_VALUE);
    int currentVersion = getAppVersion(context);
    if (registeredVersion != currentVersion) {
        Log.i(TAG, "App version changed.");
        return "";
    }
    return registrationId;
}

private static int getAppVersion(Context context) {
    try {
        PackageInfo packageInfo = context.getPackageManager()
                .getPackageInfo(context.getPackageName(), 0);
        return packageInfo.versionCode;
    } catch (NameNotFoundException e) {
        Log.d("RegisterActivity",
                "I never expected this! Going down, going down!" + e);
        throw new RuntimeException(e);
    }
}

private void registerInBackground() {
    new AsyncTask<Void, Void, String>() {
        @Override
        protected String doInBackground(Void... params) {
            String msg = "";
            try {
                if (gcm == null) {
                    gcm = GoogleCloudMessaging.getInstance(getContext());
                }
                regId = gcm.register(Config.GOOGLE_PROJECT_ID);

                storeRegistrationId(getContext(), regId);
            } catch (IOException ex) {
                msg = "Error :" + ex.getMessage();
                Log.d("RegisterActivity", "Error: " + msg);
            }
            Log.d("RegisterActivity", "AsyncTask completed: " + msg);
            return msg;
        }

        @Override
        protected void onPostExecute(String msg) {

            // get new message here

            Log.e(getApplicationContext() + "",
                    "Registered with GCM Server." + msg);
        }
    }.execute(null, null, null);
}

private void storeRegistrationId(Context context, String regId) {

    int appVersion = getAppVersion(context);
    Log.i(TAG, "Saving regId on app version " + appVersion);
    settings.edit();
    editor.putString(REG_ID, regId);
    editor.putInt(APP_VERSION, appVersion);
    editor.commit();

}
Vaishali Sutariya
  • 5,093
  • 30
  • 32
0

1.You make sure class GCMRegister () have method googleCloud.register in same package (AndroidManifest.xml)

2.Uninstall application on mobile.

3.Clean and Run Project.

4.That's Works!!