Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
343 views
in Technique[技术] by (71.8m points)

alarmmanager - Android background process loading data from webpage every minute

I'm working on an Android app with a constant repeating background process.

From the moment the device starts it should load data off a webpage every minute. It uses XmlPullParser and a simple URL inputstream. It is but 10kb so it isn't that intensive. I believe this kind of task is called Deferred. The information loaded by the process has to be accessible to the Activity once that the user opens the app. The background process also needs to be abled to place a notification once the data shows certain results.

There seem to be multiple methods to achieve this in Android, eg. a JobScheduler, WorkManager or AlarmManager however everything I've tried so far seems to either stop once the activity closes or doesn't run at all. The timing, every minute, also seems to be an issue as for both a repeating job and worker the minimum interval is 15. This one minute doesn't have to be exact. I imagine instead of having a repeating process loading the data once it might be better to have a long running process sleeping for 1m in between loading the data.

I do not have access to the server the application is connecting to. so I can't do a FirebaseMessagingService.

What would be the best way to schedule such a background process?

How can the activity best exchange information with that process?

I'm open for all suggestions, thank you for your time.

question from:https://stackoverflow.com/questions/66061718/android-background-process-loading-data-from-webpage-every-minute

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Easy with WorkManager, it's the most encouraged way for Scheduling Repeating background work in Android, see introduction.

As you say, the minimum repeating work request interval is restricted to 15 minutes, the only way to break it is to Repeatedly schedule the one-time work.

1. Setup Your 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. Setup Your Custom Application 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. Setup AndroidManifest File:

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

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

    </application>

</manifest>

By setting up with above, the work (showing Toast in my example) will be executed (or more clearly, schedule and execute) every 5 seconds no matter the app is in foreground or background or killed by system. Only way to stop it is either uninstall or go inside the app's setting to force-close it.

Demo: https://youtu.be/7IsQQppKqFs


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...