GCM注册 SERVICE_NOT_AVAILABLE

11

这真的让我很烦恼。我有一个使用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次登录,直到它正常工作(并且我有良好的连接)。我的LogCat中的错误是:

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

那么我的代码有什么问题?这让我抓狂。

4个回答

16

我们遇到了同样的问题,即用户第一次无法登录,但无论网络速度如何,在第二或第三次后都可以登录。

我们通过使用Thread.sleep来绕过此问题,并在接收到GCM ID之前重试多次。

  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.sleepnoOfAttemptsAllowed。我们设置了7000毫秒的休眠时间,以便第一次尝试注册的概率更高。然而,如果失败,则下一次尝试将消耗另外7000毫秒。这可能会使用户认为您的应用程序很慢。因此,请巧妙地调整这两个值。


谢谢你的回答。我会尝试一下这个方法。你有没有阅读官方的Google文档或其他相关资料吗?我没看到Google在这个问题上发布过任何官方“帖子”,可这似乎是比较普遍的问题... :s - João Menighin
没有查阅官方文档,但在寻找解决方案时,我们发现在这两行代码之间需要一个睡眠时间。可能是因为GCMRegistrar.register是异步方法。当我们实施了这个解决方案后,“GCM服务不可用”错误就停止出现了。 - ngrashia
我还没有机会测试,但我猜这将是最好的解决方法。如果它不起作用,我会在赏金到期之前标记为正确答案并回来。谢谢Nishanthi :) - João Menighin

5
我遇到了同样的问题。我的问题是我在我的活动的onCreate方法中执行此操作。我发现上下文没有完全实现,导致gcm无法成功注册。我提供了getApplicationContext()以获取GCM实例,这能够解决我的问题。
例子:
使用活动上下文会导致问题。
GoogleCloudMessaging.getInstance(ActivityName.this)

使用应用程序上下文解决了我的问题

GoogleCloudMessaging.getInstance(getApplicationContext())

0

1. 确保 GCMRegister 类中有 googleCloud.register 方法,且在同一包中(AndroidManifest.xml)。

2. 在手机上卸载应用程序。

3. 清理并运行项目。

4. 完成了!


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接