在前台服务中运行网络代码后,仍然收到“过度网络使用(后台)”警告

7

参考如何处理和解决“后台中的过度网络使用”

经过几个月的调试,我们现在能够在前台服务中运行所有与网络相关的代码。

然而,在Android Vital中仍然会收到“后台中的过度网络使用”的警告。

enter image description here

当执行前台服务代码时,状态栏区域将始终显示通知 UI。

enter image description here

当我们“退出”应用程序时,我们使用WorkManager启动前台服务。WorkManager将在前台服务启动后立即返回。

public class SyncWorker extends Worker {
    @NonNull
    @Override
    public Result doWork() {
        final Intent intent = new Intent(WeNoteApplication.instance(), SyncForegroundIntentService.class);

        ContextCompat.startForegroundService(
                WeNoteApplication.instance(),
                intent
        );

        return Result.success();
    }
}

public class SyncForegroundIntentService extends IntentService {
    private static final String TAG = "com.yocto.wenote.sync.SyncIntentService";

    public SyncForegroundIntentService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {

        final Context context = WeNoteApplication.instance();

        NotificationCompat.Builder builder = new NotificationCompat.Builder(...

        startForeground(SYNC_FOREGROUND_INTENT_SERVICE_ID, builder.build());

        // Perform networking operation within foreground service.

        stopForeground(true);

侧记

我们认为我们发送的数据量并不多。正如您可以看到的,我们的最新版本已经落入了最低范围(每小时0-5 MB)。

enter image description here


有任何想法,为什么我们仍然会收到“过度网络使用(后台)”的警告?显然,在后台我们不再执行任何网络调用。

我们使用了https://developer.android.com/reference/android/app/Service.html#startForeground(int,%20android.app.Notification)https://developer.android.com/reference/android/content/Context.html#startForegroundService(android.content.Intent)



不确定我理解你的期望是什么,根据你之前的问题并不清楚你最初有什么。如果你所做的只是将startForeground添加到你的意图服务中,那么我不确定你期望得到什么,因为你似乎没有解决发送大量数据的核心问题。 - tyczj
这与“发送大量数据”无关,而是与“在后台发送数据”有关,Google强烈反对这种做法-https://developer.android.com/topic/performance/vitals/bg-network-usage 因此,我们通过使用前台服务完全避免了“在后台发送数据”。然而,Android Vital仍然会给我们警告。 - Cheok Yan Cheng
Android Vitals会有显著的延迟收集数据,并显示最近30天的结果。我认为过度的网络使用量会在几周后减少。 - lukjar
@lukjar 我们在2019年2月23日进行了完整的发布。两周后,仍未出现“过度网络使用”的迹象。 - Cheok Yan Cheng
也许这里已经有答案了 - https://dev59.com/Z1QJ5IYBdhLWcg3wIiW5#54514854 - Mayur Dabhi
显示剩余6条评论
2个回答

6
您正在使用Worker来调用ForegroundService。根据Worker的文档:
工作类由WorkManager在运行时实例化,并且在预先指定的后台线程上调用doWork()方法(请参见Configuration.getExecutor())。此方法用于同步处理您的工作,这意味着一旦从该方法返回,将视为已完成Worker并将被销毁。(...)如果出于任何原因中断工作,则不会重新使用同一个Worker实例。这意味着每个Worker实例仅调用一次doWork()。如果需要重新运行工作单元,则创建新的Worker。 ForegroundService是一个处于前台状态的Service,这意味着系统不会在需要CPU或关闭应用程序时杀死进程。只有这样。我无法找到证明此点的Android Vital文档,所以这只是我的猜测,但我相当确定这是事实:这意味着无论您是否使用ForegroundServiceAndroid Vital仍将其视为后台工作
将应用程序的移动网络使用转移到前台的正确方法是使用适当的可见性设置调用DownloadManager(如您提供的链接中所述)。请告诉我这是否有帮助-如果没有,我们将尝试其他方法。顺便问一下,您能否缩小到特定的API版本统计数据?(在9.0和8.0中有一些后台线程更改,因此这也可能是一个线索)

我曾经认为一旦WorkManager返回Result.success();,用户线程就会死亡。另一个用户线程(IntentService)将被生成,负责执行前台作业?使用IntentServicestartForeground似乎非常合理-https://dev59.com/iWkw5IYBdhLWcg3wY5nq#40927723? - Cheok Yan Cheng
DownloadManager 无法帮助我们。我们需要使用 Google Drive REST API 下载文件,然后对下载的文件执行一些复杂的逻辑。 - Cheok Yan Cheng
@Cheok 我的观点是,由于您在Worker内部启动了ForegroundService,因此它仍然被视为后台工作 - 这就是为什么Android Vital会捕获此问题的原因。我认为真正的问题在于,有些设备上的同步重复次数超过了每小时50MB的限制。我建议尝试缩小范围:哪些版本?哪些设备?哪些操作系统版本?我记得安卓棒棒糖曾经有过一个过度下载的bug - 我会寻找类似的情况(我会继续思考这个非常有趣的问题 :)) 干杯! - Simon

1
如果你正在执行以下操作:
当我们“退出”我们的应用程序时,我们使用WorkManager启动前台服务。 WorkManager将立即返回,在启动前台服务后。
那么你技术上每次用户关闭应用程序时都会安排一个带有网络限制的worker。
从“过度后台网络使用”的文档link中可以看到:
当应用程序在后台连接到移动网络时,应用程序会唤醒CPU并打开无线电。反复这样做可能会耗尽设备的电池电量。
因此,即使您没有发送50MB / 0.10%的电池会话的阈值数据,由于您的应用程序技术上在后台(进行网络ping)频繁唤醒CPU,因此您会收到此警告。
虽然我不确定这是否是问题,但您可以做的是,即使工作程序文档指南也说:
WorkManager旨在用于可推迟的任务-即不需要立即运行,并且即使应用程序退出或设备重新启动,也需要可靠地运行的任务
你可以尝试这些:

  1. 将前台服务安排在用户关闭应用程序后立即调度,而不是安排一个worker,在onHandleIntent内检查用户是否在线(具有连接和对于7以上的设备,也要求有流畅的互联网连接)。

  2. 您可以尝试定期安排工作程序运行,例如每隔几个小时根据业务需求进行备份,但如果这不是您希望备份数据的方式,则可能会出现问题,但它确实实现了工作程序作为延迟任务而不是立即执行的真正目的。

  3. 不确定这个解决方案是否可行,从未尝试过,但理论上看起来是有效的,您可以使用Unique Work并使用称为REPLACE的模式替换工作程序,并设置30分钟的初始延迟时间,这是一种hack方法,但这将延迟工作程序的运行30分钟,同时,如果用户再次打开并关闭应用程序,它将使用新的工作程序替换旧的工作程序。但这种解决方案也有自己的缺点,如有时候如果用户不断使用应用程序,则任务将不会被安排计划,但总体上会减少工作程序运行的次数。

最后,您正在使用的架构是有效的,使用FG服务和工作程序进行调度,只是您经常这样做。来源

前一个工作程序执行和当前工作程序延迟执行之间的最小时间间隔为1.5小时。 - Cheok Yan Cheng
哦,那么我的回答完全过时了,请忽略。 - MadScientist

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