我试图通过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()会阻塞,直到我的超时异常被命中。有谁知道为什么会发生这种情况?
答案 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。