未收到来自 Android GCM 的消息

Posted

技术标签:

【中文标题】未收到来自 Android GCM 的消息【英文标题】:No message received from Android GCM 【发布时间】:2014-05-29 13:02:23 【问题描述】:

我正在尝试使用 GCM 发送通知。 GoogleCloudMessaging 部分中的注册工作正常,它会生成 Reg。像APA91bFZCccJh2Yt-r-9WSHk0FvmkzxCjhK9xsG2Ggc-jXNmdIg0g9Su3k5-KSL9wVd-_5CiOuqy8FKE4y7i_E6APqKsU4yTlTLmoX2pTQK25rj8JNHXcXGrd-sLDoec8GZ6jxOgtnZenzjj51eDRZMoCU_UNd1UnA这样的ID

我使用此 ID 向 GSM 发送了一条消息。 GCM 服务器的响应也很好:"multicast_id":7600934834361287625,"success":1,"failure":0,"canonical_ids":0,"results":["message_id":"0:1401367637744857%f2c63832f9fd7ecd"]

但是在我的应用程序端没有收到任何消息,甚至没有调用 WakefulBroadcastReceiver。 App端代码如下:

Android 清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.gcmtest"
    android:versionCode="1"
    android:versionName="1.0.0" >

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="18" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <permission
        android:name="com.example.gcmtest.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />

    <uses-permission android:name="com.example.gcmtest.permission.C2D_MESSAGE" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.VIBRATE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <activity
            android:name="com.example.gcmtest.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="com.example.gcmtest.MainActivity"
            android:label="@string/title_activity_main" >
        </activity>
        <activity
            android:name="com.example.gcmtest.ShowActivity"
            android:label="@string/title_activity_show" >
        </activity>

        <service android:name="com.example.gcmtest.GCMNotificationIntentService" />

        <receiver
            android:name="com.example.gcmtest.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="com.example.gcmtest" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

RegisterActivity.java

  public class RegisterActivity extends ActionBarActivity 

        Button gcmRegisterButton;
        GoogleCloudMessaging gcm;
        Context context = this;
        String regId = "";

        public static final String REG_ID = "regId";
        private static final String APP_VERSION = "appVersion";

        static final String TAG = "Register Activity";

        private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;

        @Override
        protected void onCreate(Bundle savedInstanceState) 
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_register);

            gcmRegisterButton = (Button) findViewById(R.id.gcmRegisterButton);
            gcmRegisterButton.setOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View arg0) 
                    if (regId.isEmpty()) 
                        regId = registerGCM();
                        Log.d("RegisterActivity", "GCM RegId: " + regId);
                     else 
                        Toast.makeText(getApplicationContext(),
                                "Already Registered with GCM Server!",
                                Toast.LENGTH_LONG).show();
                    
                
            );

        

        protected boolean checkPlayService() 
            // TODO Auto-generated method stub
            int resultCode = GooglePlayServicesUtil
                    .isGooglePlayServicesAvailable(this);
            if (resultCode != ConnectionResult.SUCCESS) 
                if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) 
                    GooglePlayServicesUtil.getErrorDialog(resultCode, this,
                            PLAY_SERVICES_RESOLUTION_REQUEST).show();
                 else 
                    Log.i(TAG, "This device is not supported.");
                    finish();
                
                return false;
            
            return true;
        

        public String registerGCM() 

            gcm = GoogleCloudMessaging.getInstance(this);
            regId = getRegistrationId(context);

            if (regId.isEmpty()) 

                registerInBackground();

                Log.d("RegisterActivity",
                        "registerGCM - successfully registered with GCM server - regId: "
                                + regId);
             else 
                Toast.makeText(getApplicationContext(),
                        "RegId already available. RegId: " + regId,
                        Toast.LENGTH_LONG).show();
                Intent i = new Intent(getApplicationContext(), MainActivity.class);
                i.putExtra("regId", regId);
                Log.d("RegisterActivity", "Before starting main activity.");
                startActivity(i);
                finish();
                Log.d("RegisterActivity", "After finish.");
            
            return regId;
        

        private String getRegistrationId(Context context) 
            final SharedPreferences prefs = getSharedPreferences(
                    RegisterActivity.class.getSimpleName(), Context.MODE_PRIVATE);
            String registrationId = prefs.getString(REG_ID, "");
            if (registrationId.isEmpty()) 
                Log.i(TAG, "Registration not found.");
                return "";
            
            int registeredVersion = prefs.getInt(APP_VERSION, Integer.MIN_VALUE);
            int currentVersion = getAppVersion(context);
            if (registeredVersion != currentVersion) 
                Log.i(TAG, "App version changed.");
                return "";
            
            return registrationId;
        

        private static int getAppVersion(Context context) 
            try 
                PackageInfo packageInfo = context.getPackageManager()
                        .getPackageInfo(context.getPackageName(), 0);
                return packageInfo.versionCode;
             catch (NameNotFoundException e) 
                Log.d("RegisterActivity",
                        "I never expected this! Going down, going down!" + e);
                throw new RuntimeException(e);
            
        

        private void registerInBackground() 
            new AsyncTask<Void, Void, String>() 
                @Override
                protected String doInBackground(Void... params) 
                    String msg = "";
                    try 
                        if (gcm == null) 
                            gcm = GoogleCloudMessaging.getInstance(context);
                        
                        regId = gcm.register(Config.GOOGLE_PROJECT_ID);
                        Log.d("RegisterActivity", "registerInBackground - regId: "
                                + regId);
                        msg = "Device registered, registration ID=" + regId;

                        storeRegistrationId(context, regId);
                     catch (IOException ex) 
                        msg = "Error :" + ex.getMessage();
                        Log.d("RegisterActivity", "Error: " + msg);
                    
                    Log.d("RegisterActivity", "AsyncTask completed: " + msg);
                    return msg;
                

                @Override
                protected void onPostExecute(String msg) 
                    Toast.makeText(getApplicationContext(),
                            "Registered with GCM Server." + msg, Toast.LENGTH_LONG)
                            .show();
                    Log.d("RegisterActivity", "Registered with GCM Server." + msg);

                    if (TextUtils.isEmpty(regId)) 
                        Toast.makeText(getApplicationContext(), "RegId is empty!",
                                Toast.LENGTH_LONG).show();
                     else 
                        Intent i = new Intent(getApplicationContext(),
                                MainActivity.class);
                        i.putExtra("regId", regId);
                        Log.d("RegisterActivity", "Before starting main activity.");
                        startActivity(i);
                        finish();
                        Log.d("RegisterActivity", "After finish.");
                    
                
            .execute(null, null, null);
        

        private void storeRegistrationId(Context context, String regId) 
            final SharedPreferences prefs = getSharedPreferences(
                    RegisterActivity.class.getSimpleName(), Context.MODE_PRIVATE);
            int appVersion = getAppVersion(context);
            Log.i(TAG, "Saving regId on app version " + appVersion);
            SharedPreferences.Editor editor = prefs.edit();
            editor.putString(REG_ID, regId);
            editor.putInt(APP_VERSION, appVersion);
            editor.commit();
        
