I'm trying to learn how to set a client receiver using the google cloud messaging system and i'm following this Google's tutorial: http://developer.android.com/guide/google/gcm/gs.html#android-app
I have done everything that the tutorial asks but when I run my application it works for a moment and then it crashes and this is the LogCat:
08-07 17:04:40.726: E/AndroidRuntime(8155): FATAL EXCEPTION: main
08-07 17:04:40.726: E/AndroidRuntime(8155): java.lang.RuntimeException: Unable to instantiate service com.example.google.cloud.messaging.GCMIntentService: java.lang.ClassNotFoundException: com.example.google.cloud.messaging.GCMIntentService in loader dalvik.system.PathClassLoader[/data/app/com.example.google.cloud.messaging-1.apk]
08-07 17:04:40.726: E/AndroidRuntime(8155): at android.app.ActivityThread.handleCreateService(ActivityThread.java:1933)
08-07 17:04:40.726: E/AndroidRuntime(8155): at android.app.ActivityThread.access$2500(ActivityThread.java:117)
08-07 17:04:40.726: E/AndroidRuntime(8155): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:989)
08-07 17:04:40.726: E/AndroidRuntime(8155): at android.os.Handler.dispatchMessage(Handler.java:99)
08-07 17:04:40.726: E/AndroidRuntime(8155): at android.os.Looper.loop(Looper.java:130)
08-07 17:04:40.726: E/AndroidRuntime(8155): at android.app.ActivityThread.main(ActivityThread.java:3687)
08-07 17:04:40.726: E/AndroidRuntime(8155): at java.lang.reflect.Method.invokeNative(Native Method)
08-07 17:04:40.726: E/AndroidRuntime(8155): at java.lang.reflect.Method.invoke(Method.java:507)
08-07 17:04:40.726: E/AndroidRuntime(8155): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
08-07 17:04:40.726: E/AndroidRuntime(8155): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
08-07 17:04:40.726: E/AndroidRuntime(8155): at dalvik.system.NativeStart.main(Native Method)
08-07 17:04:40.726: E/AndroidRuntime(8155): Caused by: java.lang.ClassNotFoundException: com.example.google.cloud.messaging.GCMIntentService in loader dalvik.system.PathClassLoader[/data/app/com.example.google.cloud.messaging-1.apk]
08-07 17:04:40.726: E/AndroidRuntime(8155): at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:240)
08-07 17:04:40.726: E/AndroidRuntime(8155): at java.lang.ClassLoader.loadClass(ClassLoader.java:551)
08-07 17:04:40.726: E/AndroidRuntime(8155): at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
08-07 17:04:40.726: E/AndroidRuntime(8155): at android.app.ActivityThread.handleCreateService(ActivityThread.java:1930)
This is my code
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
final String regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals("")) {
GCMRegistrar.register(this, "962129210868");
Log.i("Registrando","");
} else {
Log.i("Test", "Already registered");
}
}
}
And this is my Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.google.cloud.messaging"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission
android:name="com.example.google.cloud.messaging.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.google.cloud.messaging.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.example.google.cloud.messaging" />
</intent-filter>
</receiver>
<service android:name="com.example.google.cloud.messaging.GCMIntentService" android:enabled="true"/>
</application>
</manifest>
I have create a new class called GCMIntentService:
public class GCMIntentService extends GCMBaseIntentService {
@SuppressWarnings("hiding")
private static final String TAG = "GCMIntentService";
public GCMIntentService() {
super("Test");
}
@Override
protected void onRegistered(Context context, String registrationId) {
Log.i(TAG, "Device registered: regId = " + registrationId);
}
@Override
protected void onUnregistered(Context context, String registrationId) {
Log.i(TAG, "Device unregistered");
}
@Override
protected void onMessage(Context arg0, Intent arg1) {
Log.d("GCM", "RECIEVED A MESSAGE");
generateNotification(arg0, arg1.getStringExtra("message"));
}
@Override
protected void onDeletedMessages(Context context, int total) {
Log.i(TAG, "Received deleted messages notification");
}
@Override
public void onError(Context context, String errorId) {
Log.i(TAG, "Received error: " + errorId);
}
@Override
protected boolean onRecoverableError(Context context, String errorId) {
// log message
Log.i(TAG, "Received recoverable error: " + errorId);
return super.onRecoverableError(context, errorId);
}
/**
* Issues a notification to inform the user that server has sent a message.
*/
private static void generateNotification(Context context, String message) {
int icon = R.drawable.ic_action_search;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);
String title = context.getString(R.string.app_name);
Intent notificationIntent = new Intent(context, GCMIntentService.class);
// set intent so it does not start a new activity
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent =
PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, title, message, intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, notification);
}
}
You should have GCMIntentService
in the client code and you should define it in the AndroidManifest.xml file as follows.
<service android:name="package_name.GCMIntentService" />
Note that name of the intent service should be exactly same as GCMIntentService
if you use GCMBroadcastReceiver
. You can create your intent service if you implement your broadcast receiver.
I had the same problem. And this problem was solved because you're using GCMIntentService class name as android required. But if you want to rename or put this class to another package, problems come back :) Here the the solution link and source code.
Solution :
We should create receiver and set the name of our custom service to overrided method getGCMIntentServiceClassName.
public class GCMReceiver extends GCMBroadcastReceiver {
@Override
protected String getGCMIntentServiceClassName(Context context) {
return "PCAKAGE_NAME.GCMService";
}
}
Where PCKAGE_NAME is another package name in case of GCMIntentService is in another package.
And don’t forget change receiver name in AndroidManifest.xml too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With