1

ここで提供されているサンプルに基づいて GCM クライアントを作成しています - http://www.androidhive.info/2012/10/android-push-notifications-using-google-cloud-messaging-gcm-php-and-mysql/およびここ - http://developer.android.com/google/gcm/client.html。基本的には最初の例と同じですが、GoogleCloudMessaing API を使用するように更新しました。

サーバーとして、最初のリンクで使用したサンプルの php サーバーを使用しました。しかし、php スクリプトを介してメッセージを送信すると、デバイスにメッセージが届きません。

サーバー側では、mysql パスワードと Google API キーを使用して config.php ファイルを変更しました。

    ?php
    /**
      * Database config variables
    /
   define("DB_HOST", "localhost");
   define("DB_USER", "root");
   define("DB_PASSWORD", "password");
   define("DB_DATABASE", "gcm");

  /*
   * Google API Key
   */
   define("GOOGLE_API_KEY", "MY GOOGLE API KEY"); // Place your Google API Key

アプリから登録 ID を送信する必要がないように、手動で gcm_users テーブルにエントリを作成しました。最初のリンクに記載されているように、テーブルには regId、名前、電子メールが含まれています。

次に、index.php ページからメッセージを送信しますが、メッセージが受信されません。

私のアンドロイドマニフェストファイル -

<uses-sdk
    android:minSdkVersion="8"
    android:targetSdkVersion="16" />

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<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.example.gcmclient.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />

<uses-permission android:name="com.example.gcmclient.permission.C2D_MESSAGE" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".RegisterActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name=".GCMClientActivity" 
        android:configChanges="orientation|keyboardHidden"
        android:label="@string/app_name" >
    </activity>

    <receiver
        android:name=".GCMBroadcastReceiver"
        android:permission="com.google.android.c2dm.permission.SEND" >
        <intent-filter>
            <!-- Receives the actual messages. -->
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <!-- Receives the registration id. -->
            <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
            <category android:name="com.example.gcmclient" />
        </intent-filter>
    </receiver>
    <service android:name=".GCMIntentService" />
</application>

GCMintentService.java ファイル:

    package com.example.gcmclient;

    import android.app.IntentService;
    import android.content.Intent;
    import android.os.Bundle;

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

    public class GCMIntentService extends IntentService {
public GCMIntentService() {
    super("GCMIntentService");
}

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

    String messageType = gcm.getMessageType(intent);

    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 you're
             * not interested in, or that you don't recognize.
             */
        if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
            Utilities.showNotification(this, "Send error: " + extras.toString());
        } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
            Utilities.showNotification(this, "Deleted messages on server: " + extras.toString());
            // If it's a regular GCM message, do some work.
        } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
            Utilities.showNotification(this, "Received: " + extras.toString());
        }
        // Release the wake lock provided by the WakefulBroadcastReceiver.
        GCMBroadcastReceiver.completeWakefulIntent(intent);
    }
}

}

gcm サーバーに正しく登録されており、サーバーが登録 ID をアプリに返すことを確認しました。この RegisterActivity.java ファイルの主要部分:

    private void registerInBackground() {
    new AsyncTask<Void, Void, String>() {
        private Random mRandom = new Random();
        private long mBackoff = BACKOFF_MILLI_SECONDS + mRandom.nextInt(1000);

        private ProgressDialog mDialog;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mDialog = new ProgressDialog(mContext);
            mDialog.setMessage("Registering with Google Cloud Messaging (GCM)");
            mDialog.setIndeterminate(true);
            mDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            mDialog.setCancelable(false);
            mDialog.show();
        }

        @Override
        protected String doInBackground(Void... params) {
            String msg = "";
            for (int i = 1; i <= MAX_ATTEMPTS; i++, mBackoff *= 2) {
                msg = "";
                try {
                    if (mGcm == null) {
                        mGcm = GoogleCloudMessaging.getInstance(mContext);
                    }
                    mRegId = mGcm.register(SENDER_ID);
                    msg = "Device registered, registration ID = " + mRegId;
                    storeRegistrationId(mContext, mRegId);
                    break;
                } catch (IOException e) {
                    Log.d(TAG, e.toString());
                    // If there is an error, don't just keep trying to register.
                    // Require the user to click a button again, or perform
                    // exponential back-off.
                    Log.d(TAG, "Failed to register on attempt: " + i);
                    try {
                        Log.d(TAG, "Sleeping for " + mBackoff + " ms before retry");                        
                        Thread.sleep(mBackoff);
                    } catch(InterruptedException e1) {
                         Log.d(TAG, "Thread interrupted: abort remaining retries!");
                         Thread.currentThread().interrupt();
                         return msg;
                    }
                }
            }
            return msg;
        }

登録直後、アプリは登録 ID を含むブロードキャスト メッセージを受信します。

09-16 19:27:41.970: D/GCMBoradcastReceiver(19723): onReceive が呼び出されました: キー = registration_id 値 =

これをmysqlデータベーステーブルにコピーしました。

ローカル PC で 192.168.1.139 IP アドレスを使用してサーバーを実行しています (パブリック IP はありません)。IPtables からの出力 -

    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination         

    Chain FORWARD (policy ACCEPT)
    target     prot opt source               destination         

    Chain OUTPUT (policy ACCEPT)
    target     prot opt source               destination         
    ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:5228
    ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:5229
    ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:5230

Apache ログには、index.php からの送信要求のステータス OK (200) が表示されます。

それで、私は何が欠けていますか?どんな助けでも大歓迎です。

4

1 に答える 1

0

あなた GCMIntentService は GCM が言ったようなものではありません...

public class GCMIntentService extends GCMBaseIntentService {

    @SuppressWarnings("hiding")
    private static final String TAG = "GCMIntentService";

    public GCMIntentService() {
        super(Utility.SENDER_ID);
    }

    @Override
    protected void onRegistered(Context context, String registrationId) {
        Log.i(TAG, "Device registered: regId = " + registrationId);

    }

    @Override
    protected void onUnregistered(Context context, String registrationId) {
        Log.i(TAG, "Device unregistered");

    }

    @Override
    protected void onMessage(Context context, Intent intent) {
        Log.i(TAG, "Received message");

    }

    @Override
    protected void onDeletedMessages(Context context, int total) {
        Log.i(TAG, "Received deleted messages notification");

    }

    @Override
    public void onError(Context context, String errorId) {
        Log.i(TAG, "Received error: " + errorId);

    }

    @Override
    protected boolean onRecoverableError(Context context, String errorId) {
        // log message
        Log.i(TAG, "Received recoverable error: " + errorId);

        return super.onRecoverableError(context, errorId);
    }
}
于 2013-11-18T10:31:54.370 に答える