我正在使用oreo 8.1.0。
我面临一个奇怪的问题,在stackoverflow上找不到我的解决方案,因此我正在写这个问题。我知道一个解决方案,可以通过前台服务实现该解决方案,但是在我的应用程序上下文中我发现通知用户不友好。
我将用两种情况来描述我的问题。
情况1:
当用户通过单击图标打开我的应用程序并将其从最近的应用程序中删除时,服务会自动重新启动。很好。
情况2: 我的应用程序已关闭,并且不在最近的应用程序中。 当用户复制文本时,我的服务将启动我的应用程序的活动之一,但是当他从最近的应用程序中将其删除时,则我的服务将永久停止。
所以我的问题出在第二种情况,我不希望我的服务被杀死。即使它被杀死,我也希望它重新启动。
我尝试了在stackoverflow上提到的所有方法,例如使用START_STICKY和onTaskRemoved,但是我无法使其工作。
即使我尝试杀死每当用户单击“最近使用的应用程序”按钮时的活动,并以编程方式将其从最近使用的应用程序中删除,但这也不起作用。 尽管即使在第二种情况下,当用户使用“后退”按钮杀死我的应用程序时,这也会重新启动服务。
这部分代码来自用户复制某些文本时打开的活动。
@Override
public void finish() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
super.finishAndRemoveTask();
} else {
super.finish();
}
}
这部分代码来自启动活动的服务。
@Override
public void onTaskRemoved(Intent rootIntent){
Log.d("testing 12","onTaskRemoved");
Intent restartServiceTask = new Intent(getApplicationContext(),CBWatcherService.class);
restartServiceTask.setPackage(getPackageName());
PendingIntent restartPendingIntent =PendingIntent.getService(getApplicationContext(), 1,restartServiceTask, PendingIntent.FLAG_ONE_SHOT);
AlarmManager myAlarmService = (AlarmManager) getApplicationContext().getSystemService(this.ALARM_SERVICE);
myAlarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartPendingIntent);
super.onTaskRemoved(rootIntent);
}
@Override
public int onStartCommand(Intent intent,int flag,int startId){
super.onStartCommand(intent, flag, startId);
return START_STICKY;
}
编辑1
我只需要该服务即可继续工作。以下是在我的应用案例中不会妨碍用户体验的内容
1.调用onPause时以编程方式自行杀死活动,这样就可以使服务不被杀死
2.可以在几秒钟内显示通知
3.可以重新启动服务
答案 0 :(得分:0)
Android Oreo提供了一种范式转换,以限制后台服务执行。它经常受到批评,影响电池寿命,性能和安全性。如上面评论中所述,还有其他方法,例如JobScheduler。
为JobScheduler模式重构服务可能会涉及很多。建议您考虑将IntentService从Android支持v4库更改为JobintentService。它在Oreo和更高版本的目标上使用JobScheduler,但在较旧的设备上恢复为较旧的IntentService设计。您只需要在Service实现中用#boolean mask
m = df['label'].str.contains("###", na=False)
#helper column with repalce non ### values to NaNs and repalce it by last non NaN value
df['new'] = df['label'].where(m).ffill()
#remove rows with same values
df = df[df['label'] != df['new']].copy()
#extract new column and add to original
df['label'] = df.pop('new').str.lstrip('#') + ' ' + df['label']
print (df)
label
1 12345 LABEL text
2 12345 LABEL text
4 12213 LABEL text
5 12213 LABEL text
替换对print (df)
label value
0 ###12345 NaN
1 LABEL text
2 LABEL text
3 ###12213 NaN
4 LABEL text
5 LABEL text
m = df['label'].str.contains("###", na=False)
df['new'] = df['label'].where(m).ffill()
df = df[df['label'] != df['new']].copy()
df['label'] = df.pop('new').str.lstrip('#') + ' ' + df['label']
print (df)
label value
1 12345 LABEL text
2 12345 LABEL text
4 12213 LABEL text
5 12213 LABEL text
的覆盖即可。
添加
onHandleIntent
到AndroidManifest.xml中的服务声明。添加
onHandleWork
但是,说了这么多,通读您的问题,在我看来,您的基本抱怨是有关前台服务的装饰性问题,需要通知。在我看来,您的解决方案是只使用Context.startForegroundService,或者确保您的服务已绑定。无论哪种方式,用户都可以看到服务正在运行的内容。您将发现尝试颠覆Android设计决策需要艰苦的工作;更好地接受它-他们希望您从现在开始显示这些通知。
即使您无法完全避免使用那些通知图标,仍然为新的Android目标更新代码仍然是一种好习惯。
答案 1 :(得分:0)
这是问题
每当我的服务用来启动活动时,我的服务就曾经在活动开始后被破坏。
为什么onTaskRemoved无法正常工作?
我正在做的事情无法正常工作,因为我的服务曾经被破坏,因此无法监听onTaskRemoved。
我如何解决?
解决此问题的方法是检查活动(由服务启动)以检查服务是否处于活动状态。就我而言,服务被销毁了。因此,如果该服务还没有运行,我需要再次启动该服务。
它甚至符合OREO设计模式,因为我们可以在应用程序处于前台状态时启动后台服务,并且即使活动被破坏,该服务也将保持活动状态。
在奥利奥(Oreo),尽管一段时间后服务被销毁,但这是一个不同的问题。