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

12
我正在尝试在我的Android应用程序中使用GCM实现推送通知。我成功创建了一个服务器来向设备推送消息,并成功创建了一个API来将设备令牌存储在服务器上。根据链接中的示例项目,在应用程序中创建了一个客户端。还创建了一个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>

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


1
我刚遇到了同样的问题。但是,我没有收到警告W/GcmNotification﹕ Failed to show notification: Missing icon。你能否展示一下你发送给GCM的内容(包括curl请求)? - peshkira
你是在使用Android API 21的设备上进行测试吗?setColor是在21版本中添加的,看起来有些库仍然使用Notification而不是NotificationCompat。 - Koh
1
尝试实施@rohitsakala建议的更改,并从SDK管理器更新您的支持库、库和播放服务。希望这可以帮助到您。 - Koh
感谢@peshkira的回复。rohitsakala的解决方案解决了问题。在服务器中添加图标后,推送通知到设备时我收到了通知。 - Mahendran Sakkarai
3个回答

12
根据这个链接,您应该有图标的键值对。
请检查通知负载的图标参数。它被指定为必需的。
因此,您必须在JSON中包含一个图标。
例如:
{
    "to":   
"ci4ZzC4BW....",  
    "notification": {  
        "title": "Testing",  
        "body": "Success",  
        "icon": "@drawable/myicon"  
    }  
}

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

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

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

感谢@rohitsakala。你解决了我问题的一半。在我像上面那样改为json后,我收到了通知,但是在接收通知时函数onMessageReceived没有被调用。你知道为什么吗?如果我得到上述问题的答案,我会将其接受为答案。 - Mahendran Sakkarai
1
@Mahendran,你需要将上面的JSON通知更改为数据,以便调用onMessageReceived!例如:{ "to":
"ci4ZzC4BW....",
"data": {
"title": "测试",
"body": "成功",
"icon": "@drawable/myicon"
}
}然后,您可以通过通知构建器构建您的通知!
- rohitsakala
1
到处都找了,但这个答案正中要害!是的,每个通知都需要有一个图标!非常感谢! - Christian Tjhai

0

虽然这是一个旧的线程,但我想基于我遇到的一些类似问题添加一些内容。

应用程序有两种状态:活动非活动

如果应用程序处于活动状态,则发送没有图标通知(我怀疑仍然需要键)仍将起作用。对我有效,但键仍在那里。

我的JSON对象如下所示:

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

来自开发者文档:

对于一个活跃的Android应用程序,通知负载将在数据包中的通知键下传递到onMessageReceived()。

当应用程序处于非活动状态时:

通知在应用程序处于非活动状态时传递到通知托盘。

这就是我遇到“缺少图标”问题的原因。因此,如果应用程序处于非活动状态,则需要一个键值对。

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

请参阅此处获取详细信息

最后,在应用程序的设计中,应清楚区分“通知”和“数据”的含义。我一直在使用“通知”来处理我的应用程序的所有推送消息,但我认为这不是正确的做法。


0

我遇到了同样的问题

查看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级别21”中添加的,这意味着此方法仅适用于5.0(棒棒糖)以上版本。

我尝试了下面的结构,在两个不同的操作系统设备上进行了测试,分别是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仍然没有被调用。

数据负载中没有特定的颜色,因此考虑到它是可选的,这不应该会引起问题吧?我也遇到了同样的问题,但需要支持Jellybean和更高版本。 - John Mc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接