ActivityManager: 无法启动服务 Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x1000010 (has extras) } U=0: 未找到
ActivityManager: Unable to start service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x1000010 (has extras) } U=0: not found
自从尝试将我的 Android 应用程序从 Eclipse 更新到 Android Studio(转换为 gradle 项目)以来,我一直 运行 遇到问题。我想我已经解决了其中的大部分问题,但是我无法从 GCM(这是应用程序的重要部分)获得通知。
这是我从 Android phone 获取 GCM 消息的消息(这些消息从服务器多播发送到多个 android 设备):
--------- beginning of main
2018-10-26 15:46:36.222 2921-2921/com.ddv.android.gcm.support.app V/GCMBroadcastReceiver: onReceive: com.google.android.c2dm.intent.RECEIVE
2018-10-26 15:46:36.222 2921-2921/com.ddv.android.gcm.support.app V/GCMBroadcastReceiver: GCM IntentService class: com.ddv.android.gcm.support.app.GCMIntentService
2018-10-26 15:46:36.225 2921-2921/com.ddv.android.gcm.support.app V/GCMBaseIntentService: Acquiring wakelock
2018-10-26 15:46:36.226 1686-3213/? W/ActivityManager: Unable to start service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x10 pkg=com.ddv.android.gcm.support.app cmp=com.ddv.android.gcm.support.app/com.activate.gcm.GCMIntentService (has extras) } U=0: not found
这是我的 AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ddv.android.gcm.support.app"
android:versionCode="1"
android:versionName="1.0" >
...
<permission
android:name="com.ddv.android.gcm.support.app.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.ddv.android.gcm.support.app.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive data message. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="com.ddv.android.gcm.support.app.permission.RECEIVE" />
...
<application
android:icon="@drawable/ddv_launcher"
android:label="@string/app_name"
android:theme="@style/PulseAppTheme"
android:allowBackup="false"
android:name=".GlobalVariables" >
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:enabled="true"
android:exported="true"
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.ddv.android.gcm.support.app" />
</intent-filter>
</receiver>
<service android:name="com.ddv.android.gcm.support.app.GCMIntentService"
android:enabled="true">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
...
我也试过将 <service android:name="com.ddv.android.gcm.support.app.GCMIntentService"
更改为 <service android:name=".GCMIntentService"
,结果相同。
基本上我可以说 Android 设备正在接收 GCM 消息。它知道 GXM IntentService 是我的自定义 com.ddv.android.gcm.support.app.GCMIntentService,但它没有对它做任何事情......它并没有真正抛出任何错误。我在 logcat 中看到的消息看起来像是警告。
我已确定我的 GCMIntentService 在应用程序的主包中。而且我拥有所有正确的权限,所以我不确定我缺少什么或者为什么我不能让它工作。
当我更新我的应用程序时,我确实必须更改我的 GCM 注册方式,而且我可能仍然有这个错误。但是下面的代码没有抛出任何错误,当我从服务器发出 GCM 消息时,我所有的 Android 设备都从上面收到消息(看起来它们已经正确注册并从 Google).
GCM注册码:
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(RegisterActivity.this);
}
regId = gcm.register(SENDER_ID);
Log.d(TAG, "########################################");
Log.d(TAG, "Current Device's Registration ID is: " + regId);
SharedPreferences prefs = RegisterActivity.this.getSharedPreferences("com.google.android.gcm", 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("regId", regId);
editor.apply();
Log.d(TAG, "prefs.getString(\"regId\", \"\"): " + prefs.getString("regId", ""));
Log.d(TAG, "GCMRegistrar.getRegistrationId: " + GCMRegistrar.getRegistrationId(RegisterActivity.this));
ServerUtilities.registerToGCMServer(RegisterActivity.this, regId);
ServerUtilities 代码:
static boolean registerToGCMServer(final Context context, final String regId) {
Log.i(TAG, "registering device on GCM Server (regId = " + regId + ")");
String baseUrl = getHost(context) + context.getString(R.string.GCM_PATH) + context.getString(R.string.GCM_REGISTER_PATH);
Map<String, String> params = new HashMap<String, String>();
params.put("regId", regId);
long backoff = BACKOFF_MILLI_SECONDS + random.nextInt(1000);
// Once GCM returns a registration id, we need to register it in the
// demo server. As the server might be down, we will retry it a couple
// times.
for (int i = 1; i <= MAX_ATTEMPTS; i++) {
Log.d(TAG, "Attempt #" + i + " to register");
try {
displayMessage(context, context.getString(R.string.server_registering, i, MAX_ATTEMPTS));
post(baseUrl, params);
GCMRegistrar.setRegisteredOnServer(context, true);
String message = context.getString(R.string.server_registered);
CommonUtilities.displayMessage(context, message);
return true;
} catch (IOException e) {
// Here we are simplifying and retrying on any error; in a real
// application, it should retry only on unrecoverable errors
// (like HTTP error code 503).
Log.e(TAG, "Failed to register on attempt " + i, e);
if (i == MAX_ATTEMPTS) {
break;
}
try {
Log.d(TAG, "Sleeping for " + backoff + " ms before retry");
Thread.sleep(backoff);
} catch (InterruptedException e1) {
// Activity finished before we complete - exit.
Log.d(TAG, "Thread interrupted: abort remaining retries!");
Thread.currentThread().interrupt();
return false;
}
// increase backoff exponentially
backoff *= 2;
}
}
String message = context.getString(R.string.server_register_error, MAX_ATTEMPTS);
CommonUtilities.displayMessage(context, message);
return false;
}
哦,对了,最后一条信息。以下是我希望我的应用程序执行的操作:在我的 GCMIntentService.java
中,我希望调用覆盖的 onMessage()
函数,该函数会根据收到的 GCM 消息显示警报。
public class GCMIntentService extends GCMBaseIntentService {
...
@Override
public void onMessage(Context context, Intent intent) {
Log.i(TAG, "Received message");
String alertText = intent.getExtras().getString("text");
String ackID = intent.getExtras().getString("id");
String detailID = intent.getExtras().getString("detail_id");
// Sets the class to be called when the notification is selected
intent.setClass(context, AlertFragmentActivity.class);
intent.putExtra("alert", (Parcelable) (new Alert(ackID, detailID, alertText)));
// I think this only goes through if the app is already running?
displayAlert(context, intent);
// notifies user
generateNotification(context, intent);
}
}
我知道我最终将不得不更新到 FCM,但这同时应该仍然有效(直到 2019 年 4 月 GCM 被完全删除)。
因为我将我的注册从 GMCRegistrar.register()
更新为 GoogleCloudMessaging.register()
,所以我必须将我的广播接收器更新为 WakefulBroadcastReceiver
。
这个 link 给了我获取更新的 GCM 消息所需的代码。
我完成的全部步骤:
- 创建了新的自定义
WakefulBoradcastReciever
以获取新的 GCM 消息。
CGCMBroadcastReciever.java
package com.ddv.android.gcm.support.app;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.WakefulBroadcastReceiver;
import android.util.Log;
public class CGCMBroadcastReceiver extends WakefulBroadcastReceiver {
private static final String TAG = "CGCMBroadcastReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive");
ComponentName comp = new ComponentName(context.getPackageName(),
CGCMIntentService.class.getName());
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
- 创建了新的
IntentService
来处理从接收 GCM 消息创建的新 Intent。
CGCMIntentService.java
package com.ddv.android.gcm.support.app;
import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
import android.support.v4.app.NotificationCompat;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.ddv.android.gcm.support.app.alerts.Alert;
import com.ddv.android.gcm.support.app.alerts.AlertFragmentActivity;
import com.google.android.gcm.GCMBroadcastReceiver;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import static com.ddv.android.gcm.support.app.CommonUtilities.displayAlert;
public class CGCMIntentService extends IntentService {
private static final String TAG = "CGCMIntentService";
private static final String DDV_GROUP_KEY = "ddv_group_key";
// This "notifcationStyle" will hold all of the notifications that come in
// It will only be cleared when a user goes to the Alert page
public static NotificationCompat.InboxStyle notificationStyle = new NotificationCompat.InboxStyle();
public CGCMIntentService() {
super("GcmIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "onHandleIntent");
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
Log.i(TAG, "Received message");
String alertText = intent.getExtras().getString("text");
String ackID = intent.getExtras().getString("id");
String detailID = intent.getExtras().getString("detail_id");
// Sets the class to be called when the notification is selected
intent.setClass(CGCMIntentService.this, AlertFragmentActivity.class);
intent.putExtra("alert", (Parcelable) (new Alert(ackID, detailID, alertText)));
// I think this only goes through if the app is already running?
displayAlert(CGCMIntentService.this, intent);
// notifies user
generateNotification(CGCMIntentService.this, intent);
CGCMBroadcastReceiver.completeWakefulIntent(intent);
}
/**
* Issues a notification to inform the user that server has sent a message.
*/
@SuppressWarnings("deprecation")
public static void generateNotification(Context context, Intent intent) {
String message = "Alert from " + intent.getStringExtra("text");
//String id = intent.getStringExtra("id");
int icon = R.drawable.ic_stat_example;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// set intent so it does not start a new activity
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// build notification
NotificationCompat.Builder nBuilder = new NotificationCompat.Builder(context)
.setContentTitle("DDV Alert")
.setContentText(message)
.setContentIntent(pendingIntent)
.setSmallIcon(icon)
.setWhen(when)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setGroup(DDV_GROUP_KEY)
.setGroupSummary(true)
.setStyle(notificationStyle.addLine(message))
.setVibrate(new long[] { 0, 100, 200, 300, 400, 500, 400, 300, 200, 100, 0,
0, 100, 200, 300, 400, 500, 400, 300, 200, 100, 0,
0, 100, 200, 300, 400, 500, 400, 300, 200, 100, 0 })
.setSound(Uri.parse("android.resource://com.ddv.android.gcm.support.app/raw/" + R.raw.annoying_alarm93))
.setLights(0xff00ff00, 300, 1000)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setAutoCancel(true);
String title = context.getString(R.string.app_name);
//Set notification sound to max
AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audio.setStreamVolume(AudioManager.STREAM_NOTIFICATION, audio.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION), 0);
//If user is not on a call send the notification
//Else wait for the call to end to send the notification
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if(telephony.getCallState() == TelephonyManager.CALL_STATE_IDLE) {
// start notification
notificationManager.notify(0, nBuilder.build());
} else {
// create a handler to listen for the call to end
Handler handler = new Handler(context.getMainLooper());
GCMIntentService activity = new GCMIntentService();
handler.post(activity.new TelephonyRunnable(context, telephony, notificationManager, nBuilder.build()));
}
}
}
- 更新 AndroidManifest.xml 以使用新的自定义服务。
AndroidManifest.xml
<receiver
android:name=".CGCMBroadcastReceiver"
android:enabled="true"
android:exported="true"
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.ddv.android.gcm.support.app" />
</intent-filter>
</receiver>
<!--
Application-specific subclass of GCMBaseIntentService that will
handle received messages.
By default, it must be named .CGCMIntentService, unless the
application uses a custom BroadcastReceiver that redefines its name.
-->
<service android:name=".CGCMIntentService"
android:enabled="true">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
自从尝试将我的 Android 应用程序从 Eclipse 更新到 Android Studio(转换为 gradle 项目)以来,我一直 运行 遇到问题。我想我已经解决了其中的大部分问题,但是我无法从 GCM(这是应用程序的重要部分)获得通知。
这是我从 Android phone 获取 GCM 消息的消息(这些消息从服务器多播发送到多个 android 设备):
--------- beginning of main
2018-10-26 15:46:36.222 2921-2921/com.ddv.android.gcm.support.app V/GCMBroadcastReceiver: onReceive: com.google.android.c2dm.intent.RECEIVE
2018-10-26 15:46:36.222 2921-2921/com.ddv.android.gcm.support.app V/GCMBroadcastReceiver: GCM IntentService class: com.ddv.android.gcm.support.app.GCMIntentService
2018-10-26 15:46:36.225 2921-2921/com.ddv.android.gcm.support.app V/GCMBaseIntentService: Acquiring wakelock
2018-10-26 15:46:36.226 1686-3213/? W/ActivityManager: Unable to start service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x10 pkg=com.ddv.android.gcm.support.app cmp=com.ddv.android.gcm.support.app/com.activate.gcm.GCMIntentService (has extras) } U=0: not found
这是我的 AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ddv.android.gcm.support.app"
android:versionCode="1"
android:versionName="1.0" >
...
<permission
android:name="com.ddv.android.gcm.support.app.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.ddv.android.gcm.support.app.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive data message. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="com.ddv.android.gcm.support.app.permission.RECEIVE" />
...
<application
android:icon="@drawable/ddv_launcher"
android:label="@string/app_name"
android:theme="@style/PulseAppTheme"
android:allowBackup="false"
android:name=".GlobalVariables" >
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:enabled="true"
android:exported="true"
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.ddv.android.gcm.support.app" />
</intent-filter>
</receiver>
<service android:name="com.ddv.android.gcm.support.app.GCMIntentService"
android:enabled="true">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
...
我也试过将 <service android:name="com.ddv.android.gcm.support.app.GCMIntentService"
更改为 <service android:name=".GCMIntentService"
,结果相同。
基本上我可以说 Android 设备正在接收 GCM 消息。它知道 GXM IntentService 是我的自定义 com.ddv.android.gcm.support.app.GCMIntentService,但它没有对它做任何事情......它并没有真正抛出任何错误。我在 logcat 中看到的消息看起来像是警告。
我已确定我的 GCMIntentService 在应用程序的主包中。而且我拥有所有正确的权限,所以我不确定我缺少什么或者为什么我不能让它工作。
当我更新我的应用程序时,我确实必须更改我的 GCM 注册方式,而且我可能仍然有这个错误。但是下面的代码没有抛出任何错误,当我从服务器发出 GCM 消息时,我所有的 Android 设备都从上面收到消息(看起来它们已经正确注册并从 Google).
GCM注册码:
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(RegisterActivity.this);
}
regId = gcm.register(SENDER_ID);
Log.d(TAG, "########################################");
Log.d(TAG, "Current Device's Registration ID is: " + regId);
SharedPreferences prefs = RegisterActivity.this.getSharedPreferences("com.google.android.gcm", 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("regId", regId);
editor.apply();
Log.d(TAG, "prefs.getString(\"regId\", \"\"): " + prefs.getString("regId", ""));
Log.d(TAG, "GCMRegistrar.getRegistrationId: " + GCMRegistrar.getRegistrationId(RegisterActivity.this));
ServerUtilities.registerToGCMServer(RegisterActivity.this, regId);
ServerUtilities 代码:
static boolean registerToGCMServer(final Context context, final String regId) {
Log.i(TAG, "registering device on GCM Server (regId = " + regId + ")");
String baseUrl = getHost(context) + context.getString(R.string.GCM_PATH) + context.getString(R.string.GCM_REGISTER_PATH);
Map<String, String> params = new HashMap<String, String>();
params.put("regId", regId);
long backoff = BACKOFF_MILLI_SECONDS + random.nextInt(1000);
// Once GCM returns a registration id, we need to register it in the
// demo server. As the server might be down, we will retry it a couple
// times.
for (int i = 1; i <= MAX_ATTEMPTS; i++) {
Log.d(TAG, "Attempt #" + i + " to register");
try {
displayMessage(context, context.getString(R.string.server_registering, i, MAX_ATTEMPTS));
post(baseUrl, params);
GCMRegistrar.setRegisteredOnServer(context, true);
String message = context.getString(R.string.server_registered);
CommonUtilities.displayMessage(context, message);
return true;
} catch (IOException e) {
// Here we are simplifying and retrying on any error; in a real
// application, it should retry only on unrecoverable errors
// (like HTTP error code 503).
Log.e(TAG, "Failed to register on attempt " + i, e);
if (i == MAX_ATTEMPTS) {
break;
}
try {
Log.d(TAG, "Sleeping for " + backoff + " ms before retry");
Thread.sleep(backoff);
} catch (InterruptedException e1) {
// Activity finished before we complete - exit.
Log.d(TAG, "Thread interrupted: abort remaining retries!");
Thread.currentThread().interrupt();
return false;
}
// increase backoff exponentially
backoff *= 2;
}
}
String message = context.getString(R.string.server_register_error, MAX_ATTEMPTS);
CommonUtilities.displayMessage(context, message);
return false;
}
哦,对了,最后一条信息。以下是我希望我的应用程序执行的操作:在我的 GCMIntentService.java
中,我希望调用覆盖的 onMessage()
函数,该函数会根据收到的 GCM 消息显示警报。
public class GCMIntentService extends GCMBaseIntentService {
...
@Override
public void onMessage(Context context, Intent intent) {
Log.i(TAG, "Received message");
String alertText = intent.getExtras().getString("text");
String ackID = intent.getExtras().getString("id");
String detailID = intent.getExtras().getString("detail_id");
// Sets the class to be called when the notification is selected
intent.setClass(context, AlertFragmentActivity.class);
intent.putExtra("alert", (Parcelable) (new Alert(ackID, detailID, alertText)));
// I think this only goes through if the app is already running?
displayAlert(context, intent);
// notifies user
generateNotification(context, intent);
}
}
我知道我最终将不得不更新到 FCM,但这同时应该仍然有效(直到 2019 年 4 月 GCM 被完全删除)。
因为我将我的注册从 GMCRegistrar.register()
更新为 GoogleCloudMessaging.register()
,所以我必须将我的广播接收器更新为 WakefulBroadcastReceiver
。
这个 link 给了我获取更新的 GCM 消息所需的代码。
我完成的全部步骤:
- 创建了新的自定义
WakefulBoradcastReciever
以获取新的 GCM 消息。
CGCMBroadcastReciever.java
package com.ddv.android.gcm.support.app;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.WakefulBroadcastReceiver;
import android.util.Log;
public class CGCMBroadcastReceiver extends WakefulBroadcastReceiver {
private static final String TAG = "CGCMBroadcastReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive");
ComponentName comp = new ComponentName(context.getPackageName(),
CGCMIntentService.class.getName());
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
- 创建了新的
IntentService
来处理从接收 GCM 消息创建的新 Intent。
CGCMIntentService.java
package com.ddv.android.gcm.support.app;
import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
import android.support.v4.app.NotificationCompat;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.ddv.android.gcm.support.app.alerts.Alert;
import com.ddv.android.gcm.support.app.alerts.AlertFragmentActivity;
import com.google.android.gcm.GCMBroadcastReceiver;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import static com.ddv.android.gcm.support.app.CommonUtilities.displayAlert;
public class CGCMIntentService extends IntentService {
private static final String TAG = "CGCMIntentService";
private static final String DDV_GROUP_KEY = "ddv_group_key";
// This "notifcationStyle" will hold all of the notifications that come in
// It will only be cleared when a user goes to the Alert page
public static NotificationCompat.InboxStyle notificationStyle = new NotificationCompat.InboxStyle();
public CGCMIntentService() {
super("GcmIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "onHandleIntent");
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
Log.i(TAG, "Received message");
String alertText = intent.getExtras().getString("text");
String ackID = intent.getExtras().getString("id");
String detailID = intent.getExtras().getString("detail_id");
// Sets the class to be called when the notification is selected
intent.setClass(CGCMIntentService.this, AlertFragmentActivity.class);
intent.putExtra("alert", (Parcelable) (new Alert(ackID, detailID, alertText)));
// I think this only goes through if the app is already running?
displayAlert(CGCMIntentService.this, intent);
// notifies user
generateNotification(CGCMIntentService.this, intent);
CGCMBroadcastReceiver.completeWakefulIntent(intent);
}
/**
* Issues a notification to inform the user that server has sent a message.
*/
@SuppressWarnings("deprecation")
public static void generateNotification(Context context, Intent intent) {
String message = "Alert from " + intent.getStringExtra("text");
//String id = intent.getStringExtra("id");
int icon = R.drawable.ic_stat_example;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// set intent so it does not start a new activity
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// build notification
NotificationCompat.Builder nBuilder = new NotificationCompat.Builder(context)
.setContentTitle("DDV Alert")
.setContentText(message)
.setContentIntent(pendingIntent)
.setSmallIcon(icon)
.setWhen(when)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setGroup(DDV_GROUP_KEY)
.setGroupSummary(true)
.setStyle(notificationStyle.addLine(message))
.setVibrate(new long[] { 0, 100, 200, 300, 400, 500, 400, 300, 200, 100, 0,
0, 100, 200, 300, 400, 500, 400, 300, 200, 100, 0,
0, 100, 200, 300, 400, 500, 400, 300, 200, 100, 0 })
.setSound(Uri.parse("android.resource://com.ddv.android.gcm.support.app/raw/" + R.raw.annoying_alarm93))
.setLights(0xff00ff00, 300, 1000)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setAutoCancel(true);
String title = context.getString(R.string.app_name);
//Set notification sound to max
AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audio.setStreamVolume(AudioManager.STREAM_NOTIFICATION, audio.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION), 0);
//If user is not on a call send the notification
//Else wait for the call to end to send the notification
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if(telephony.getCallState() == TelephonyManager.CALL_STATE_IDLE) {
// start notification
notificationManager.notify(0, nBuilder.build());
} else {
// create a handler to listen for the call to end
Handler handler = new Handler(context.getMainLooper());
GCMIntentService activity = new GCMIntentService();
handler.post(activity.new TelephonyRunnable(context, telephony, notificationManager, nBuilder.build()));
}
}
}
- 更新 AndroidManifest.xml 以使用新的自定义服务。
AndroidManifest.xml
<receiver
android:name=".CGCMBroadcastReceiver"
android:enabled="true"
android:exported="true"
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.ddv.android.gcm.support.app" />
</intent-filter>
</receiver>
<!--
Application-specific subclass of GCMBaseIntentService that will
handle received messages.
By default, it must be named .CGCMIntentService, unless the
application uses a custom BroadcastReceiver that redefines its name.
-->
<service android:name=".CGCMIntentService"
android:enabled="true">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>