在某些情况下,在Android中GCM ID不可用的原因是什么

时间:2015-04-19 09:49:21

标签: android google-cloud-messaging

您好我们正在开发一个Android应用程序,其中GCM在营销目的中起着非常重要的作用,将一些重要信息推送给用户等。

它在60-70%的情况下工作正常,但其他30-40%不起作用。因此,其他用户永远不会收到任何仅对他们有用的通知。

这就是我们每天都在失去用户的原因。以下是获取GCM注册ID的代码。

String msg = "";
int exceptionOccurRetry = 0;
while (exceptionOccurRetry < 5) {
    try {
        if (gcm == null) {
            gcm = GoogleCloudMessaging.getInstance(context);
        }
        int retry = 0;
        while (retry < 5 && regid.length() == 0) {
            regid = gcm.register(SENDER_ID);

            ++retry;
        }

        msg = "Device registered, registration ID=" + regid;

        if (!regid.equals("")) {
            // You should send the registration ID to your
            // server
            // over HTTP, so it
            // can use GCM/HTTP or CCS to send messages to your
            // app.
            sendRegistrationIdToBackend();
        }
        break;
    } catch (IOException ex) {
        msg = "Error :" + ex.getMessage();
        exceptionOccurRetry++;
    }
}

我们正在查看某些用户无法使用GCM ID的原因。

我们知道只有一个原因如果用户设备没有在用户手机上安装Google Play服务,那么它就不起作用。

我们正在寻找解决此问题的更多理由。

7 个答案:

答案 0 :(得分:2)

无法使用的最常见原因之一是用户没有安装Google Play服务或使用阻止程序。

您还应注意,如果您的应用程序版本已更改,则应刷新GCM ID。您应该将唯一的设备ID保存到SharedPreferences并始终检查它是否相同,否则您应该再次启动注册过程。

不时刷新id也是一个好主意。

答案 1 :(得分:1)

我们的团队成员正在尝试发送通知,如果失败,他们会等待大约60毫秒或几秒钟(我不确定)再次发送此推送通知,如果它仍然不起作用,他们会等待两次时间,等等...

你必须评估谷歌的回复,下面有一个错误字符串:

std::string error = response["results"][0]["error"].asString();

如果用户帐户已移至,则为您提供信息,如果是,您可以使用:

Json::Value newRegistrationId = response["results"][0]["registration_id"];

获取新ID。

答案 2 :(得分:1)

如果gcm id为null,请尝试启动后台任务并获取id.check以下代码

 private void registerInBackground() {
        new AsyncTask() {
            @Override
            protected String doInBackground(Object[] params) {
                String msg = "";
                try {
                    if (gcm == null) {
                        gcm = GoogleCloudMessaging.getInstance(context);
                    }
                    regid = gcm.register(SENDER_ID);
                    msg = "Device registered, registration ID=" + regid;


                    sendRegistrationIdToBackend();


                    // Persist the regID - no need to register again.
                    storeRegistrationId(context, regid);
                } catch (IOException ex) {
                    msg = "Error :" + ex.getMessage();


                }
                return msg;
            }

            @Override
            protected void onPostExecute(Object msg) {
//                mDisplay.append(msg + "\n");

            }
        }.execute(null, null, null);
    }

答案 3 :(得分:1)

Check if app was updated; if so, it must clear the registration ID since the existing registration ID is not guaranteed to work with the new app version.

当应用程序版本更改时,注册ID也应该更改。所以你应该将最后一个注册ID保存到后端大小。也许你的问题是这个。

答案 4 :(得分:1)

如果你的问题都集中在id注册上,你可以忽略我的答案.. 对不起,我的回答可能是你问题的错误答案。

我只想表明可能还有其他一些因素&#39;影响消息传递..

  1. 您是否仅在单个收件人上发送所有邮件?

      

    GCM最有用的功能之一是支持最多1,000个   单个邮件的收件人。   http://developer.android.com/training/cloudsync/gcm.html#

    有时我们的PHP也会丢失发送到注册设备的消息......

  2. 消息必须小于4K(GCM是否包含图片?)

  3. 您可能已经读过这个..

      

    在Android上实施GCM客户端

         

    http://developer.android.com/google/gcm/client.html

答案 5 :(得分:1)

asyncTask中的那段代码是否可能是某个版本中的错误(不记得是哪个)gcm注册由于某种原因给出了NetworkOnMainThreadException,他们稍后更新了但是我前段时间遇到了同样的问题,这是我用过的一段代码希望它可以帮助你:

private void performRegisterGCM(){
    //Check for GCM availability
    if(checkPlayServices(this)){
        // If this check succeeds, proceed with normal processing.
        // Otherwise, prompt user to get valid Play Services APK.
        gcm = GoogleCloudMessaging.getInstance(this);
        String regId = mPreferences.getGcmRegistrationId();
        if (regId.isEmpty()){
            RegisterGCM();
        }else{
            log.d("regId: "+regId);
        }
    } else {
        // Status is a random integer
        GooglePlayServicesUtil.getErrorDialog(status, this, RQS_GooglePlayServices).show();
    }
}

public static boolean checkPlayServices(Activity mActivity){
    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mActivity);
    return resultCode == ConnectionResult.SUCCESS
}

 private void RegisterGCM(){
    new AsyncTask<Void,Void,String>() {
        @Override
        protected String doInBackground(Void... params) {
            String regid = "";
            try{
                if (gcm == null) {
                    gcm = GoogleCloudMessaging.getInstance(mContext);
                }
                regid = gcm.register(Util.SENDER_ID);
            }catch(Exception e){
                log.e(e.getMessage());
            }
            return regid;
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            mPreferences.setGcmRegistrationId(s);
            //TODO send regid to server with all the other info
            sendGCMIDtoBackend(s);
        }
    }.execute(null, null, null);
}

请注意,checkPlayServices也给了我很多问题:

public static boolean checkPlayServices(Activity mActivity){
    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mActivity);
    if(resultCode!= ConnectionResult.SUCCESS) {
        if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)){
            GooglePlayServicesUtil.getErrorDialog(
                    resultCode,
                    mActivity,
                    PLAY_SERVICES_RESOLUTION_REQUEST
            ).show();
        } else{
            log.d("DEVICE NOT SUPPORTED");
            exit(true);
        }
        return false;
    }
    return true;
}

然后在第一段代码中看到它就改变了,因为出于某种原因,当它出现在isUserRecoverableError(结果)中时,它会带来很多麻烦...... 这里的一切都来自一个实际的工作项目代码段在 http://developer.android.com/google/gcm/client.html 中获得并修改为正常工作。希望这可以帮助您,祝您好运......

答案 6 :(得分:1)

How about the backend? If you delete the ID from the server's database, the user will never receive a notification unless you update the app version?