未收到来自 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 的消息的主要内容,如果未能解决你的问题,请参考以下文章
Android - GCM 在打开应用程序时收到来自 gcm 的通知