在回答这个问题时需要指出几件事。我们有 appWidgets 使用服务来处理事务,因为 jobService 不是我们的选择。分享我们所做的一些事情,希望对您有所帮助。
关于您的第一个问题:
该服务从 appWidget 提供者调用并完成所有工作,它必须作为 Oreo+ 上的前台服务调用,如果该前台服务未在该调用后 5 秒内启动,您将收到异常:“Context.startForegroundService did然后不调用 Service.startForeground”。 Google 跟踪器中有一个未解决的问题似乎尚未解决,因此您应该确保您也阅读了此内容。有些人建议将以下代码放在服务的 onCreate() 和 onStart() 中。问题是https://issuetracker.google.com/issues/76112072。
我建议在从提供商处调用服务后,在服务中完成您需要的所有工作。 (另外记得使用 Oreo+ 的通知渠道)例如:
在appWidget提供者onUpdate()中:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(new Intent(serviceIntent));
} else {
context.startService(new Intent(serviceIntent));
}
然后在您的服务类中 - 根据我上面发布的问题链接将其放入 onStartCommand() 和 onCreate() 中。
savedIntent = intent;
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//Google Issue tracker https://issuetracker.google.com/issues/76112072 as of 9/26/2018. StartForeground notification must be in both onCreate and onStartCommand to minimize
//crashes in event service was already started and not yet stopped, in which case onCreate is not called again
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(PRIMARY_NOTIF_CHANNEL, "YOUR NOTIFICATION CHANNEL", NotificationManager.IMPORTANCE_DEFAULT);
channel.setSound(null, null);
channel.enableVibration(false);
if (notificationManager != null) {
notificationManager.createNotificationChannel(channel);
}
Notification notification = new NotificationCompat.Builder(this, PRIMARY_NOTIF_CHANNEL)
.setSmallIcon(R.drawable.your_drawable)
.setBadgeIconType(NotificationCompat.BADGE_ICON_SMALL)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setContentTitle(getText(R.string.app_name))
.setStyle(new NotificationCompat.InboxStyle()
.addLine("Needs to sync periodically. Long press to hide.")
.addLine(""))
.build();
startForeground(PRIMARY_FOREGROUND_NOTIF_SERVICE_ID, notification);
}
关于你的第二个问题:
AppWidget Provider 的 onReceive() 方法由带有意图的广播触发,可用于执行不同的任务、部分更新 appWidget 或重启服务。因此,根据您提供的信息,您应该可以在提供者的 onReceive 区域进行网络调用,但您可能需要指定自定义意图以触发 onReceive(),并确保更新所有实例appWidget 以及更新远程视图。例如,我们有几个自定义意图触发 onReceive() 并部分更新我们的 appWidget:
在 appWidget 提供者中:
// sample custom intent name
public static final String ACTION_CLICK_ADVANCE_STATUS = "widget_action_click_advance_status";
...
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (ACTION_CLICK_ADVANCE_STATUS.equals(intent.getAction())) {
// update all instances of appWidgets
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, WidgetJobProvider.class));
// Do your work here
}