在Android Marshmallow 6.0及以上的设备上,后台服务停止工作。

3

当应用程序进入后台(通过按下Home键),当屏幕关闭后,Android M (6.0)手机上的后台服务会在15-20分钟后停止。尽管在Lollipop(5.0)手机上正常运行。


当设备内存不足时,为释放内存而使其“停止”。 - HB.
阅读有关Android M、N等版本的背景限制的内容。 - ADM
请问您的代码是在哪个设备上测试您的应用程序的?请将代码放入问题中。 - Jaydip Kalkani
我正在测试的设备是HTC U Play(6.0),具有4 GB RAM。手机上没有运行其他应用程序。因此,内存不足不能是问题所在。还有一件事,这也发生在其他6.0+设备上。 - Akhtar Khan
在onStartCommand()中应该返回START_STICKY。即使由于内存不足或其他任何原因而被操作系统停止,它也会重新启动您的服务。 - Jaydip Kalkani
@JaydipKalkani 我已经添加了START_STICKY,但它并没有起作用。 - Akhtar Khan
3个回答

3

Android M引入了Doze和App Standby功能,限制后台服务以保护电池。有关如何处理Doze的详细信息,请参见官方Android培训手册。

编辑: 虽然不属于最初的问题,但如果您想支持Android O,您还需要牢记新的Background Execution Limits。有关如何执行此操作的详细信息,请参见官方Android培训手册。


1
以上主题对我也帮助很大。我还按照上述主题添加了Manfiest权限REQUEST_IGNORE_BATTERY_OPTIMIZATIONS。我做的第二个更改是使用setAndAllowWhileIdle设置闹钟。现在它在每台手机上都可以工作。谢谢!! - Akhtar Khan
测试过使用 5.0、6.0、7.0 手机,运行得非常好。但是在 Android 8.0 上仍然无法正常工作! - Akhtar Khan
你最初的问题是关于它在Android 6上停止工作的原因,但我已经更新了我的答案,并提供了为什么它在Android 8上不起作用的信息。 - Sander
我无法在Android 8.0上解决这个问题。请有人帮我在那里解决它。 - Akhtar Khan

1

根据您在评论中提到的,您已经将服务设为START_STICKY,但是在后台它在Android Marshmallow设备上无法运行。

  1. 您应该确保您测试应用程序的设备包含自动启动权限。如果是,则必须授予您的应用程序自动启动权限,否则您的服务无法在后台运行。
  2. 即使按照上述步骤操作后问题仍未解决,我建议您按以下方式使用Alarmmanager来启动您的服务。

在注册服务的位置使用Alarmmanager,如下所示:

AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
                    Intent intent = new Intent(context,ServiceStarter.class);
                    PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 1545, intent, 0);
                    alarmMgr.set(AlarmManager.RTC,
                            System.currentTimeMillis() + 5000, alarmIntent);

然后在ServiceStarter广播接收器中执行以下操作...

public class ServiceStarter extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        if (!ConstantData.isServiceRunning(YourService.class , context)){ //check service is running or not
            context.startService(new Intent(context , YourService.class));
        }
        else{
            Log.e("service-->>" , "service already running");
        }


        try {
        //set alarm for next 5 seconds...this will set alarm for every next 5 seconds

            AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
            Intent intent2 = new Intent(context, ServiceStarter.class);
            PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 1545, intent2, 0);
            alarmMgr.set(AlarmManager.RTC,
                    System.currentTimeMillis() + 5000, alarmIntent);

        } catch (Exception e) {

        }
    }
}

"

ConstantData.isServiceRunning() 方法:

"
public static boolean isServiceRunning(Class<?> serviceClass, Context context) {
        ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (serviceClass.getName().equals(service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }

以上代码将每5秒触发alarmmanager,并检查服务是否正在运行。如果服务正在运行,则不执行任何操作,如果服务已停止,则会重新启动服务。

1
它帮助我解决了问题。非常感谢!! - Akhtar Khan
是的,我知道这个方法,但这是唯一能在每个设备上都能运行的方式。这种方法可以在大多数设备上运行,甚至包括小米、vivo和oppo等自带优化机制的定制操作系统设备。如果您有更好的解决方案,可以在所有设备上运行,请告诉我。@Sander - Jaydip Kalkani
这段代码不适用于所有设备,从BroadcastReceiver调用context.startService将在Android 8及更高版本上导致IllegalStateException。更好的解决方案很大程度上取决于您想要实现什么,现在无法再让自己的服务一直在后台运行了。 - Sander
@JaydipKalkani 我几天前在Android 6.0上测试过,那时候运行良好。今天在7.0和8.0上测试,但服务在这里停止了。 - Akhtar Khan
@JaydipKalkani,请问哪个自启动权限可以使服务在后台运行? - Akhtar Khan
显示剩余8条评论

0
当应用程序处于空闲状态时,其后台服务的使用受到限制。这不适用于前台服务,前台服务更加引人注目。
参考:文档

以上文档解释了“Android 8.0(API级别26)对应用程序在后台运行时可以执行的操作施加了限制”。我在Android 6.0上遇到了问题。 - Akhtar Khan

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