GCM返回了一个空的消息类型。

8
我创建了一个应用程序,使用GoogleCloudMessaging。 应用程序可以注册到gcm并将其注册ID存储到我的服务器上的数据库中。 我正在使用php发送推送通知,但当谷歌将其发送到我的设备时,意图服务发现其消息类型为空。 我在另一个应用程序中尝试了相同的代码,并且它运行良好。 但是这次不行。 应用程序可以从谷歌获取消息,并通过显示一个空文本的通知来处理它。 我在下面提供了意图服务和php代码。 感谢您的答案。
send_message.php
<?php
if (isset($_GET["regId"]) && isset($_GET["message"])) {
$regId = $_GET["regId"];
$message = $_GET["message"];

include_once './GCM.php';

$gcm = new GCM();

$registatoin_ids = array($regId);
$message = array("price" => $message);

$result = $gcm->send_notification($registatoin_ids, $message);

echo $result;
}
?>

GCM.php

<?php

class GCM {

//put your code here
// constructor
function __construct() {

}

/**
 * Sending Push Notification
 */
public function send_notification($registatoin_ids, $message) {
    // include config
    include_once './config.php';

    // Set POST variables
    $url = 'https://android.googleapis.com/gcm/send';

    $fields = array(
        'registration_ids' => $registatoin_ids,
        'data' => $message,
    );

    $headers = array(
        'Authorization: key=' . GOOGLE_API_KEY,
        'Content-Type: application/json'
    );
    // Open connection
    $ch = curl_init();

    // Set the url, number of POST vars, POST data
    curl_setopt($ch, CURLOPT_URL, $url);

    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    // Disabling SSL Certificate support temporarly
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));

    // Execute post
    $result = curl_exec($ch);
    if ($result === FALSE) {
        die('Curl failed: ' . curl_error($ch));
    }

    // Close connection
    curl_close($ch);
    echo $result;
    }

}

?>

MyIntentService.java

public class MyIntentService extends IntentService {

public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;

public MyIntentService() {
    super("MyIntentService");
}

@Override
protected void onHandleIntent(Intent intent) {
    Log.v(MainActivity.TAG, "Handling intent.");
    Bundle extras = intent.getExtras();
    GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
    // The getMessageType() intent parameter must be the intent you received
    // in your BroadcastReceiver.
    String messageType = gcm.getMessageType(intent);
    generateNotification(getApplicationContext(), extras.getString("price"));
    Log.v(MainActivity.TAG, "IntentService messagetype= " + messageType);
    if (!extras.isEmpty()) {  // has effect of unparcelling Bundle
        /*
         * Filter messages based on message type. Since it is likely that GCM will be
         * extended in the future with new message types, just ignore any message types   
         * not interested in, or that you don't recognize.
         */
        if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
            sendNotification("Send error: " + extras.toString());
        } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
            sendNotification("Deleted messages on server: " + extras.toString());
        // If it's a regular GCM message, do some work.
        } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
            // This loop represents the service doing some work.
//                for (int i = 0; i < 5; i++) {
//                    Log.i(TAG, "Working... " + (i + 1)
//                            + "/5 @ " + SystemClock.elapsedRealtime());
//                    try {
//                        Thread.sleep(5000);
//                    } catch (InterruptedException e) {
//                    }
//                }
            Log.i(MainActivity.TAG, "Completed work @ " +SystemClock.elapsedRealtime());
            // Post notification of received message.
            sendNotification("Received: " + extras.toString());
            generateNotification(getApplicationContext(),
"Received:" + extras.getString("price"));
            Log.i(MainActivity.TAG, "Received: " + extras.toString());
        }
    }
    // Release the wake lock provided by the WakefulBroadcastReceiver.
    WakefulBroadcastReceiver.completeWakefulIntent(intent);
}

