Android 应用程序从应用程序托盘中移除后服务的进程被杀死
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20592366/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
The process of the service is killed after the application is removed from the application tray
提问by geekoraul
I am starting a service (or re-starting the running service) when an activity is launched, using :
当活动启动时,我正在启动服务(或重新启动正在运行的服务),使用:
Intent intent = new Intent(this, MyService.class);
startService(intent);
Intent intent = new Intent(this, MyService.class);
startService(intent);
Later on based on certain actions, the same activity binds to the service using
稍后基于某些操作,相同的活动使用
bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE);
And when the activity is destroyed, I call
当活动被破坏时,我打电话
unbindService(mConnection);
Earlier, the service used to restart when I killed the same activity/application from the application tray and showed the "message 1 process 1 service running" under running apps.
早些时候,当我从应用程序托盘中杀死相同的活动/应用程序并在正在运行的应用程序下显示“消息 1 进程 1 服务正在运行”时,该服务会重新启动。
Now, the service does not restart on killing the same activity/application.
现在,服务不会在杀死相同的活动/应用程序时重新启动。
And I get the message "0 process 1 service running", which means the service is actually not running.
我收到消息"0 process 1 service running",这意味着该服务实际上没有运行。
The service does not restart on application being closed. My application consists of one activity. Also the service is successfully started when launched after a system boot.
该服务不会在应用程序关闭时重新启动。我的申请由一项活动组成。在系统启动后启动时,该服务也成功启动。
Why does the process of the service gets killed when I start it using startService() ??
为什么当我使用 startService() 启动它时服务的进程会被杀死??
edit
编辑
The service used to re-start earlier after i closed the app from the application tray. But now suddenly with the SAME code, it doesn't. It happens with other apps too when i close them. eg.
在我从应用程序托盘关闭应用程序后,该服务过去常常重新启动。但是现在突然使用相同的代码,它没有。当我关闭它们时,它也会发生在其他应用程序上。例如。
回答by geekoraul
Here is a workaround I came across and works well for re-starting a service if its process is killed on closing the application. In your service, add the following code.
这是我遇到的一种解决方法,如果它的进程在关闭应用程序时被终止,则它可以很好地重新启动服务。在您的服务中,添加以下代码。
I came across this workaround in thisthread.
我在这个线程中遇到了这个解决方法。
@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);
}
Seems to be a bug that the process of the application is killed. There is no point for a service to run if its process is killed.
似乎是应用程序进程被杀死的错误。如果其进程被终止,则服务没有意义运行。
回答by Nick Jian
Please be aware of that: onDestroy is not always called.You should not put code that way.
When activity forced closed or closed by system abnormally, onDestroy is not getting called.
请注意:onDestroy 并不总是被调用。你不应该那样放置代码。
当系统异常强制关闭或关闭活动时,不会调用 onDestroy。
回答by Sam
Unfortunately, this is a complicated problem due to the way Android works. There are a number of strategies that each work around different parts of the problem. For best results, combine multiple strategies together.
不幸的是,由于 Android 的工作方式,这是一个复杂的问题。有许多策略可以解决问题的不同部分。为获得最佳效果,请将多种策略组合在一起。
Note that some of these strategies may no longer be necessary in more recent Android versions.
请注意,在更新的 Android 版本中,其中一些策略可能不再需要。
1. Start an activity
1.开始活动
What to do
该怎么办
Taken from Foreground service killed when receiving broadcast after acitivty swiped away in task list:
In the foreground service:
@Override public void onTaskRemoved( Intent rootIntent ) { Intent intent = new Intent( this, DummyActivity.class ); intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK ); startActivity( intent ); }
In the manifest:
<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" />
在前台服务中:
@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" />
(If your service is in a different process then set this activity's process to the same one.)
(如果您的服务处于不同的流程中,则将此活动的流程设置为相同的流程。)
In DummyActivity.java:
public class DummyActivity extends Activity { @Override public void onCreate( Bundle icicle ) { super.onCreate( icicle ); finish(); } }
在 DummyActivity.java 中:
public class DummyActivity extends Activity { @Override public void onCreate( Bundle icicle ) { super.onCreate( icicle ); finish(); } }
Side effects
副作用
Causes the recents activity to close. Normally, swiping away an app doesn't close the recents activity.
导致最近的活动关闭。通常,滑动应用程序不会关闭最近的活动。
Disadvantages
缺点
This only takes effect when the dummy activity starts, which may take half a second or more, so this still leaves the service open to being killed for a bit.
这仅在虚拟活动开始时生效,这可能需要半秒或更长时间,因此这仍然会使服务被杀死一段时间。
Explanation
解释
When you remove/swipe your app away, a flag called waitingToKill
is set. While this flag is set, Android may kill the process at any point in the future, such as when you receive a broadcast. Starting an activity clears this flag.
当您移除/滑动您的应用程序时,waitingToKill
会设置一个名为set的标志。设置此标志后,Android 可能会在未来的任何时候终止该进程,例如当您收到广播时。启动活动会清除此标志。
2. Spam a BroadcastReceiver
with foreground broadcasts
2.BroadcastReceiver
用前台广播发送垃圾邮件
What to do
该怎么办
Merge this into your service code:
将其合并到您的服务代码中:
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);
}
Create a dummy broadcast receiver:
创建一个虚拟广播接收器:
public class DummyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {}
}
Add the receiver to your manifest:
将接收器添加到您的清单中:
<receiver android:name=".DummyReceiver" />
Side effects
副作用
May cause a slight (~250ms) delay/hang when the task is removed from the recents screen.
从最近屏幕中删除任务时,可能会导致轻微(~250 毫秒)延迟/挂起。
Disadvantages
缺点
This only keeps the process alive while it is receiving the broadcasts. the waitingToKill
flag is still set, so the process may still be killed afterwards, such as when a broadcast is received.
这只会让进程在接收广播时保持活动状态。该waitingToKill
标志仍然设置,因此该进程可能仍会在之后被终止,例如在接收到广播时。
Explanation
解释
If your process isn't running in foreground priority, Android will try to kill it immediately. Receiving foreground broadcasts temporarily prevents this, resulting in the waitingToKill
flag being set instead.
如果您的进程没有以前台优先级运行,Android 将尝试立即终止它。接收前台广播暂时阻止了这种情况,导致waitingToKill
设置了标志。
3. Don't bind to services
3. 不要绑定到服务
回答by Ajith K P
onDestroy is not always called.The Main problem in your case is ur unable to start the service when app closed,that time android OS(In Some OS) will kill the service, If you are not able to restart the service then call a alarm manger to start the reciver like this,
onDestroy 并不总是被调用。您的情况的主要问题是您无法在应用程序关闭时启动该服务,那时 android 操作系统(在某些操作系统中)将终止该服务,如果您无法重新启动该服务,则调用警报管理器来启动接收器,例如这个,
Manifest is,
体现的是,
<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>
IN Main Activty start alarm manger in this way,
IN Main Activty 以这种方式启动报警管理器,
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);
this will call reciver and reciver is,
这将调用接收器,接收器是,
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;
}
}
And this Alaram reciver calls once when android app is opened and when app is closed.SO the service is like this,
当android应用程序打开和应用程序关闭时,这个Alaram接收器调用一次。所以服务是这样的,
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");
}
}
回答by lego king
I know this question is old but I recently encountered this problem and suddenly my service get stopped on closing app. Earlier it was working fine. This problem wasted my lot of time. To others who have similar problem make sure that YOUR BACKGROUND DATA RESTRICTION IS OFF. This was the problem I had and it actually makes sense as when background data is Restricted background process won't run.
我知道这个问题很老,但我最近遇到了这个问题,突然关闭应用程序时我的服务停止了。早些时候它工作正常。这个问题浪费了我很多时间。对于有类似问题的其他人,请确保您的后台数据限制关闭。这是我遇到的问题,它实际上是有道理的,因为当后台数据受到限制时,后台进程将不会运行。
回答by aljuaid86
when there is no binding to a service or well established foreground then android system recognize the service as unused overloading service that should be shut down. Here is the best way to maintain your service even if the app is closed: AlarmManager or Service
当没有绑定到服务或建立良好的前台时,android 系统会将服务识别为未使用的重载服务,应该关闭。即使应用程序关闭,以下也是维护服务的最佳方式:AlarmManager 或 Service