java - GCM 注册阻塞 AsyncTask 直到发生超时

标签 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() 一直处于阻塞状态,直到我的超时异常被命中。有谁知道为什么会发生这种情况?

最佳答案

原因是因为你正在执行 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);

结合这个例子,一切都应该工作。

关于java - GCM 注册阻塞 AsyncTask 直到发生超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31686227/

相关文章:

java - 如何使用 Robolectric 测试 AsyncTask?

java - AsyncTask 完成后执行操作

java - URL 连接 : how to get body returned with status ! = 200?

Java8 FileSystems.getDefault 抛出 UnsupportedCharsetException

java - 如何在 Spring Boot 中更改允许的 header

java - 如何从另一个事件 Android Studio 中获取数据对象

java - 'System services not available to Activities before onCreate()' 出现问题

java - 无法使用 getGraphics() 方法一次性加载图像

java - 如何修复 Timertask 只运行一次?

android - ListFragment 中没有加载圆圈