繁体   English   中英

Android 后台进程每分钟从网页加载数据

[英]Android background process loading data from webpage every minute

我正在开发一个具有不断重复后台进程的 Android 应用程序。

从设备启动的那一刻起,它应该每分钟从网页加载数据。 它使用 XmlPullParser 和一个简单的 URL 输入流。 它只有 10kb,所以不是那么密集。 我相信这种任务被称为延迟。 一旦用户打开应用程序,该进程加载的信息必须可供 Activity 访问。 一旦数据显示某些结果,后台进程也需要能够发出通知。

在 Android 中似乎有多种方法可以实现这一点,例如。 JobScheduler、WorkManager 或 AlarmManager 但是到目前为止我尝试过的一切似乎要么在活动关闭时停止,要么根本不运行。 每分钟的时间似乎也是一个问题,因为对于重复工作和工人来说,最小间隔是 15。这一分钟不必精确。 我想,与其让一个重复的过程加载数据,不如让一个长时间运行的进程在加载数据之间休眠 1m 可能会更好。

我无权访问应用程序连接的服务器。 所以我不能做 FirebaseMessagingService。

安排这样一个后台进程的最佳方式是什么?

活动如何最好地与该流程交换信息?

我愿意接受所有建议,感谢您的宝贵时间。

使用WorkManager很容易,这是在 Android 中调度重复后台工作最受鼓励的方式,请参阅介绍

正如您所说,最小重复工作请求间隔限制为15 分钟,打破它的唯一方法是重复安排一次性工作

1. 设置你的 Worker Class:

class ToastShower(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
    override suspend fun doWork(): Result {
        withContext(Dispatchers.Main) {      //ui related work must run in Main thread!!
            Toast.makeText(applicationContext, "Hey, I'm Sam! This message will appear every 5 seconds.", Toast.LENGTH_SHORT).show()
        }

        return Result.success()
    }
}

2. 设置您的自定义应用程序 Class:

class WorkManagerApplication : Application() {
    private val backgroundScope = CoroutineScope(Dispatchers.Default)       //standard background thread
    private val applicationContext = this

    override fun onCreate() {                           //called when the app launches (same as Activity)
        super.onCreate()

        initWork()
    }

    private fun initWork() {
        backgroundScope.launch {                                //all rnu in background thread
            setupToastShowingWork(0)                            //no delay at first time

            observeToastShowingWork()                       //observe work state changes, see below
        }
    }

    private fun setupToastShowingWork(delayInSeconds: Long) {               //must run in background thread
        val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.UNMETERED)          //when using WiFi
            .build()

        val oneTimeRequest = OneTimeWorkRequestBuilder<ToastShower>()       //【for breaking 15 minutes limit we have to use one time request】
            .setInitialDelay(delayInSeconds, TimeUnit.SECONDS)          //customizable delay (interval) time
            .setConstraints(constraints)
            .build()

        WorkManager.getInstance(applicationContext).enqueueUniqueWork(      //【must be unique!!】
            ToastShower::class.java.simpleName,                 //work name, use class name for convenient
            ExistingWorkPolicy.KEEP,                        //if new work comes in with same name, discard the new one
            oneTimeRequest
        )
    }

    private suspend fun observeToastShowingWork() {
        withContext(Dispatchers.Main) { //must run in Main thread for using observeForever 
            WorkManager.getInstance(applicationContext).getWorkInfosForUniqueWorkLiveData(ToastShower::class.java.simpleName).observeForever {
                if (it[0].state == WorkInfo.State.SUCCEEDED) {          //when the work is done
                    backgroundScope.launch {                        //prevent from running in Main thread
                        setupToastShowingWork(5)                        //every 5 seconds
                    }
                }
            }
        }
    }
}

3.设置AndroidManifest文件:

<manifest 
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.workmanagertest">

    <application
        android:name=".WorkManagerApplication"                  //【here, must!!!】
    
        ...

    </application>

</manifest>

通过以上设置,无论应用程序处于前台还是后台或被系统杀死,工作(在我的示例中显示Toast )将每 5 秒执行一次(或者更清楚地,调度和执行)。 阻止它的唯一方法是在应用程序设置中卸载或 go 以强制关闭它。

演示: https://youtu.be/7IsQQppKqFs

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM