android - 来自 appWidget 的网络请求

标签 android android-appwidget

SO 上有许多类似的问题,但它们都是 O 之前的问题,IntentService 在其中工作得很好。我试图将它作为 JobIntentService 来做,但延迟是 Not Acceptable 。我的小部件的网络交换应该非常快,或者根本不会,socketTimeout 设置为 100 毫秒,因此几秒钟的延迟令人沮丧。

我想在这里尝试几种解决方案。首先,从上下文中创建一个 foregroundService。据我所知,在服务被终止之前我有 5 秒的时间,所以如果我的交换只需要其中的一小部分,我应该很好。这个假设是否正确?这对 foregroundService 有用吗?

接下来,如果我只是通过在我的 AppWidgetProvider 的 onReceive 中手动启动一个新线程来实现呢?正如我所说,网络交换应该花费不到四分之一秒。在那段时间上下文可能会发生什么?

从 appWidget 发出快速网络请求的最佳方式是什么,应该在它发送广播后立即发生?

最佳答案

在回答这个问题时有几点需要指出。我们有 appWidgets 使用服务来处理事务,因为 jobService 不是我们的选择。分享我们所做的一些事情,希望对您有所帮助。

关于你的第一个问题:
该服务从 appWidget 提供程序调用并完成所有工作,并且它必须作为 Oreo+ 上的前台服务调用,如果该前台服务在调用后 5 秒内未启动,您将得到一个异常:“Context.startForegroundService did而不是调用 Service.startForeground”。 Google 跟踪器中有一个 Unresolved 问题,似乎还没有解决这个问题,所以你应该确保你也阅读了这篇文章。有些人建议将以下代码放在服务的 onCreate() 和 onStart() 中。问题是 https://issuetracker.google.com/issues/76112072 .

我建议在从提供商调用服务后,在服务中完成您需要的所有工作。 (还记得为 Oreo+ 使用通知 channel )例如:

在 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()方法由带有intents的广播触发,可以用来做不同的任务,部分更新appWidget,或者重启服务。因此,根据您提供的信息,您应该能够在提供商的 onReceive 区域进行网络调用,但您可能需要为其指定自定义 Intent 以触发 onReceive(),并确保更新所有实例appWidget 的更新远程 View 。例如,我们有几个自定义 Intent 触发 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 
    }

关于android - 来自 appWidget 的网络请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59049611/

相关文章:

java - 单击 recyclerAdapter 在大型数据集上工作很奇怪,但在小型数据集上工作正常

android - 列出设备上具有特定扩展名的所有文件

android - 如何仅在首次创建应用小部件时显示 Activity ?

android - Expo 中的相机预览失真

android - 如何以编程方式创建具有所需背景颜色的 Drawable?

java - 查询 ParseObject

android - 如何在 android 主屏幕 ListView 小部件中加载项目?

java - 为什么我的 AdapterViewAdapter 在 AppWidget 中使用时会闪烁?

android - UpdateAppWidget 空指针异常

android - 如何在 appwidgetprovider 中找到 View ID?