0

GCM メッセージを使用するゲームを作成しています。1 人のプレーヤーがサーバーへのターン移動に入ると、サーバーは対戦相手に GCM メッセージを送信し、そのクライアントに追加のターン データが利用可能であることを知らせます。これは単純なはずです。サンプルの GCM クライアント コードにできる限り厳密に従っています。

テスト用に次の 2 つのデバイスがあります。 Motorola Xoom と Ice Cream Sandwich バージョン 4.0.4 と Motorola X2 と Gingerbread バージョン 2.3.5

どちらのデバイスにも Goggle アカウントが設定されています (実際には同じアカウントです)。両方で Play ストアからアプリケーションをダウンロードできます。新しい Google トーク メッセージまたは Gmail メッセージを受信すると、両方で通知メッセージを受け取ります。どちらも同じ Wi-Fi ネットワークを使用して目の前にあるため、ファイアウォールの問題がないことを確認できます。両方に同じゲーム アプリケーションをインストールしています。両方のデバイスで GCM 登録 ID 番号を取得できました。Android OS のバージョンを除けば、両方のデバイスは実質的に同一です。ただし、Xoom は GCM メッセージを受信しますが、X2 は受信しません。または、少なくともメッセージが X2 上のアプリケーションにブロードキャストされていません。

これは私のマニフェストファイルです:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="myGame.app.main" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<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="myGame.app.main.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="myGame.app.main.permission.C2D_MESSAGE" />

<application android:icon="@drawable/icon" android:name="myGameApp" android:label="@string/app_name" android:description="@string/description" android:theme="@style/GlobalTheme" android:killAfterRestore="false" android:allowTaskReparenting="false" android:persistent="false">

    ... Other Activities ...

    <receiver android:name="com.google.android.gcm.GCMBroadcastReceiver" 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="myGame.app.main" />
        </intent-filter>
    </receiver>
    <service android:name=".GCMIntentService" android:enabled="true" />
    </application>
</manifest>

これは私の GCMIntentService のコードです:

package myGame.app.main;

import com.google.android.gcm.GCMBaseIntentService;
import com.google.android.gcm.GCMRegistrar;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import java.util.logging.Logger;

public class GCMIntentService extends GCMBaseIntentService
{
    private static PowerManager.WakeLock sWakeLock;
    private static final Object LOCK = GCMIntentService.class;
    private static final String GCM_SENDER_ID = "... My Sender ID...";
    private static final String GCM_INTENT_FILTER = "myGame.app.main.GCM_MESSAGE";
    private static final String MESSAGE_TYPE = "Type";
    private static final String MESSAGE_CONTENT = "Body";
    private static Logger log = Logger.getLogger(GCMIntentService.class.getName());

    public GCMIntentService()
    {
        super(GCM_SENDER_ID);
    }

    static void runIntentInService(Context context,Intent intent)
    {
        synchronized(LOCK)
        {
            if (sWakeLock == null)
            {
                PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
                sWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"sc_wakelock");
            }
        }
        sWakeLock.acquire();
        intent.setClassName(context,GCMIntentService.class.getName());
        context.startService(intent);
    }

    @Override protected void onRegistered(Context context,String registrationId)
    {
        log.warning("From GCMIntentService: Device successfully registered as "+registrationId);
        ... Other Code ...
    }

    @Override protected void onUnregistered(Context context,String registrationId)
    {
        log.warning("From GCMIntentService: Device successfully unregistered");
        ... Other Code ...
    }

    @Override protected void onMessage(Context context,Intent messageIntent)
    {
        log.warning("From GCMIntentService: Game update notice received");
        ... Other Code ...
    }

    @Override protected void onDeletedMessages(Context context,int total)
    {
        log.warning("From GCMIntentService: Server deleted "+Integer.toString(total)+" pending messages");
    }

    @Override public void onError(Context context,String errorId)
    {
        log.warning("From GCMIntentService: Error "+errorId);
        ... Other Code ...
    }

    @Override protected boolean onRecoverableError(Context context,String errorId)
    {
        log.warning("From GCMIntentService: Recoverable error "+errorId);
        return(super.onRecoverableError(context,errorId));
    }
}

独自の getGCMIntentServiceClassName() 関数を使用して独自の GCMBroadcastReceiver クラスを作成し、そこにログ メッセージを配置するところまで行きました。私が試したすべてのバリエーションで、アプリケーションが Xoom で実行されている場合は適切な LogCat メッセージが表示されますが、X2 では GCM メッセージの証拠はまったく表示されません。GCMBroadcastReceiver や GCMIntentService がまったく機能していないように見えますが、エラー メッセージは表示されません。

誰でもこれで私を助けることができますか?

4

1 に答える 1

0

GCM メッセージのサンプル コードをコンパイルしました。私が行った唯一の変更は、ゲーム アプリケーションで使用しているものと同じ API キーと Sender ID を使用することでした。このアプリケーションは両方のデバイスで動作するため、ネットワークに問題がないことを再確認でき、X2 が実際に GCM メッセージを受信できることを確認できます。

悪いニュースは、X2 がまだ私のゲームの GCM メッセージを受信して​​いないことです。さらに調査した結果、サーバーが GCM メッセージを X2 に送信しようとすると (ゲーム アプリケーションのみ)、サーバーが ERROR_NOT_REGISTERED の結果を受け取ることがわかりました。Xoom に送信するようなエラーはありません。サーバーが登録ID番号を正常に受信していることを確認しました。わかりにくいのは承知していますが、登録 ID は送信プロセスで壊れることはありません。

デバイスを GCM サーバーから登録解除する方法について、公開されているいくつかの推奨事項を試しましたが、どれもうまくいかないようでした。いつも同じ登録 ID が返ってきました。そのため、ゲームを完全にアンインストールしてから、X2 に再インストールしました。これにより、問題を解決した新しい登録 ID 番号を取得する必要がありました。私のゲームは両方のデバイスで正しく動作するようになりました。デバッグ中に、ゲームと GCM サーバーの間で何らかの形で登録 ID が混同されたと想定する必要があります。

アプリケーションをアンインストールする以外に解決策がないように見えるので、これが通常の問題にならないことを願うばかりです。

于 2012-07-26T21:09:32.963 に答える