我已经创建了一个服务来定期获取设备的当前位置。即使从最近打开的应用程序中清除了应用程序,我也希望该服务在后台运行。目前,该服务仅在后台运行,直到应用程序出现在最近打开的应用程序中,但在应用程序被刷掉(或以其他方式杀死)时立即停止。 我已经尝试过堆栈溢出中的各种帮助,但我无法解决这个问题。请帮忙。这是我的服务代码。
[array([1, 1, 1]), array([1, 1, 1]), array([2, 2, 2])]
答案 0 :(得分:20)
覆盖服务中的onTaskRemoved()并使用警报管理器再次启动服务。以下是来自我们的应用程序的代码,它做同样的工作并正常工作:
@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Log.d(TAG, "TASK REMOVED");
PendingIntent service = PendingIntent.getService(
getApplicationContext(),
1001,
new Intent(getApplicationContext(), MyService.class),
PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service);
}
由于您可能希望定期发送位置,即使服务在内存不足(或出于任何原因)被杀死的情况下,我建议您处理uncaughtException以在N秒后重新启动它。这就是我们在完美运行的应用程序中所做的工作:
private Thread.UncaughtExceptionHandler defaultUEH;
private Thread.UncaughtExceptionHandler uncaughtExceptionHandler = new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
Log.d(TAG, "Uncaught exception start!");
ex.printStackTrace();
//Same as done in onTaskRemoved()
PendingIntent service = PendingIntent.getService(
getApplicationContext(),
1001,
new Intent(getApplicationContext(), MyService.class),
PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service);
System.exit(2);
}
};
注意:我认为我记得我在Kitkat上验证过,START_STICKY无法在Kitkat和更高的API级别上运行。请自行验证。
更多强>
当您定期发送loc时,您可能必须考虑深度睡眠模式。为了让您在深度睡眠中工作,请将WakefulBroadcastReceiver与AlarmManager结合使用。看看我的其他帖子How to use http in deep sleep mode。
<强>更新强>
如果用户从“设置”中“强制停止”应用程序,则此解决方案不起作用(实际上不需要工作)。事实上这很好,因为如果用户自己想要停止应用程序,重新启动服务并不是一个好方法。所以,没关系。
答案 1 :(得分:0)
将return Service.START_NOT_STICKY;
替换为return START_STICKY;
答案 2 :(得分:0)
如果您仅想要从最近任务中杀死后重新启动服务,请使用
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
如果您使用START_STICKY
,当您从最近的任务中删除应用时,您的服务将被终止(onTaskRemoved
被解雇,onDestroy
不被解雇那么它会再次自动启动(onCreate
被解雇,onStartComand
已被解雇)
答案 3 :(得分:-1)
我使用 android 9 ,该解决方案部分对我有效。
我有一个前台服务案例(工作24/7),我想在应用程序崩溃后重新启动。
捕获到事件render() {
return (
/**
* @see https://github.com/reduxjs/react-redux/blob/master/docs/api/Provider.md
*/
<Provider store={store}>
{/**
* PersistGate delays the rendering of the app's UI until the persisted state has been retrieved
* and saved to redux.
* The `loading` prop can be `null` or any react instance to show during loading (e.g. a splash screen),
* for example `loading={<SplashScreen />}`.
* @see https://github.com/rt2zz/redux-persist/blob/master/docs/PersistGate.md
*/}
<PersistGate loading={<SplashScreen />} onBeforeLift={this.onBeforeLift} persistor={persistor}>
{this.state.gateLifted ? <RootScreen LoginStatus={this.state.isLogin} /> : <SplashScreen />}
{/* {<RootScreen LoginStatus={this.state.isLogin} />} */}
</PersistGate>
</Provider>
)
}
时,除了uncaughtExceptionHandler
事件外,应用程序也被冻结,在最新的Android版本中(我认为是O +),它不再起作用。
如果您需要更多活动的解决方案,那么我的应用程序只有一个活动有片段,只需使用this链接即可。
为了解决该问题,我添加了一个功能,该功能可以检查活动是否正常运行(以终止活动),以及一些终止活动的说明:
public void onTaskRemoved(Intent rootIntent) {
添加到清单:
class MyApplication : Application() {
private var currentActivity: Activity? = null
override fun onCreate() {
super.onCreate()
StorageManager.init()
this.registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
override fun onActivityPaused(activity: Activity) {
}
override fun onActivityStarted(activity: Activity) {
currentActivity = activity
}
override fun onActivityDestroyed(activity: Activity) {
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
}
override fun onActivityStopped(activity: Activity) {
currentActivity = null
}
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
}
override fun onActivityResumed(activity: Activity) {
}
})
Thread.setDefaultUncaughtExceptionHandler { _, e ->
// Close current activity
currentActivity?.finish()
val service : PendingIntent? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Start service in Oreo and latest
PendingIntent.getForegroundService(
applicationContext,
8888,
Intent(applicationContext, SensorService::class.java),
PendingIntent.FLAG_ONE_SHOT)
} else {
// Start service in Nougat and older
PendingIntent.getService(
applicationContext,
8888,
Intent(applicationContext, MyService::class.java),
PendingIntent.FLAG_ONE_SHOT)
}
// The great solution introduced by @cgr
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service)
// Kill the current application process to avoid freezing activity
android.os.Process.killProcess(android.os.Process.myPid())
exitProcess(10)
}
}
}