GCM register blocks AsyncTask until a timeout occurs

I am trying to get device registration id using GCM. My code for this is contained in AsyncTask, which is called from my main thread.

Main code

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 Class

 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); } } } 

And here is my log dump

 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 

Therefore, for some reason, the call to gcm.register () is blocked until my timeout exception is removed. Does anyone know why this might happen?

+4
source share
2 answers

The reason is that you are running gcm with

 .get(5, TimeUnit.SECONDS); 

This call blocks the flow for 5 seconds, however, due to various reasons, such as an unstable network connection, the registration process may take more than 5 seconds. This is not the best approach to what you want.

Take a look at this example taken from the 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); 

Include this example and everything should work.

+2
source

Using AsyncTask like this does not make sense. AsyncTasks are used to avoid blocking the thread, but by using the get () blocking call, you still block the thread. You can also call register () directly in this case.

You get a timeout because you block 5 seconds, but GCM takes more than 5 seconds to register. This may be due to poor network conditions, as a network request may take some time. Or perhaps it takes just over 5 seconds to get a registration certificate.

+1
source

All Articles