如何在Android上运行无限服务(前台服务被杀死)?

4
我创建了一个黏性前台服务,每次它被杀死时都会重新启动,看起来它运行得很好,但我注意到在某些情况下(例如当操作系统将其杀死时),它就不会重新启动。如何让它在每次被杀死时都重新启动?我希望这个服务始终运行。 I want it to run like those 就像那些服务一样。
以下是我的前台服务 onStartCommand:
public int onStartCommand(Intent intent, int flags, int startId) {

    Intent notificationIntent = new Intent(this, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this,
            0, notificationIntent, 0);

    Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("InsiteMobile Service")
            .setContentText("Run the app by clicking here")
            .setSmallIcon(R.drawable.ic_launcher)
            .setContentIntent(pendingIntent)
            .build();
    Log.i("InsiteMobileLog", "Service Started");
    startForeground(1, notification);

    //do heavy work on a background thread
    //stopSelf();

    return START_STICKY;
}

这是我在MainActivity onCreate()中调用服务的方式:

public void startService() {

    Intent serviceIntent = new Intent(this, AppService.class);
    serviceIntent.putExtra("inputExtra", "InsiteMobileService");

    ContextCompat.startForegroundService(this, serviceIntent);
}

1
幸运的是,你不能这样做 - 我真的不想拥有一个“不朽”的恶意服务。 - pskink
我写了我使用startForeground()。 但在某些情况下,该服务会被操作系统杀死,并且在这种情况下不会重新启动。 - Ohados
请不要将自己的应用与大公司的应用相比,他们与谷歌有协议并且他们的应用已被列入白名单。 - Tim
我猜@Melih Toksari写的就是这个问题,在Oreo中前台服务确实会被杀死。 我的代码很通用。我在MainActivity中像这样启动服务:public void startService() { Intent serviceIntent = new Intent(this, AppService.class); serviceIntent.putExtra("inputExtra", "InsiteMobileService"); ContextCompat.startForegroundService(this, serviceIntent); }并且我在onStartCommand()中使用startForeground()并返回START_STICKY。 - Ohados
我猜是这样,因为在MainActivity的Oncreate中调用了该服务,并且我总是收到有关该服务的通知,这意味着它正在正常运行。唯一的问题是当操作系统决定终止该服务时,它就不会再回来了。 - Ohados
显示剩余5条评论
4个回答

5
目前我正在处理一个需要在后台运行服务的项目。我们需要注意以下几点:
1. 在服务的 onDestroy() 方法中,使用 startService 意图再次启动它自己。
2. 对于操作系统及以下版本,请在 onStartCommand() 方法中使用 onTaskRemoved(intent);
3. 在 onStartCommand() 中返回 START_STICKY
另外,您还需要了解一件事情,设备的电话管理器(phone manager)基于电池优化(battery optimization)策略会倾向于杀死后台进程。请检查测试设备的电话管理器设置,然后再试一次。
此外,如果您要使用通知(notification)来保持服务活动状态,则需要重新检查通过应用程序发送通知的权限。

2
你能再解释一下第二个问题吗?我没听懂。还有,你能详细说明一下手机管理器的事情吗? - Ohados
START_STICKY对于Android Kitkat及以下版本无效,因此我们必须使用onTaskRemove()来使服务在尽可能多的设备上后台运行。 - Abhijit
几乎所有的设备都有电话管理器,以确保手机运行顺畅。为此,它会关闭后台服务以及系统中空闲一段时间的应用程序。因此,在测试您的应用程序时,只需查找电话管理器设置/电池优化设置,并通过编码来解决它们。 - Abhijit

1

Android Oreo在服务方面有一些限制。您可以查看此线程https://dev59.com/Hafja4cB1Zd3GeqPsTrI#47611385。此外,Evernote团队提供了良好的,可与Android Oreo(API级别26)兼容的后台服务。JobScheduler库提供使用JobInfo.Builder.setPeriodic(long intervalMillis, long flexMillis)方法的定期服务。此服务的最短工作时间为15分钟。一些前台服务教程:

  1. https://blog.klinkerapps.com/android-o-background-services/
  2. https://medium.com/exploring-android/exploring-background-execution-limits-on-android-oreo-ab384762a66c

1
你无法创建一个始终在最新操作系统版本上运行的服务。但是,你可以使用具有通知的前台服务,它无法被关闭。原则是用户应始终看到你的应用正在运行并消耗操作系统资源。

2
我写了我使用startForeground()。 但在某些情况下,该服务会被操作系统杀死,并且在这种情况下不会重新启动。 - Ohados

0

我也在做一个需要不死服务的项目,所以你应该使用作业调度程序来实现这个目的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接