SO上有许多类似的问题,但是它们都是O之前的版本,因此IntentService可以正常工作。我尝试将其作为JobIntentService进行,但是延迟是不可接受的。我的小部件的网络交换应该是真的很快,或者根本没有,socketTimeout设置为100ms,所以几秒钟的延迟令人沮丧。
我想在这里尝试几种解决方案。首先,从上下文创建一个前台服务。据我了解,我在服务终止前还有5秒钟的时间,因此,如果我的交换只花了其中的一小部分,那我应该很好。这个假设正确吗?这对前台服务有用吗?
接下来,如果我只是通过在我的AppWidgetProvider的onReceive中手动启动一个新线程来执行此操作,该怎么办?正如我所说,网络交换应该花费不到四分之一秒。在这段时间内上下文可能会发生什么?
从appWidget发出快速网络请求的最佳方法是什么,它应该在发送广播后立即发生?
答案 0 :(得分:1)
回答这个问题有几点要指出。我们有一些appWidgets使用服务来处理事务,因为jobService不是我们的选择。分享一些我们已经完成的事情,希望会对您有所帮助。
第一个问题:
该服务是从appWidget提供程序调用的,并完成了所有工作,并且必须在Oreo +上将其作为前台服务调用,如果该调用前5秒钟内未启动该前台服务,您将得到一个异常:“ Context.startForegroundService执行了然后再调用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(),并确保更新所有实例并更新远程视图。例如,我们有几个自定义方法,它们会触发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
}