androidandroid-intentgoogle-cloud-messaginggcmlistenerserviceandroid-unity-plugin

Unity Android Plugin for GCM is Unable to Start Service Intent on Receive


I am currently working on a plugin for unity that will make use of GCM for push notifications and cannot seem to resolve this issue. I followed the steps on the Google Developers site and managed to get the app to register and receive messages from the server. However, once the GcmReceiver gets the message, my logcat outputs the following error:

Unable to start service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x10 pkg=com.test.app.appname (has extras) } U=0: not found

The following is the manifest that i am using for the plugin:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.app.appname">

    <permission android:name="com.test.app.appname.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission android:name="com.test.app.appname.permission.C2D_MESSAGE" />

    <uses-permission android:name="android.permission.WAKE_LOCK" />
	
	 <!-- This app has permission to register and receive data message. -->
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/app_icon"
        android:label="@string/app_name">

        <receiver
            android:name="com.google.android.gms.gcm.GcmReceiver"
            android:exported="true"
            android:permission="com.google.android.c2dm.permission.SEND" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <category android:name="com.test.app.appname" />
            </intent-filter>
        </receiver>
        <service
            android:name="com.test.app.appname.MyGCMListenerService"
            android:exported="false"
            android:enabled="true">
            <intent-filter>
                <action android:name="com.google.android.c2m.intent.RECEIVE" />
            </intent-filter>
        </service>
        <service
            android:enabled="true"
            android:name="com.test.app.appname.MyRegistrationIntentService"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.test.app.appname.GCMREGISTER" />
            </intent-filter>
        </service>
        <activity
            android:name=".AndroidAPI"
            android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"
            android:screenOrientation="sensorLandscape"
            android:label="@string/app_name"
            android:windowSoftInputMode="adjustPan">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:host ="startActivity" android:scheme ="LOHengqa"  />
            </intent-filter>
        </activity>
    </application>
</manifest>

One thing I was wondering was if I needed to create my own custom receiver. From the tutorial at google developers, it appeared that you could use the android.gms.gcm.GcmReceiver and that would trigger the call on your GCMListener. Yet, from what I am experiencing and attempting to debug the code, I do not know if that is right. How exactly is my GCMListenerService being triggered? Am i missing a piece that connects the receiver to the GCMListenerService?

By the way, here is the code for MyGCMListenerService

/**
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.test.app.appname;
import static com.test.app.appname.CommonUtilities.APP_CONTEXT;
import static com.test.app.appname.CommonUtilities._GetString;
import static com.test.app.appname.CommonUtilities._GetDrawable;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.google.android.gms.gcm.GcmListenerService;

public class MyGCMListenerService extends GcmListenerService
{
    private static final String TAG = "MyGCMListService";

    /**
     * Called when message is received.
     *
     * @param from SenderID of the sender.
     * @param data Data bundle containing message data as key/value pairs.
     *             For Set of keys use data.keySet().
     */
    // [START receive_message]
    @Override
    public void onMessageReceived(String from, Bundle data) {
        String message = data.getString("message");
        Log.d(TAG, "From: " + from);
        Log.d(TAG, "Message: " + message);

        if (from.startsWith("/topics/")) {
            // message received from some topic.
        } else {
            // normal downstream message.
        }

        sendNotification(message);
    }
    // [END receive_message]

    /**
     * Create and show a simple notification containing the received GCM message.
     *
     * @param message GCM message received.
     */
    private void sendNotification(String message) {

        final String appId = this.getPackageName();
        long when = System.currentTimeMillis();

        Intent intent = APP_CONTEXT.getPackageManager().getLaunchIntentForPackage(appId);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(_GetDrawable(APP_CONTEXT, "notification_icon"))
                .setContentTitle(_GetString(APP_CONTEXT, "app_name"))
                .setContentText(message)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify((int)(when % 1000), notificationBuilder.build());
    }
}


Solution

  • <service
       android:name="com.test.app.appname.MyGCMListenerService"
       android:exported="false"
        android:enabled="true">
        <intent-filter>
            <action android:name="com.google.android.c2m.intent.RECEIVE" />
        </intent-filter>
    </service>
    

    Specifically, I'm seeing: com.google.android.c2m.intent.RECEIVE which should be com.google.android.c2dm.intent.RECEIVE.

    Seems like if anyone encounters this issue it has to do with the manifest.