我正在实施我的应用推送通知服务,我按照教程on Android developers.com,但不幸的是,我没有收到任何通知。
我正在成功收到注册ID,但是,虽然后备服务收到成功的响应,但设备不会从后端收到任何通知。
p.s:我确信将后续服务的实施发送给Google云服务器。
任何人都可以帮我解决这个问题..?,提前谢谢。
下面你可以找到我的实现。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ettamen.app"
android:versionCode="1"
android:versionName="1.0" >
<supports-screens
android:anyDensity="true"
android:largeScreens="true"
android:normalScreens="true"
android:resizeable="true"
android:smallScreens="true"
android:xlargeScreens="true" />
<!-- GCM connects to Internet Services. -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Creates a custom permission so only this app can receive its messages. -->
<permission
android:name="com.ettamen.app.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.ettamen.app.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive data message. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- Network State Permissions to detect Internet status -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Permission to vibrate -->
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.SEND_SMS" />
<application
android:hardwareAccelerated="true"
android:icon="@drawable/icon"
android:label="@string/app_name" >
<activity
android:name="Ettamen"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale"
android:label="@string/app_name"
android:theme="@android:style/Theme.Black.NoTitleBar" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name="com.ettamen.app.pushnotifications.CordovaGCMBroadcastReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.ettamen.app.pushnotifications" />
</intent-filter>
</receiver>
<service android:name="com.ettamen.app.pushnotifications.GCMIntentService" >
</service>
<activity android:name=".pushnotifications.PushHandlerActivity" >
</activity>
<service android:name="LocationUpdateService" >
</service>
</application>
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
</manifest>
import com.ettamen.app.R;
import com.google.android.gms.gcm.GoogleCloudMessaging;
/*
* Implementation of GCMBroadcastReceiver that hard-wires the intent service to be
* com.plugin.gcm.GCMIntentService, instead of your_package.GCMIntentService
*/
public class CordovaGCMBroadcastReceiver extends BroadcastReceiver {
static final String TAG = "GCMDemo";
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
Context ctx;
@Override
public void onReceive(Context context, Intent intent) {
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
ctx = context;
String messageType = gcm.getMessageType(intent);
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
sendNotification("Send error: " + intent.getExtras().toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
.equals(messageType)) {
sendNotification("Deleted messages on server: "
+ intent.getExtras().toString());
} else {
sendNotification("Received: " + intent.getExtras().toString());
}
setResultCode(Activity.RESULT_OK);
}
// Put the GCM message into a notification and post it.
private void sendNotification(String msg) {
mNotificationManager = (NotificationManager) ctx
.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0,
new Intent(ctx, PushHandlerActivity.class), 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
ctx).setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("GCM Notification")
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
}
GCM意图服务
import android.app.ActivityManager.RunningTaskInfo;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
public class GCMIntentService extends GCMBaseIntentService {
public static final int NOTIFICATION_ID = 237;
private static final String TAG = "GCMIntentService";
public GCMIntentService() {
super("GCMIntentService");
}
@Override
public void onRegistered(Context context, String regId) {
}
@Override
public void onUnregistered(Context context, String regId) {
}
@Override
protected void onMessage(Context context, Intent intent) {
Log.d(TAG, "onMessage - context: " + context);
// Extract the payload from the message
Bundle extras = intent.getExtras();
if (extras != null) {
createNotification(context, extras);
}
}
public void createNotification(Context context, Bundle extras) {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String appName = getAppName(this);
Intent notificationIntent = new Intent(this, PushHandlerActivity.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
notificationIntent.putExtra("pushBundle", extras);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
context).setSmallIcon(context.getApplicationInfo().icon)
.setWhen(System.currentTimeMillis()).setContentTitle(appName)
.setTicker(appName).setContentIntent(contentIntent);
String message = extras.getString("message");
if (message != null) {
mBuilder.setContentText(message);
} else {
mBuilder.setContentText("<missing message content>");
}
String msgcnt = extras.getString("msgcnt");
if (msgcnt != null) {
mBuilder.setNumber(Integer.parseInt(msgcnt));
}
mNotificationManager.notify((String) appName, NOTIFICATION_ID,
mBuilder.build());
tryPlayRingtone();
}
private void tryPlayRingtone() {
try {
Uri notification = RingtoneManager
.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(),
notification);
r.play();
} catch (Exception e) {
Log.e(TAG, "failed to play notification ringtone");
}
}
public static void cancelNotification(Context context) {
NotificationManager mNotificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancel((String) getAppName(context),
NOTIFICATION_ID);
}
private static String getAppName(Context context) {
CharSequence appName = context.getPackageManager().getApplicationLabel(
context.getApplicationInfo());
return (String) appName;
}
public boolean isInForeground() {
ActivityManager activityManager = (ActivityManager) getApplicationContext()
.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> services = activityManager
.getRunningTasks(Integer.MAX_VALUE);
if (services.get(0).topActivity
.getPackageName()
.toString()
.equalsIgnoreCase(
getApplicationContext().getPackageName().toString()))
return true;
return false;
}
@Override
public void onError(Context context, String errorId) {
Log.e(TAG, "onError - errorId: " + errorId);
}
}
package com.ettamen.app.pushnotifications;
import com.ettamen.app.PushNotificationWorker;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
public class PushHandlerActivity extends Activity {
private static String TAG = "PushHandlerActivity";
/*
* this activity will be started if the user touches a notification that we
* own. We send it's data off to the push plugin for processing. If needed,
* we boot up the main activity to kickstart the application.
*
* @see android.app.Activity#onCreate(android.os.Bundle)
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.v(TAG, "onCreate");
boolean isPushPluginActive = PushNotificationWorker.isActive();
if (!isPushPluginActive) {
forceMainActivityReload();
}
// processPushBundle(isPushPluginActive);
GCMIntentService.cancelNotification(this);
finish();
}
/**
* Takes the pushBundle extras from the intent, and sends it through to the
* PushPlugin for processing.
*/
private void processPushBundle(boolean isPushPluginActive) {
// Bundle extras = getIntent().getExtras();
//
// if (extras != null) {
//
// Bundle originalExtras = extras.getBundle("pushBundle");
//
// if ( !isPushPluginActive ) {
// originalExtras.putBoolean("coldstart", true);
// }
//
// PushPlugin.sendExtras(originalExtras);
// }
}
/**
* Forces the main activity to re-launch if it's unloaded.
*/
private void forceMainActivityReload() {
PackageManager pm = getPackageManager();
Intent launchIntent = pm
.getLaunchIntentForPackage(getApplicationContext()
.getPackageName());
startActivity(launchIntent);
}
}
private void getRegID(CallbackContext ctx) {
new AsyncTask<CallbackContext, Void, String>() {
CallbackContext context;
@Override
protected String doInBackground(CallbackContext... params) {
// TODO Auto-generated method stub
context = params[0];
String regid = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(cordova
.getActivity());
}
regid = gcm.register(Constants.SENDER_ID);
} catch (IOException ex) {
Log.d("Exceptio:", ex.getMessage());
}
String message = "{\"ChannelURI\":\"" + regid + "\"}";
return message;
};
protected void onPostExecute(String result) {
try {
JSONObject jResult = new JSONObject(result);
context.success(jResult);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.execute(ctx);
}
答案 0 :(得分:1)
整个清单中包装名称不匹配:
应用程序包:
package="com.ettamen.app"
在权限中,您应该使用应用程序的包,而是使用:
<permission
android:name="com.ettamen.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.ettamen.permission.C2D_MESSAGE" />
两者都应该是com.ettamen.app.permission.C2D_MESSAGE
。
最后,广播接收器:
<receiver
android:name="com.ettamen.app.pushnotifications.CordovaGCMBroadcastReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.ettamen.app.pushnotifications" />
</intent-filter>
</receiver>
该类别应包含您的应用包名称,因此应为com.ettamen.app
。
答案 1 :(得分:0)
经过大量的试验,我发现问题是接收器可以在你喜欢的任何包中,只要清单中的intent过滤器的类别包含应用程序的主包
谢谢大家的帮助和支持。
答案 2 :(得分:0)
使用构建器构建通知时,应在此处设置传递给onReceive
方法而不是您创建的方法的意图:
mBuilder.setContentIntent(contentIntent);
完整代码:
import com.ettamen.app.R;
import com.google.android.gms.gcm.GoogleCloudMessaging;
/*
* Implementation of GCMBroadcastReceiver that hard-wires the intent service to be
* com.plugin.gcm.GCMIntentService, instead of your_package.GCMIntentService
*/
public class CordovaGCMBroadcastReceiver extends BroadcastReceiver {
static final String TAG = "GCMDemo";
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
Context ctx;
@Override
public void onReceive(Context context, Intent intent) {
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
ctx = context;
String messageType = gcm.getMessageType(intent);
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
sendNotification("Send error: " + intent.getExtras().toString(), intent);
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
.equals(messageType)) {
sendNotification("Deleted messages on server: "
+ intent.getExtras().toString(), intent);
} else {
sendNotification("Received: " + intent.getExtras().toString(), intent);
}
setResultCode(Activity.RESULT_OK);
}
// Put the GCM message into a notification and post it.
private void sendNotification(String msg, Intent intent) {
mNotificationManager = (NotificationManager) ctx
.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
ctx).setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("GCM Notification")
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(intent); // here passing the valid intent
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
}
它也可以应用于类GCMIntentService
。