Reputation: 23
I'm having a problem with the Google Cloud to Device messaging example. I'm following the instructions here(https://github.com/GoogleCloudPlatform/gradle-appengine-templates/tree/master/GcmEndpoints) as this was the instructions given by Android Build when I created the project. As per the instructions I've created the required classes to register and receive messages. The register was created as an AsyncTask and called from the OnCreate method of my Main App. The problem I have is every time it runs I get an IOException: MAIN THREAD. I tried changing the code to a Runnable to no luck I just get the same error. Everything I've read in the Documentation, says that what I've done should work, so I can't understand why its not.
Below is a Logcat dump showing the error and stack trace
10-19 13:04:21.637 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ java.io.IOException: MAIN_THREAD 10-19 13:04:21.637 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at com.google.android.gms.gcm.GoogleCloudMessaging.register(Unknown Source) 10-19 13:04:21.647 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at com.hillbilly.kidslauncher.GcmRegistrationAsyncTask.doInBackground(GcmRegistrationAsyncTask.java:75) 10-19 13:04:21.647 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at com.hillbilly.kidslauncher.MainActivity.onCreate(MainActivity.java:43) 10-19 13:04:21.657 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at android.app.Activity.performCreate(Activity.java:5008) 10-19 13:04:21.657 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079) 10-19 13:04:21.667 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023) 10-19 13:04:21.667 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084) 10-19 13:04:21.677 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at android.app.ActivityThread.access$600(ActivityThread.java:130) 10-19 13:04:21.677 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195) 10-19 13:04:21.677 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at android.os.Handler.dispatchMessage(Handler.java:99) 10-19 13:04:21.687 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at android.os.Looper.loop(Looper.java:137) 10-19 13:04:21.687 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at android.app.ActivityThread.main(ActivityThread.java:4745) 10-19 13:04:21.697 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at java.lang.reflect.Method.invokeNative(Native Method) 10-19 13:04:21.697 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at java.lang.reflect.Method.invoke(Method.java:511) 10-19 13:04:21.707 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 10-19 13:04:21.707 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 10-19 13:04:21.717 1291-1291/com.hillbilly.kidslauncher W/System.err﹕ at dalvik.system.NativeStart.main(Native Method)
Any help great fully received.
As requested here is the relevant code:
the onCreate Method from the main Activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_main);
new GcmRegistrationAsyncTask().doInBackground(this);
}
The Registration Class
package com.hillbilly.kidslauncher;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;
import com.appspot.kidslauncherparent.registration.Registration;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.extensions.android.json.AndroidJsonFactory;
import com.google.api.client.googleapis.services.AbstractGoogleClientRequest;
import com.google.api.client.googleapis.services.GoogleClientRequestInitializer;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Created by craighillbeck on 19/10/2014.
*/
public class GcmRegistrationAsyncTask extends AsyncTask<Context, Void, String> {
private GoogleCloudMessaging gcm;
private Context context;
private Registration regService = null;
// TODO: change to your own sender ID to Google Developers Console project number, as per instructions above
private static final String SENDER_ID = "978823093525";
/**
* Override this method to perform a computation on a background thread. The
* specified parameters are the parameters passed to {@link #execute}
* by the caller of this task.
* <p/>
* This method can call {@link #publishProgress} to publish updates
* on the UI thread.
*
* @param params The parameters of the task.
*
* @return A result, defined by the subclass of this task.
*
* @see #onPreExecute()
* @see #onPostExecute
* @see #publishProgress
*/
@Override
protected String doInBackground(Context... params) {
context = params[0];
if (regService == null) {
Registration.Builder builder = new Registration.Builder(
AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
// Need setRootUrl and setGoogleClientRequestInitializer only for local testing,
// otherwise they can be skipped
.setRootUrl("http://10.0.2.2:8080/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
@Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest)
throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
// end of optional local run code
builder.setApplicationName(context.getString(R.string.app_name));
regService = builder.build();
}
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
String 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.
// The request to your server should be authenticated if your app
// is using accounts.
regService.register(regId).execute();
} catch (IOException ex) {
ex.printStackTrace();
msg = "Error: " + ex.getMessage();
}
return msg;
}
/**
* <p>Runs on the UI thread after {@link #doInBackground}. The
* specified result is the value returned by {@link #doInBackground}.</p>
* <p/>
* <p>This method won't be invoked if the task was cancelled.</p>
*
* @param msg The result of the operation computed by {@link #doInBackground}.
*
* @see #onPreExecute
* @see #doInBackground
* @see #onCancelled(Object)
*/
@Override
protected void onPostExecute(String msg) {
Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
Logger.getLogger("REGISTRATION").log(Level.INFO, msg);
}
}
Upvotes: 1
Views: 2771
Reputation: 393821
That's not how you execute a background task in the background. Simply calling the doInBackGround()
method executes this method in the same (main) thread, which causes your execption.
new GcmRegistrationAsyncTask().doInBackground(this);
The right way is :
new GcmRegistrationAsyncTask().execute(null,null,null);
Here's an example 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);
}
Upvotes: 2