......
.....
    

GcmBroadcastReceiver.java

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver 

    @Override
    public void onReceive(Context context, Intent intent) 
        // TODO Auto-generated method stub
        Log.d("GcmBroadcastReceiver","Broadcast Received.");
        ComponentName comp = new ComponentName(context.getPackageName(),
                GCMNotificationIntentService.class.getName());
        startWakefulService(context, (intent.setComponent(comp)));
        setResultCode(Activity.RESULT_OK);
    


GCMNotificationIntentService.java

public class GCMNotificationIntentService extends IntentService 

    public static final int NOTIFICATION_ID = 1;

    public GCMNotificationIntentService() 
        super("GcmIntentService");
    

    @Override
    protected void onHandleIntent(Intent intent) 
        // TODO Auto-generated method stub
        Log.d("IntentService","IntentService started.");
        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);

        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)) 

                // error in GoogleCloudMessage

             else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
                    .equals(messageType)) 

                // GoogleCloudMessage deleted from server

                // If it's a regular GCM message, do some work.
             else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
                    .equals(messageType)) 

                String gcmData = intent.getExtras().getString("data");
                Log.d("gcmData", gcmData);
            
        
        // Release the wake lock provided by the WakefulBroadcastReceiver.
        GcmBroadcastReceiver.completeWakefulIntent(intent);
    

    // Put the message into a notification and post it.
    // This is just one simple example of what you might choose to do with
    // a GCM message.
    private void sendNotification(String msg) 
        NotificationManager mNotificationManager = (NotificationManager) this
                .getSystemService(Context.NOTIFICATION_SERVICE);

        Intent notificationIntent = new Intent(this, ShowActivity.class);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                notificationIntent, 0);

        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
                this)
                .setSmallIcon(R.drawable.common_signin_btn_icon_normal_light)
                .setContentTitle("GCM Notification")
                .setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
                .setContentText(msg);

        mBuilder.setContentIntent(contentIntent);
        mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
    


我的代码有什么问题?

【问题讨论】:

乍一看,我看不出有什么问题。您是否尝试在应用连接到 PC 时发送通知?您应该检查 logcat 以查看是否调用了广播接收器,以及是否调用了服务。 我已经在设备(未连接)和模拟器中进行了测试。不,不调用广播接收器或服务。 你解决了吗... 【参考方案1】:

请检查您是否使用浏览器 API 密钥将消息从服​​务器(php 代码)发送到 android 设备。

【讨论】:

以上是关于未收到来自 Android GCM 的消息的主要内容,如果未能解决你的问题,请参考以下文章

未收到 GCM 消息

当设备连接互联网时,我无法收到旧消息-GCM

Android - GCM 在打开应用程序时收到来自 gcm 的通知

为啥我无法在 Android 设备上接收来自 GCM 的消息

在android中没有收到推送通知

java中的XMPP服务器没有收到来自GCM服务器的所有消息