使用PendingIntent在app小部件中的Oreo上启动服务

Tho*_*Vos 16 android android-widget android-service android-appwidget android-8.1-oreo

我正在使用Android应用小部件.我正在创建一个PendingIntent对象并在方法中使用它RemoteViews#setOnClickPendingIntent().这是未决的意图:

// The below code is called in the onUpdate(Context, AppWidgetManager, int[]) method of the AppWidgetProvider class.

// Explicit intent
Intent intent = new Intent(context, MyService.class);
intent.setAction(MY_ACTION);
intent.putExtra(EXTRA_KEY, VALUE);

// Create the pending intent
PendingIntent pendingIntent = PendingIntent.getService(context, appWidgetId, intent, 0);

// 'views' is a RemoteViews object provided by onUpdate in the AppWidgetProvider class.
views.setOnClickPendingIntent(R.id.root_layout, pendingIntent);
Run Code Online (Sandbox Code Playgroud)

上面的代码在Android Oreo之前按预期工作.但是,在Android Oreo中,如果将应用程序从最近的位置移除,它将不再启动该服务.(不再有效).PendingIntent在Oreo的后台执行限制中不排除?

出于测试目的,我更换getServicegetForegroundServiceService仍未启动.这两种方法都在日志中显示以下消息:

W/ActivityManager: Background start not allowed: service Intent { act=com.example.myapp.MY_ACTION flg=0x10000000 cmp=com.example.myapp/com.example.myapp.MyService bnds=[607,716][833,942] (has extras) } to com.example.myapp/com.example.myapp.MyService from pid=-1 uid=10105 pkg=com.example.myapp
Run Code Online (Sandbox Code Playgroud)

为什么Service即使在使用时也没有启动getForegroundService?我在运行Android 8.1.0的Nexus 6P上进行了测试.

Ale*_*xey 15

您无法再在8.0后台启动服务,但您可以使用它JobScheduler来实现类似的结果.还有一个JobIntentService帮助程序类,允许您JobScheduler从服务切换到没有太多PendingIntent.并且你不能使用Activity指向服务,但你可以使用一个指向BroadcastReceiverIntentService.

如果你有一个8.0之前的工作小部件,现在你需要让它在Android 8.0上工作,只需执行这个简单的步骤:

  1. 把你的JobIntentService班级改为onHandleIntent
  2. 将服务onHandleWork方法重命名为BIND_JOB_SERVICE(相同参数)
  3. enqueueWork在清单中添加您的服务权限:
    <service android:name=".widget.MyWidgetService"
           android:permission="android.permission.BIND_JOB_SERVICE">
    </service>
Run Code Online (Sandbox Code Playgroud)

如果你的PendingIntent开始activity,只需留下它 - 它将在Android 8.0+上正常工作.6.要确保widget旧设备可以使用,请确保清单中具有WAKE_LOCK权限(JobIntentService在旧设备上使用).

而已.此小部件现在可以在新旧设备上正常运行.唯一真正的区别在于,如果您的8.0设备处于打盹模式,它可能不会经常更新小部件,但这应该不是问题,因为如果它是打瞌睡,这意味着用户现在无法看到您的小部件无论如何.


Com*_*are 7

如您所知,应用小部件不计入PendingIntent背景白名单.我不知道为什么 - 它似乎与a PendingIntent开始相提并论Notification.也许这Notification是一个系统问题,而app小部件是一个主屏事件.无论如何,你可以:

  • getForegroundService(),因为你有,或

  • 尝试getBroadcast()使用显式Intent,并使用BroadcastReceiver启动a JobIntentService,如果您不想提出Notification(作为前台服务需要)

根据你的症状,你似乎已经绊倒了我认为是一个bug:应该有一种方法可以切换getService()getForegroundService()无需重启.:-)我会尝试运行一些实验,如果我能重现问题就会提出问题.