简而言之,“Log.v(MainActivity.TAG,“IntentService messagetype =” + messageType);”显示“IntentService messagetype = null”。我该如何解决这个问题?
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    // Explicitly specify that GcmIntentService will handle the intent.
    ComponentName comp = new ComponentName(context.getPackageName(),
            GcmIntentService.class.getName());
    // Start the service, keeping the device awake while it is launching.
    startWakefulService(context, (intent.setComponent(comp)));
    setResultCode(Activity.RESULT_OK);
}
}

请发布触发意图服务的广播接收器代码。也许您正在向意图服务传递错误的意图。我建议您尝试在广播接收器中打印消息类型,以查看是否也为空。 - Eran
这里,我发布了广播接收器。 - Mert Karatas
我认为我的清单文件没有问题,因为应用程序可以注册自己并处理传入的推送通知。问题是每次消息都为空。 - Mert Karatas
1
有什么解决方案吗?我遇到了类似的问题。 - SaKet
@MertKaratas,你有找到任何解决方案吗? - Fahid Nadeem
3个回答

4

请检查你的AndroidManifest.xml文件!并按照以下方式修复GCM的设置。在我的情况下,我解决了这个“null”问题。祝你好运!

<permission
    android:name="[MY PACKAGE NAME].permission.C2D_MESSAGE"
    android:protectionLevel="signature" />
...

<uses-permission android:name="[MY PACKAGE NAME].permission.C2D_MESSAGE" />
...
<service android:name="[MY PACKAGE NAME].GCMIntentService" /> 
...
<receiver
    android:name="[MY PACKAGE NAME].GcmBroadcastReceiver"  android:exported="true"
    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="[MY PACKAGE NAME]" />
    </intent-filter>
</receiver>

太晚了,但我有和你一样的清单文件,但仍然在gcm.getMessageType(intent)上得到null值。 你能帮忙吗? @cmcromance - Fahid Nadeem
@FahidNadeem,我认为帮助你并不容易。我们应该查看有关GCM的新指南。谷歌经常更改代码!您是否了解“InstanceID”类?我根本不知道它。我应该学习它。如果您正在遭受老式代码的困扰,我认为您最好学习新的指南。:)加油!https://developers.google.com/cloud-messaging/android/client - cmcromance

1
在我的情况下,我通过移除以下内容来解决它:
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />

根据官方指南,现在不再需要: https://developer.android.com/google/gcm/client.html
请注意,接收器中的exported="true"也不再是必需的。

删除注册功能导致我的应用程序无法再检索注册广播(显然是因为这个原因)。因此,尽管它不是他们文档的一部分,但似乎是必需的。 - akohout
该行代码 <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> 支持 Android 4.4 KitKat 之前的设备。https://developers.google.com/cloud-messaging/android/client - Mood

-1

与 Android 文档提出的检查 messageType 不同,我只检查 Intent 动作。在我看来,这是一个变通方法,但有效:

/**
 * Action for GCM registration intents.
 */
private static final String ACTION_GCM_REGISTRATION =
        "com.google.android.c2dm.intent.REGISTRATION";

/**
 * Action for new app updated installed intent.
 */
private static final String ACTION_PACKAGE_REPLACED =
        "android.intent.action.PACKAGE_REPLACED";

@Override
protected void onHandleIntent(final Intent intent) {
    final Bundle extras = intent.getExtras();
    final String action = intent.getAction();
    final GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);

    // messageType will be null for broadcasts with action registration
    // or package replaced
    String messageType = gcm.getMessageType(intent);

    if (!extras.isEmpty()) {
        if (GoogleCloudMessaging.
                MESSAGE_TYPE_MESSAGE.equals(messageType)) {
            onNotification("Received: " + extras.toString());
        } else if (action.equals(ACTION_GCM_REGISTRATION)) {
            onRegistration(extras.getString("registration_id"), intent);
        } else if (action.equals(ACTION_PACKAGE_REPLACED)) {
            onNewAppVersion();
        }
    }

    GcmBroadcastReceiver.completeWakefulIntent(intent);
}

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