我有一个Android服务(Servcie接口的实现),与我的真实应用程序相比,它运行在一个单独的进程上。不幸的是,当我离开我的真实应用程序(我点击按钮启动我的服务)并从任务管理器中滑出它时,我的服务也被杀死了。
我知道这里有很多这样的问题,但不知何故,任何问题都是针对我的具体星座中的问题,或者是模糊地回答。
所以在我的清单中我有类似的东西:
<application ...>
<activity .../>
<service Android:name="MyService"
Android:label="MyLabel"
Android:export="false"
Android:process=":MyRemoteProcessName" />
</application>
我首先使用IntentService,但也切换到自己的服务接口实现(消除了IntentService成为失败点),它看起来像:
public class MyService extends Service {
private ScheduledExecutorService scheduledWorker = Executors.newSingleThreadScheduledExecutor();
@Override
public void onStart() {
// Init components
startInForeground(this, MyNotification);
}
@Override
public int onStartCommand(Intent i, int startId) {
// Execute Work on Threadpool here
scheduledWorker.execute(new ScheduledStopRequest(this, startId), 5, TimeUnit.Minutes);
return START_REDILIVER_INTENT;
}
// Overwritten onDestroy-Method
@Override
public void onLowMemory() {
Log.e(LOG_TAG, "On Low Memory called!");
}
@Override
public IBind onBind() {
// Dont't want to let anyone bind here
return null;
}
// Simply tries to stop the service after e.g. 5 Minutes after a call
private static class MyRunnable implements Runnable {
// Constructor with params used in run method..
@Override
public void run() {
mReferenceToMyService.stopSelfResult(startId);
}
}
}
我在一个特殊按钮上的onClick-Listener中启动我的服务,具有明确的Intent,其类似于以下内容:
@Override
public void onClick(View v) {
Intent i = new Intent(this, MyService.class);
startService(i);
}
我的意图是在用户离开应用程序时保持服务运行,以便服务可以完成下载和存储一些重要数据。当用户再次回到我的应用程序时,他可以查看数据(这就是为什么我在一个单独的过程中执行它)。这可能吗?
我现在的假设是,Adnroid不知怎的注意到我的Serice只是被我的应用程序使用(由于在Manifest或显式调用中缺少IntentFilters而不是过滤器?!)因此当我的应用程序关闭时立即杀死它(即使作为ForegroundService运行,如上所示)。
对你来说这似乎是否可能,并且服务调用中的某些更改可能会解决此问题,或者我是否将服务的概念弄错了?
(最后一点:onLowMemory-Method没有被调用 - >没有日志条目。)
答案 0 :(得分:1)
所以,根据你的提示(以及我要寻找的新关键词)以及经过我自己的一些额外研究后,我想我已经解决了我的问题。在我的研究过程中,我发现了一篇关于这个主题的非常内容的博客文章,也许也适合你,这就是我想与你分享的原因:http://workshop.alea.net/post/2016/06/android-service-kill/。
在验证并完成本文中的步骤后,一切似乎都运行正常(因此startForeground似乎解决了问题)。我想在这里指出,我只测试了它,我的服务实例仍然在单独的进程中运行,所以清单条目如上所述。
在开始时让我困惑的实际事情是我的android工作室调试会话每次都被杀死,就在从最近的应用程序(菜单)中刷出我的应用程序之后。这让我觉得我的服务也被系统杀死了。但是根据文章(我已经在提供的回调方法中添加了一些日志)
打开我的应用
启动服务
刷掉应用
再次启动应用程序
再次致电服务,
我只收到了对方法的回调,好像我的服务仍在运行一样。明确了解DDMS(工具)也证明了我的第二个过程,因此我的服务仍然存在。验证了这一点后,我清除了所有应用数据并重复上述步骤(不包括第5步)。之后看过数据库,证明服务已经下载了数据。
对你好奇:
从最近的应用程序中刷出我的应用程序(因此调用了onTaskRemoved回调方法)会导致另一个问题。它以某种方式将onStartCommand的startId参数增加1,以便我的DelayedStopRequest出现故障并且不再停止我的服务。
这意味着:重复上述步骤1 - 3会使我在onStartCommand中收到startId = 1。通过稍后调用stopSelfResult(1)(这是最新的startId),它返回false并且服务继续运行。继续执行步骤4 + 5然后,使用startId = 3调用onStartCommand(但实际上应该是2!以某种方式跳过)。稍后使用参数3调用stopSelfResult(3)将再次停止服务(在屏幕截图中也可以看到)。
我希望到目前为止我的答案是正确的(可理解的),对你也有帮助。感谢您提供有益意见的所有答案,并指出了解决方案。我一直在使用的Android版本是:
4.1.2 - 果冻豆| API等级:16我还添加了来自DDMS的日志条目的截图(imgur拒绝我的上传,因此您将暂时拥有指向我的保管箱的链接): screenshots from logs from DDMS
答案 1 :(得分:0)
不幸的是,在单独的流程中运行服务对您没有帮助。我认为如果用户删除其任务,您无法阻止服务被关闭。但是,您可以重新启动覆盖onTaskRemoved的服务。请参阅此answer。
答案 2 :(得分:0)
如果你想在关闭应用程序后无限期地运行这个服务类..你应该使用Alaram Manager类..
public void scheduleAlarm() {
// Construct an intent that will execute the AlarmReceiver
Intent intent = new Intent(this, LocationListnerServiec.class);
// Create a PendingIntent to be triggered when the alarm goes off
final PendingIntent pIntent = PendingIntent.getBroadcast(this, MyAlarmReceiver.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Setup periodic alarm every 5 seconds
long firstMillis = System.currentTimeMillis(); // alarm is set right away
AlarmManager alarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
// First parameter is the type: ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC_WAKEUP
// Interval can be INTERVAL_FIFTEEN_MINUTES, INTERVAL_HALF_HOUR, INTERVAL_HOUR, INTERVAL_DAY
alarm.setRepeating(AlarmManager.RTC_WAKEUP, firstMillis,
60000, pIntent);
}
使用此方法继续检查服务类是打开还是关闭。使用此方法您的服务类将在销毁应用程序后继续工作。