在 GCM 客户端上接收推送通知的问题

Issue on receiving push notification on the GCM Client

我正在尝试在我的 Android 应用程序中使用 GCM 实现推送通知。我创建了一个服务器来成功地将消息推送到设备,还创建了一个 api 来成功地将设备令牌存储在服务器中。在 link based on the sample project 中提到的应用程序中创建了一个客户端。并且还在 php 中创建了一个函数来将通知推送到应用程序。当我 运行 在服务器中运行该功能时,我得到的响应是成功的。这意味着消息从 gcm 发送到移动设备。但是通知没有显示,而是我在日志 cat 中得到以下内容。

06-05 14:58:59.172  23693-28001/com.greenboards.base I/dalvikvm﹕ Could not find method android.app.Notification$Builder.setColor, referenced from method com.google.android.gms.gcm.zza.zzv
06-05 14:58:59.172  23693-28001/com.greenboards.base W/dalvikvm﹕ VFY: unable to resolve virtual method 184: Landroid/app/Notification$Builder;.setColor (I)Landroid/app/Notification$Builder;
06-05 14:58:59.173  23693-28001/com.greenboards.base D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x0068
06-05 14:58:59.175  23693-28001/com.greenboards.base W/GcmNotification﹕ Failed to show notification: Missing icon

为了捕获消息,我使用了在示例应用程序中表示的相同侦听器服务(我在下面添加以供参考)。所以我想到了通知管理器中的问题。所以我将其注释掉并 运行 应用程序。但是我再次收到相同的回复而没有任何通知。不知道是什么问题

package com.greenboards.base;

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.greenboards.base.R;

import com.google.android.gms.gcm.GcmListenerService;
import com.greenboards.base.SplashScreen;

public class MyGcmListenerService extends GcmListenerService {

    private static final String TAG = "MyGcmListenerService";

    /**
     * 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);

        /**
         * Production applications would usually process the message here.
         * Eg: - Syncing with server.
         *     - Store message in local database.
         *     - Update UI.
         */

        /**
         * In some cases it may be useful to show a notification indicating to the user
         * that a message was received.
         */
        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) {
        /*Intent intent = new Intent(this, SplashScreen.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 *//* Request code *//*, intent,
                PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_stat_ic_notification)
                .setContentTitle("GCM Message")
                .setContentText(message)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager.notify(0 *//* ID of notification *//*, notificationBuilder.build());*/
        Log.v("notification message",message);
    }
}

但是只要从服务器接收到消息,onMessageReceived 就必须在上面的侦听器中调用。在 onMessageReceived 函数中有两个日志函数来显示消息和发件人。那也没有执行。这意味着函数本身没有执行。下面我添加了清单内容。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.greenboards.base"
    android:versionCode="1"
    android:versionName="1.0">

    <uses-sdk
        android:minSdkVersion="9"
        android:targetSdkVersion="19" />

    <!-- Application Permissions -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

    <permission
        android:name="com.greenboards.base.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />

    <uses-permission android:name="com.greenboards.base.permission.C2D_MESSAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.VIBRATE" />

    <!-- Application Configuration and Activities -->
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity android:name=".SplashScreen">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- [START gcm_receiver] -->
        <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.greenboards.base" />
            </intent-filter>
        </receiver>
        <!-- [END gcm_receiver] -->

        <!-- [START gcm_listener] -->
        <service
            android:name="com.greenboards.base.MyGcmListenerService"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            </intent-filter>
        </service>
        <!-- [END gcm_listener] -->
        <!-- [START instanceId_listener] -->
        <service
            android:name="com.greenboards.base.MyInstanceIDListenerService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.android.gms.iid.InstanceID"/>
            </intent-filter>
        </service>
        <!-- [END instanceId_listener] -->
        <service
            android:name="com.greenboards.base.RegistrationIntentService"
            android:exported="false">
        </service>

    </application>
</manifest>

现在我仍然无法调试问题所在。我做错了什么还是遗漏了什么?

根据这个 link 你应该有 key/value 对图标。

检查通知负载的图标参数。按需指定。

因此,您必须在 JSON 中包含一个图标。

一个例子可能是

{
    "to":   
"ci4ZzC4BW....",  
    "notification": {  
        "title": "Testing",  
        "body": "Success",  
        "icon": "@drawable/myicon"  
    }  
}

myicon 是应用程序 drawable 文件夹中名为 myicon.png 的图像。

onMessageReceived 在收到带有 data 负载的消息时调用。当我们在上面的 json 中将 notification 更改为 data(如下所示)时,将调用 onMessageReceived 函数。

{
    "to":   
"ci4ZzC4BW....",  
    "data": {  
        "title": "Testing",  
        "body": "Success",  
        "icon": "@drawable/myicon"  
    }  
}

我遇到了同样的问题

查看logcat中的信息:

dalvikvm﹕ Could not find method android.app.Notification$Builder.setColor, referenced from method com.google.android.gms.gcm.zza.zzv

dalvikvm﹕ VFY: unable to resolve virtual method 173: Landroid/app/Notification$Builder;.setColor (I)Landroid/app/Notification$Builder;

并参考 API 文档: http://developer.android.com/reference/android/app/Notification.Builder.html

搜索"setColor"会发现在"API level 21"中添加了,表示此方法只对5.0(Lollipop)以上有效

我在 2 个不同的 OS 设备上尝试了下面的结构,分别是 5.0 和 4.4,但只适用于 5.0

{"to": "/topics/global","data": {"message": "<message>"},"notification": {"icon": "ic_stat_ic_notification","body": "Use Gradle Command","title": "Self test"}}

注意: 我在 OS 5.0 上使用 JSON 测试,显示了通知,但仍然没有调用 onMessageReceived

虽然是旧线程,但我想根据我遇到的一些类似问题对此进行补充。

应用有两种状态:活跃不活跃

如果应用程序处于活动状态,发送 notification 没有图标 value(我怀疑仍然需要密钥)仍然有效。对我有用,但钥匙还在里面。

我的 JSON 对象如下所示:

.., icon=, sound=default, title=Bruce...

来自开发者文档:

For an active Android app, notification payloads are passed to onMessageReceived() under the notification key in the data bundle.

应用处于非活动状态时:

Notifications are delivered to the notification tray when the app is inactive.

这是我遇到 Missing icon 问题的时候。因此,如果应用处于非活动状态,则需要键值对。

如果负载是通知,请确保它始终具有 icon key/value 对,以便无论应用程序处于活动状态还是非活动状态,它都能按预期工作。

See here for details

最后,在应用程序的设计中,notificationdata 之间应该有明确的区别。我一直在为我的应用程序的所有推送消息使用 notification,我认为这不是正确的做法。