GCM寄存器阻止AsyncTask直到超时发生

时间:2015-07-28 20:16:05

标签: java android android-asynctask google-cloud-messaging

我试图通过GCM获取设备注册ID。我这样做的代码包含在从我的主线程调用的AsyncTask中。

主要代码

try
{
    String deviceId = new Gcm().execute(this.activity).get(5, TimeUnit.SECONDS);

    Log.i("Login", "User device id returned as " + deviceId);
    return deviceId;
}
catch (Exception e)
{
    Log.e("Login", "Exception", e);
}

GCM课程

public class Gcm extends AsyncTask<Activity,Void,String>
{

@Override
protected String doInBackground(Activity... params)
{
    Log.i("GCM", "Attempting to get device id");
    Activity activity = params[0];
    try
    {
        Log.i("GCM", "Getting GCM instance");
        GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(activity.getApplicationContext());

        Log.i("GCM", "Registering with GCM");

        String regId = gcm.register(PROJECT_NUMBER);

        Log.i("GCM",  "Device registered, registration ID=" + regId);

        return regId;
    }
    catch (IOException e)
    {
        throw new IllegalStateException(e);
    }
}
}

这是我的日志转储

07-28 13:07:39.093  I/GCM﹕ Attempting to get device id
07-28 13:07:39.093  I/GCM﹕ Getting GCM instance
07-28 13:07:39.093  I/GCM﹕ Registering with GCM
07-28 13:07:44.103  E/Login﹕ Exception
    java.util.concurrent.TimeoutException
        at java.util.concurrent.FutureTask.get(FutureTask.java:176)
        at android.os.AsyncTask.get(AsyncTask.java:507)
I/GCM﹕ Device registered, registration ID=XXXXXX

因此,出于某种原因,调用gcm.register()会阻塞,直到我的超时异常被命中。有谁知道为什么会发生这种情况?

2 个答案:

答案 0 :(得分:2)

原因是你用

执行gcm
.get(5, TimeUnit.SECONDS); 

此调用会阻塞线程5秒,但由于网络连接不稳定等原因,注册过程可能需要5秒以上。这不是做你想做的最好的方法。

看看这个例子,取自official GCM demo

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

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

                // For this demo: we don't need to send it because the device will send
                // upstream messages to a server that echo back the message using the
                // 'from' address in the message.

                // Persist the regID - no need to register again.
                storeRegistrationId(context, regid);
            } catch (IOException ex) {
                msg = "Error :" + ex.getMessage();
                // If there is an error, don't just keep trying to register.
                // Require the user to click a button again, or perform
                // exponential back-off.
            }
            return msg;
        }

        @Override
        protected void onPostExecute(String msg) {
            mDisplay.append(msg + "\n");
        }
    }.execute(null, null, null);

合并这个例子,一切都应该有效。

答案 1 :(得分:1)

使用像这样的AsyncTask是没有意义的。 AsyncTasks用于避免阻塞线程,但是通过使用阻塞get()调用,无论如何都阻塞了线程。在这种情况下,你也可以直接调用register()。

您正在暂停,因为您已经阻止5秒,但GCM的注册时间超过5秒。这可能是由于网络状况不佳,因为网络请求超时可能需要一段时间。或者可能只需要5秒以上就可以获得注册ID。