【问题标题】:Using GCM, no error but no message received使用 GCM,没有错误但没有收到消息
【发布时间】:2016-08-13 09:08:09
【问题描述】:

我正在尝试使用 GCM。我想从服务器(PHP 文件)向我的设备(Android 手机)发送消息

这个想法是启动应用程序,在任何导航器(chrome、firefox...)上加载 test.php,然后我的手机上应该会出现一个通知。 实际上,我的手机没有任何反应。在 Android Studio 的日志中,我可以看到 GCM 注册令牌,这样就可以了。但是之后……我有点迷路了。如何检查消息是否发送到服务器?我如何知道该服务正在侦听应用程序?

这是我的实际文件,当我发送消息和启动应用程序时没有错误:

test.php

<?php

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

require_once __DIR__ . '/gcm.php';

$gcm = new GCM();

$data = array();
$data['message'] = "Un message de test";

// the topic you want to send notification
$topic = 'global';

// sending push message to a topic
$gcm->sendToTopic($topic, $data);

?>

gcm.php(我已经从这里删除了 API 密钥)

<?php
class GCM {

    // constructor
    function __construct() {

    }

    // sending push message to single user by gcm registration id
    public function send($to, $message) {
        $fields = array(
            'to' => $to,
            'data' => $message,
        );
        return $this->sendPushNotification($fields);
    }

    // Sending message to a topic by topic id
    public function sendToTopic($to, $message) {
        $fields = array(
            'to' => '/topics/' . $to,
            'data' => $message,
        );
        return $this->sendPushNotification($fields);
    }

    // sending push message to multiple users by gcm registration ids
    public function sendMultiple($registration_ids, $message) {
        $fields = array(
            'registration_ids' => $registration_ids,
            'data' => $message,
        );

        return $this->sendPushNotification($fields);
    }

    // function makes curl request to gcm servers
    private function sendPushNotification($fields) {

        // include config

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

        $headers = array(
            'Authorization: key=AIz...',
            '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);

    return $result;
}}?>

对于应用程序:

MainActivity.java

protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Registering BroadcastReceiver
        //registerReceiver();

        if (checkPlayServices()) {
            // Start IntentService to register this application with GCM.
            Intent intent = new Intent(this, RegistrationIntentService.class);
            startService(intent);

        }
...
private boolean checkPlayServices() {
        GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
        int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
        if (resultCode != ConnectionResult.SUCCESS) {
            if (apiAvailability.isUserResolvableError(resultCode)) {
                apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
                        .show();
            } else {
                Log.i(TAG, "This device is not supported.");
                finish();
            }
            return false;
        }
        return true;
    }

RegistrationIntentService.java

public class RegistrationIntentService extends IntentService {

    private static final String TAG = "RegIntentService";
    private static final String[] TOPICS = {"global"};

    public RegistrationIntentService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);

        try {
            InstanceID instanceID = InstanceID.getInstance(this);
            String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
                    GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
            Log.i(TAG, "GCM Registration Token: " + token);


            sendRegistrationToServer(token);

            subscribeTopics(token);
      sharedPreferences.edit().putBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, true).apply();

        } catch (Exception e) {
            Log.d(TAG, "Failed to complete token refresh", e);

            sharedPreferences.edit().putBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, false).apply();
        }
    }

    /**
     * Persist registration to third-party servers.
     *
     * Modify this method to associate the user's GCM registration token with any server-side account
     * maintained by your application.
     *
     * @param token The new token.
     */
    private void sendRegistrationToServer(String token) {
        // Add custom implementation, as needed.
    }

    /**
     * Subscribe to any GCM topics of interest, as defined by the TOPICS constant.
     *
     * @param token GCM token
     * @throws IOException if unable to reach the GCM PubSub service
     */
    // [START subscribe_topics]
    private void subscribeTopics(String token) throws IOException {
        GcmPubSub pubSub = GcmPubSub.getInstance(this);
        for (String topic : TOPICS) {
            pubSub.subscribe(token, "/topics/" + topic, null);
        }
    }
    // [END subscribe_topics]

}

MyGcmListenerService.java

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 = "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);

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

        // [START_EXCLUDE]
        /**
         * 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_EXCLUDE]
    }
    // [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, MainActivity.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.notification_icon)
                .setContentTitle("GCM Message")
                .setContentText(message)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

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

        notificationManager.notify(1 /* ID of notification */, notificationBuilder.build());
    }
}

build.gradle(生成 google-services.json 并且在“app”文件夹中)

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'
    compile 'com.google.android.gms:play-services-appindexing:8.4.0'
    compile 'com.google.android.gms:play-services:8.4.0'
}

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        // Google Play Services
        classpath 'com.google.gms:google-services:1.3.0-beta1'
    }
}
apply plugin: 'com.google.gms.google-services'

最后是清单

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!-- [START gcm_permission] -->
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
 <service
            android:name=".MyGcmListenerService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
            </intent-filter>
        </service>
        <service
            android:name=".MyInstanceIDListenerService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.android.gms.iid.InstanceID"/>
            </intent-filter>
        </service>
        <service
            android:name=".RegistrationIntentService"
            android:exported="false">
        </service>

【问题讨论】:

  • 欢迎来到 StackOverflow。请编辑您的问题,具体说明您当前的代码有什么问题以及您希望发生什么。
  • 已编辑,谢谢。

标签: android google-cloud-messaging


【解决方案1】:

现在可以使用 GCM statistics 查看通过 GCM 发送的消息的状态,以供已发布的 Google Play 应用使用。要在您的 Google Play 开发者控制台上查看 GCM 统计信息,请通过以下步骤将 GCM 简单 API 密钥或 C2DM 令牌与您的应用程序关联:

  1. 登录您的 Google Play 开发者控制台。
  2. 选择一个应用程序。
  3. 在左侧菜单中,点击服务和 API
  4. 点击链接发件人 ID 按钮。
  5. 输入您的 GCM API 密钥或 C2DM 客户端登录令牌。
  6. 点击链接

您的应用发布后,您可以在应用的统计信息页面上查看 GCM 统计信息。

  1. 登录您的 Google Play 开发者控制台。
  2. 选择一个应用程序。
  3. 在左侧菜单中,点击统计数据
  4. 点击“统计信息”旁边的下拉菜单并选择 GCM 统计信息

对于您的编码问题,这篇 SO 帖子 - GCM couldnt receive message 可以提供帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 2016-06-14
    • 2014-12-24
    相关资源
    最近更新 更多