Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.lang.RuntimeException: Unable to instantiate service .GCMIntentService

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>

FIXED

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

}
like image 225
Matteo Cardellini Avatar asked Aug 07 '12 15:08

Matteo Cardellini


2 Answers

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.

like image 196
Parvin Gasimzade Avatar answered Dec 05 '22 14:12

Parvin Gasimzade


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.

like image 41
dexxtr Avatar answered Dec 05 '22 14:12

dexxtr