Регистрация GCM SERVICE_NOT_AVAILABLE

Это действительно раздражает меня. У меня есть приложение, которое использует GCM. У меня есть люди, жалующиеся, что они не могут войти из-за ошибки. Позвольте мне показать вам, как я делаю вход:

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

Таким образом, многие люди жалуются, что не могут войти в систему из-за ошибки "Ошибка при регистрации", что указывает на то, что GCM не работает в регистре. Даже я с моим устройством Android 4.4.2 не может сделать это сначала. Мне нужно попытаться войти в систему 2 или 3 раза, пока это не сработает (и Im в хорошей связи). Ошибка в моем LogCat:

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

Так что же случилось с моим кодом? Это сводит меня с ума.

Ответ 1

Мы столкнулись с той же проблемой, когда пользователи не могут войти в систему в первый раз, но могут войти в систему после 2-го или 3-го времени независимо от скорости сети.

Мы сделали обходной путь, используя Thread.sleep и повторив несколько раз, до получения идентификатора GCM.

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


   }

Примечание. Thread.sleep и noOfAttemptsAllowed можно воспроизводить на основе вашего дизайна и других параметров. У нас было время сна 7000, так что вероятность регистрации при первой попытке выше. Однако, если это не удастся, следующая попытка будет потреблять еще 7000 мс. Это может заставить пользователей думать, что ваше приложение работает медленно. Итак, играйте разумно с этими двумя значениями.

Ответ 2

Я столкнулся с этой проблемой. Моя проблема заключалась в том, что я делал это по методу onCreate моей деятельности. Я обнаружил, что контекст не был полностью реализован, и gcm не удалось зарегистрировать. Я предоставил getApplicationContext() для получения экземпляра GCM, и это позволило решить мою проблему.

Пример:

Использование контекста активности вызвало проблему

GoogleCloudMessaging.getInstance(ActivityName.this)

Использование контекста приложения разрешило мою проблему

GoogleCloudMessaging.getInstance(getApplicationContext())

Ответ 3

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

}

Ответ 4

1. Убедитесь, что класс GCMRegister() имеет метод googleCloud.register в том же пакете  (AndroidManifest.xml)

2.Установить приложение на мобильном устройстве.

3. Очистите и запустите проект.

4.Что работает!!