android 运行 服务自动启动应用程序
android running service starts app autmatically
在我的应用程序中,我启动了一项服务以在应用程序处于后台时接收通知 - 此服务强制我的应用程序在我停止后自动启动。我试图通过使用未决意图来解决问题,但它仍然发生。
这是我启动服务的意图:
Intent messageReceivingIntent = new Intent(this, MessageReceivingService.class);
messageReceivingIntent.putExtra("myUserId", myUserId);
Pending Inten messagePendingIntent = PendingIntent.getService(this, 0, messageReceivingIntent, PendingIntent.FLAG_UPDATE_CURRENT);
try {
// Perform the operation associated with our pendingIntent
messagePendingIntent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
如果我通过 externalreceiver 调用服务,我会得到一个 nullpointerexception。知道为什么吗?
这是我的 BroadcastReceiver 调用:
messageReceivingIntent = new Intent(this, MessageReceivingService.class);
messageReceivingIntent.putExtra("myUserId", myUserId);
messageReceivingIntent.setAction("com.example.androidtest");
sendBroadcast(messageReceivingIntent);
这是我的广播接收器:
public class ExternalReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(intent!=null){
Bundle extras = intent.getExtras();
if(!MapsActivity.inBackground){
MessageReceivingService.sendToApp(extras, context);
}
else{
MessageReceivingService.saveToLog(extras, context);
}
}
}
}
这是 MessageReceivingService
public class MessageReceivingService extends Service {
private GoogleCloudMessaging gcm;
public static SharedPreferences savedValues;
public static final String INSTANCE_ID_SCOPE = "GCM";
final String BASE_URL = "http://www.example.com/";
public String myUserId;
public String registeredUserId;
public String token;
static PendingIntent pendingIntent;
public static void sendToApp(Bundle extras, Context context) {
Intent newIntent = new Intent();
newIntent.setClass(context, MapsActivity.class);
newIntent.putExtras(extras);
ShortcutBadger.applyCount(Content.getAppContext(), 0);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(newIntent);
}
public void onCreate() {
super.onCreate();
final String preferences = getString(R.string.preferences);
savedValues = getSharedPreferences(preferences, Context.MODE_PRIVATE);
// In later versions multi_process is no longer the default
if (VERSION.SDK_INT > 9) {
savedValues = getSharedPreferences(preferences, Context.MODE_MULTI_PROCESS);
}
gcm = GoogleCloudMessaging.getInstance(getBaseContext());
// Let AndroidMobilePushApp know we have just initialized and there may be stored messages
sendToApp(new Bundle(), this);
}
protected static void saveToLog(Bundle extras, Context context) {
SharedPreferences.Editor editor = savedValues.edit();
String numOfMissedMessages = context.getString(R.string.num_of_missed_messages);
int linesOfMessageCount = 0;
for (String key : extras.keySet()) {
String line = String.format("%s=%s", key, extras.getString(key));
editor.putString(key, line);
linesOfMessageCount++;
}
editor.putInt(context.getString(R.string.lines_of_message_count), linesOfMessageCount);
editor.putInt(context.getString(R.string.lines_of_message_count), linesOfMessageCount);
editor.putInt(numOfMissedMessages, savedValues.getInt(numOfMissedMessages, 0) + 1);
editor.commit();
String type = extras.getString("model");
String id = extras.getString("id");
String userId = extras.getString("user_id");
//postNotification(new Intent(context, MapsActivity.class), context);
if(type != null) {
if (type.equals("content")) {
Intent contentIntent = new Intent(context, ContentDetailActivity.class);
Log.v("userID", userId);
contentIntent.putExtra("contentId", id);
if (userId != null) {
contentIntent.putExtra("userId", userId);
}
postNotification(contentIntent, context);
} else if (type.equals("user")) {
Intent userIntent = new Intent(context, ProfileActivity.class);
userIntent.putExtra("userId", id);
postNotification(userIntent, context);
}
} else {
postNotification(new Intent(context, NotificationsActivity.class), context);
}
ShortcutBadger.applyCount(Content.getAppContext(), Integer.valueOf(savedValues.getInt(Content.getAppContext().getString(R.string.num_of_missed_messages), 0)));
}
protected static void postNotification(Intent intentAction, Context context) {
final NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
pendingIntent = PendingIntent.getActivity(context, 0, intentAction, PendingIntent.FLAG_UPDATE_CURRENT);
int numOfMissedMessages = 0;
String missedMessage = "";
if(savedValues != null){
missedMessage = savedValues.getString("message", "nothing there");
}
Log.v("NUMOFMISSEDMESSAGES", String.valueOf(numOfMissedMessages));
final Notification notification = new NotificationCompat.Builder(context).setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(missedMessage.substring(missedMessage.indexOf("=") + 1, missedMessage.length()))
.setContentText("")
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.build();
mNotificationManager.notify(R.string.notification_number, notification);
}
private void register() {
new AsyncTask() {
protected Object doInBackground(final Object... params) {
try {
String instanceId = InstanceID.getInstance(getApplicationContext()).getId();
//token = gcm.register(getString(R.string.project_number));
token = InstanceID.getInstance(getApplicationContext()).getToken(getString(R.string.project_number), INSTANCE_ID_SCOPE);
Log.i("registrationId", token);
} catch (IOException e) {
Log.i("Registration Error", e.getMessage());
}
return true;
}
@Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
new SendRegUserId().execute();
}
}.execute();
}
public IBinder onBind(Intent arg0) {
return null;
}
}
使用 Broadcast Receiver to receive the notification, and then send it to your Service。这将允许您在不启动您的应用程序的情况下向用户发送 notification
。
=========
编辑 1:
因此您的广播接收器需要启动服务而不是调用其方法。因此,在检查 intent 是否为 null 之后,类似以下内容:
ComponentName comp = new ComponentName(context.getPackageName(), YourIntentService.class.getName());
startWakefulService(context, (intent.setComponent(comp));
setResultCode(Activity.RESULT_OK);
另外,如果您在 phone 关闭后仍想收到通知,您的 Broadcast Receiver
应该扩展 WakefulBroadcastReceiver。
此外,您的 Service
应该是 IntentService。我认为 Android Studio 实际上附带了一些预制的 GCM 类 或 GCM 应用程序,它们实际上可以解决您遇到的这些小问题中的 90%。这是一个更好的起点。
查看 GCM docs 以获得更多帮助。
一些可能的解决方案-
1) 使用 BroadcastReceiver
2) 使用 onPause()、onResume() 方法
SharedPreferences prefs=PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
Intent messageReceivingIntent = new Intent(this,MessageReceivingService.class);
onCreate(){
//YOUR OWN CODE
prefs.getBoolean("service_started",false);
}
onPause(){
//YOUR OWN CODE
prefs.edit().putBoolean("service_started",true).apply();
startService(messageReceivingIntent);
}
onResume(){
//YOUR OWN CODE
if(prefs.getBoolean("service_started",false)){
stopService(new Intent(this, MessageReceivingService.class));
prefs.edit().putBoolean("service_started",false).apply();
}
}
3) 或者根据我的说法,最好的做法是实施 Firebase 云消息传递以进行通知。
看看这个 https://firebase.google.com/docs/cloud-messaging/
它大大减少了电池和服务器的工作量。这是 Google.
的一项全新服务
或者我认为您的服务代码中可能存在错误
在我的应用程序中,我启动了一项服务以在应用程序处于后台时接收通知 - 此服务强制我的应用程序在我停止后自动启动。我试图通过使用未决意图来解决问题,但它仍然发生。
这是我启动服务的意图:
Intent messageReceivingIntent = new Intent(this, MessageReceivingService.class);
messageReceivingIntent.putExtra("myUserId", myUserId);
Pending Inten messagePendingIntent = PendingIntent.getService(this, 0, messageReceivingIntent, PendingIntent.FLAG_UPDATE_CURRENT);
try {
// Perform the operation associated with our pendingIntent
messagePendingIntent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
如果我通过 externalreceiver 调用服务,我会得到一个 nullpointerexception。知道为什么吗?
这是我的 BroadcastReceiver 调用:
messageReceivingIntent = new Intent(this, MessageReceivingService.class);
messageReceivingIntent.putExtra("myUserId", myUserId);
messageReceivingIntent.setAction("com.example.androidtest");
sendBroadcast(messageReceivingIntent);
这是我的广播接收器:
public class ExternalReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(intent!=null){
Bundle extras = intent.getExtras();
if(!MapsActivity.inBackground){
MessageReceivingService.sendToApp(extras, context);
}
else{
MessageReceivingService.saveToLog(extras, context);
}
}
}
}
这是 MessageReceivingService
public class MessageReceivingService extends Service {
private GoogleCloudMessaging gcm;
public static SharedPreferences savedValues;
public static final String INSTANCE_ID_SCOPE = "GCM";
final String BASE_URL = "http://www.example.com/";
public String myUserId;
public String registeredUserId;
public String token;
static PendingIntent pendingIntent;
public static void sendToApp(Bundle extras, Context context) {
Intent newIntent = new Intent();
newIntent.setClass(context, MapsActivity.class);
newIntent.putExtras(extras);
ShortcutBadger.applyCount(Content.getAppContext(), 0);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(newIntent);
}
public void onCreate() {
super.onCreate();
final String preferences = getString(R.string.preferences);
savedValues = getSharedPreferences(preferences, Context.MODE_PRIVATE);
// In later versions multi_process is no longer the default
if (VERSION.SDK_INT > 9) {
savedValues = getSharedPreferences(preferences, Context.MODE_MULTI_PROCESS);
}
gcm = GoogleCloudMessaging.getInstance(getBaseContext());
// Let AndroidMobilePushApp know we have just initialized and there may be stored messages
sendToApp(new Bundle(), this);
}
protected static void saveToLog(Bundle extras, Context context) {
SharedPreferences.Editor editor = savedValues.edit();
String numOfMissedMessages = context.getString(R.string.num_of_missed_messages);
int linesOfMessageCount = 0;
for (String key : extras.keySet()) {
String line = String.format("%s=%s", key, extras.getString(key));
editor.putString(key, line);
linesOfMessageCount++;
}
editor.putInt(context.getString(R.string.lines_of_message_count), linesOfMessageCount);
editor.putInt(context.getString(R.string.lines_of_message_count), linesOfMessageCount);
editor.putInt(numOfMissedMessages, savedValues.getInt(numOfMissedMessages, 0) + 1);
editor.commit();
String type = extras.getString("model");
String id = extras.getString("id");
String userId = extras.getString("user_id");
//postNotification(new Intent(context, MapsActivity.class), context);
if(type != null) {
if (type.equals("content")) {
Intent contentIntent = new Intent(context, ContentDetailActivity.class);
Log.v("userID", userId);
contentIntent.putExtra("contentId", id);
if (userId != null) {
contentIntent.putExtra("userId", userId);
}
postNotification(contentIntent, context);
} else if (type.equals("user")) {
Intent userIntent = new Intent(context, ProfileActivity.class);
userIntent.putExtra("userId", id);
postNotification(userIntent, context);
}
} else {
postNotification(new Intent(context, NotificationsActivity.class), context);
}
ShortcutBadger.applyCount(Content.getAppContext(), Integer.valueOf(savedValues.getInt(Content.getAppContext().getString(R.string.num_of_missed_messages), 0)));
}
protected static void postNotification(Intent intentAction, Context context) {
final NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
pendingIntent = PendingIntent.getActivity(context, 0, intentAction, PendingIntent.FLAG_UPDATE_CURRENT);
int numOfMissedMessages = 0;
String missedMessage = "";
if(savedValues != null){
missedMessage = savedValues.getString("message", "nothing there");
}
Log.v("NUMOFMISSEDMESSAGES", String.valueOf(numOfMissedMessages));
final Notification notification = new NotificationCompat.Builder(context).setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(missedMessage.substring(missedMessage.indexOf("=") + 1, missedMessage.length()))
.setContentText("")
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.build();
mNotificationManager.notify(R.string.notification_number, notification);
}
private void register() {
new AsyncTask() {
protected Object doInBackground(final Object... params) {
try {
String instanceId = InstanceID.getInstance(getApplicationContext()).getId();
//token = gcm.register(getString(R.string.project_number));
token = InstanceID.getInstance(getApplicationContext()).getToken(getString(R.string.project_number), INSTANCE_ID_SCOPE);
Log.i("registrationId", token);
} catch (IOException e) {
Log.i("Registration Error", e.getMessage());
}
return true;
}
@Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
new SendRegUserId().execute();
}
}.execute();
}
public IBinder onBind(Intent arg0) {
return null;
}
}
使用 Broadcast Receiver to receive the notification, and then send it to your Service。这将允许您在不启动您的应用程序的情况下向用户发送 notification
。
=========
编辑 1:
因此您的广播接收器需要启动服务而不是调用其方法。因此,在检查 intent 是否为 null 之后,类似以下内容:
ComponentName comp = new ComponentName(context.getPackageName(), YourIntentService.class.getName());
startWakefulService(context, (intent.setComponent(comp));
setResultCode(Activity.RESULT_OK);
另外,如果您在 phone 关闭后仍想收到通知,您的 Broadcast Receiver
应该扩展 WakefulBroadcastReceiver。
此外,您的 Service
应该是 IntentService。我认为 Android Studio 实际上附带了一些预制的 GCM 类 或 GCM 应用程序,它们实际上可以解决您遇到的这些小问题中的 90%。这是一个更好的起点。
查看 GCM docs 以获得更多帮助。
一些可能的解决方案-
1) 使用 BroadcastReceiver
2) 使用 onPause()、onResume() 方法
SharedPreferences prefs=PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
Intent messageReceivingIntent = new Intent(this,MessageReceivingService.class);
onCreate(){
//YOUR OWN CODE
prefs.getBoolean("service_started",false);
}
onPause(){
//YOUR OWN CODE
prefs.edit().putBoolean("service_started",true).apply();
startService(messageReceivingIntent);
}
onResume(){
//YOUR OWN CODE
if(prefs.getBoolean("service_started",false)){
stopService(new Intent(this, MessageReceivingService.class));
prefs.edit().putBoolean("service_started",false).apply();
}
}
3) 或者根据我的说法,最好的做法是实施 Firebase 云消息传递以进行通知。
看看这个 https://firebase.google.com/docs/cloud-messaging/
它大大减少了电池和服务器的工作量。这是 Google.
的一项全新服务或者我认为您的服务代码中可能存在错误