应用程序从应用程序托盘中删除后,服务的进程被终止

我开始一项服务(或重新启动正在运行的服务),当一项活动启动时,使用:

Intent intent = new Intent(this, MyService.class); startService(intent);

稍后根据某些操作,相同的活动将绑定到使用的服务

 bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE); 

当活动被破坏时,我打电话

 unbindService(mConnection); 

之前,当我从应用程序托盘中杀掉相同的活动/应用程序并在运行的应用程序下显示“消息1进程1服务正在运行”时,服务用于重新启动。

现在,该服务不会重新启动杀死相同的活动/应用程序。

我得到消息“0进程1服务运行” ,这意味着服务实际上没有运行。

该服务在应用程序closures时不重新启动。 我的应用程序包含一个活动。 此外,服务在系统启动后启动时成功启动。

为什么当我使用startService()启动它时,服务的进程会被杀死?

编辑

在我从应用程序托盘closures应用程序之后,用于重新启动的服务。 但现在突然用同样的代码,它不。 它也发生在其他应用程序,当我closures它们。 例如。

在这里输入图像描述

这是我遇到的一种解决方法,如果在closures应用程序时终止了进程,则可以重新启动服务。 在您的服务中,添加以下代码。

我在这个线程中遇到了这个解决方法。

 @Override public void onTaskRemoved(Intent rootIntent){ Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass()); restartServiceIntent.setPackage(getPackageName()); PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT); AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE); alarmService.set( AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 1000, restartServicePendingIntent); super.onTaskRemoved(rootIntent); } 

似乎是应用程序的进程被终止的错误。 如果一个服务被终止了,那么服务就没有意义了。

请注意: onDestroy并不总是被调用。 你不应该这样写代码。
当系统exception强制closures或closures活动时,onDestroy不会被调用。

不幸的是,由于Android的工作方式,这是一个复杂的问题。 有许多策略可以解决问题的不同部分。 为获得最佳效果,请将多个策略组合在一

请注意,在更新的Android版本中,其中一些策略可能不再需要。

1.开始一个活动

该怎么办

从任务列表中删除活动之后接收广播时被杀的前台服务采取:

在前台服务:

  @Override public void onTaskRemoved( Intent rootIntent ) { Intent intent = new Intent( this, DummyActivity.class ); intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK ); startActivity( intent ); } 

在清单中:

  <activity android:name=".DummyActivity" android:theme="@android:style/Theme.NoDisplay" android:enabled="true" android:allowTaskReparenting="true" android:noHistory="true" android:excludeFromRecents="true" android:alwaysRetainTaskState="false" android:stateNotNeeded="true" android:clearTaskOnLaunch="true" android:finishOnTaskLaunch="true" /> 

(如果您的服务处于不同的过程,则将此活动的过程设置为同一过程。)

在DummyActivity.java中:

  public class DummyActivity extends Activity { @Override public void onCreate( Bundle icicle ) { super.onCreate( icicle ); finish(); } } 

副作用

导致最近的活动closures。 通常情况下,移除应用程序不会closures最近的活动。

缺点

这只有在虚拟活动开始时才会生效,这可能需要半秒或更长时间,所以这仍然使服务开放,被杀了一下。

说明

当你删除/刷你的应用程序,一个名为waitingToKill的标志被设置 。 设置此标志时,Android可能会在将来的任何时候终止进程,例如收到广播时 。 开始一个活动清除这个标志。

2.使用前台广播垃圾邮件广播接收器

该怎么办

将其合并到您的服务代码中:

 if (Build.VERSION.SDK_INT >= 16) { Intent intent = new Intent(this, DummyReceiver.class); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); //This seems to be timing-related; the more times we do this, //the less likely the process gets killed for (int i = 0; i < 50; ++i) sendBroadcast(intent); } 

创build一个虚拟广播接收器:

 public class DummyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) {} } 

将接收器添加到您的清单:

 <receiver android:name=".DummyReceiver" /> 

副作用

从最近的屏幕中删除任务时,可能会导致轻微的(〜250ms)延迟/挂起。

缺点

这只在收到广播时才使这个进程保持活跃状态​​。 waitingToKill标志仍然被设置 ,所以过程可能在之后仍然被杀死,例如当收到广播时。

说明

如果您的进程没有以前台优先级运行, Android会立即尝试杀死它 。 暂时接收前台广播会阻止这种情况发生,导致waitingToKill标志被设置。

3.不要束缚服务

绑定到服务似乎增加了当任务被移除时服务进程被立即终止的可能性。

我知道这个问题是旧的,但我最近遇到这个问题,突然我的服务停止closures应用程序。 此前它工作正常。 这个问题浪费了我很多时间。 对于其他有类似问题的人,请确保您的背景数据限制已closures。 这是我的问题,它实际上是有道理的,因为当背景数据是受限制的后台进程将无法运行。

onDestroy并不总是被调用。 在你的情况的主要问题是你无法启动服务,当应用程序closures,那时android操作系统( 在某些操作系统 )将终止服务,如果你不能够重新启动服务,然后调用一个警报pipe理器来启动像reciver这个,

清单是,

  <service android:name=".BackgroundService" android:description="@string/app_name" android:enabled="true" android:label="Notification" /> <receiver android:name="AlarmReceiver"> <intent-filter> <action android:name="REFRESH_THIS" /> </intent-filter> </receiver> 

在主要活动启动闹铃pipe理器这样,

 String alarm = Context.ALARM_SERVICE; AlarmManager am = (AlarmManager) getSystemService(alarm); Intent intent = new Intent("REFRESH_THIS"); PendingIntent pi = PendingIntent.getBroadcast(this, 123456789, intent, 0); int type = AlarmManager.RTC_WAKEUP; long interval = 1000 * 50; am.setInexactRepeating(type, System.currentTimeMillis(), interval, pi); 

这会叫reciver和reciver是,

 public class AlarmReceiver extends BroadcastReceiver { Context context; @Override public void onReceive(Context context, Intent intent) { this.context = context; System.out.println("Alarma Reciver Called"); if (isMyServiceRunning(this.context, BackgroundService.class)) { System.out.println("alredy running no need to start again"); } else { Intent background = new Intent(context, BackgroundService.class); context.startService(background); } } public static boolean isMyServiceRunning(Context context, Class<?> serviceClass) { ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE); if (services != null) { for (int i = 0; i < services.size(); i++) { if ((serviceClass.getName()).equals(services.get(i).service.getClassName()) && services.get(i).pid != 0) { return true; } } } return false; } } 

而这个Alaram reciver在Android应用程序被打开和应用程序closures时会调用一次。这个服务就是这样,

 public class BackgroundService extends Service { private String LOG_TAG = null; @Override public void onCreate() { super.onCreate(); LOG_TAG = "app_name"; Log.i(LOG_TAG, "service created"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(LOG_TAG, "In onStartCommand"); //ur actual code return START_STICKY; } @Override public IBinder onBind(Intent intent) { // Wont be called as service is not bound Log.i(LOG_TAG, "In onBind"); return null; } @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) @Override public void onTaskRemoved(Intent rootIntent) { super.onTaskRemoved(rootIntent); Log.i(LOG_TAG, "In onTaskRemoved"); } @Override public void onDestroy() { super.onDestroy(); Log.i(LOG_TAG, "In onDestroyed"); } } 

当没有绑定到一个服务或build立良好的前景,然后android系统将服务识别为未使用的应该closures的重载服务。 即使应用程序已closures,以下是维护您的服务的最佳方法: AlarmManager或Service