Запускайте worker каждый раз, когда пользователь подключается к Интернету

#java #android #kotlin #android-workmanager

Вопрос:

Я хочу синхронизироваться с сервером каждый раз, когда пользователь подключается к Интернету. До сих пор я использовал WorkManager для выполнения работы с 3-часовыми интервалами и ограничениями, требующими подключения к Интернету. Но в нем отсутствуют интервалы, когда устройство подключено к Интернету, но период работы не достигнут. Я хочу, чтобы он запускался каждый раз, когда пользователь подключается к Интернету.

Ниже приведен пример кода, который я использую:

 val constraints = Constraints.Builder()
        .setRequiredNetworkType(NetworkType.CONNECTED)
        .build()
    val work = PeriodicWorkRequestBuilder<ExampleWorker>(3, TimeUnit.HOURS)
        .setConstraints(constraints)
        .build()
    val workManager = WorkManager.getInstance(context)
    workManager.enqueueUniquePeriodicWork(UniqueWorkerTag,
    ExistingPeriodicWorkPolicy.KEEP, work)
 

Я просмотрел разные страницы, и единственное решение, которое я нахожу, — это использовать Firebase JobScheduler, но теперь он устарел.

Комментарии:

1. На самом деле больше нет ничего доступного, что позволяло бы вам делать это каждый раз при повторном подключении устройства. приемник широковещательной передачи подключения не работает, если вы не зарегистрируете его в коде, что означает, что вам либо нужно, чтобы ваше приложение было на переднем плане, либо вам нужна постоянно работающая служба переднего плана, и вы зарегистрируете ее там

2. WorkManager отложит работу, если ваши ограничения не будут выполнены, на более позднее время, но он не будет делать это каждый раз при повторном подключении

3. WorkManager-это удовлетворенные ограничения, а не событие. У вас есть только триггеры об изменениях для URI. Вам следует либо использовать приемник вещания, если это возможно, либо просто зарегистрироваться для обратного вызова подключения как часть постоянно работающей службы.

Ответ №1:

Вы пробовали использовать ConnectivityManager ? Вы можете зарегистрировать диспетчер соединений.Обратный вызов сети в диспетчер соединений. Этот обратный вызов будет срабатывать при каждом изменении состояния сети.

Вот пример кода:

  1. В AndroidManifest.xml файл, добавить
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 
  1. В вашем файле kotlin / java:
 package app.soumicslab.stackoverflow

import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.annotation.RequiresApi

class MainActivity : AppCompatActivity() {
    // Constants / Statics
    companion object {
        const val TAG: String = "MainActivity"
    }

    // Variables
    private lateinit var connectivityManager: ConnectivityManager
    private lateinit var networkCallback: ConnectivityManager.NetworkCallback
    private var isInternetAvailableForApiGte21: Boolean = false

    // Override methods
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


    }

    override fun onResume() {
        super.onResume()
        if(!this::connectivityManager.isInitialized) {
            connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            registerNetworkCallBackForApiGte21()
        }
    }

    override fun onPause() {
        super.onPause()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            unregisterNetworkCallBackForApiGte21()
        }
    }

    // Private methods

    @RequiresApi(Build.VERSION_CODES.N)
    private fun registerNetworkCallBackForApiGte21() {
        if(!this::networkCallback.isInitialized) {
            this.networkCallback = object: ConnectivityManager.NetworkCallback() {
                override fun onAvailable(network: Network) {
                    super.onAvailable(network)
                    isInternetAvailableForApiGte21 = true
                    Log.e(TAG, "networkCallBack onAvailable")

                    // todo: <------Your worker code goes inside here-----

                }

                override fun onLost(network: Network) {
                    super.onLost(network)
                    isInternetAvailableForApiGte21 = false
                    Log.e(TAG, "networkCallBack onLost")
                }
            }
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val looper: Looper = Looper.getMainLooper()
            val handler = Handler(looper)
            this.connectivityManager.registerDefaultNetworkCallback(this.networkCallback, handler)
        }else{
            this.connectivityManager.registerDefaultNetworkCallback(this.networkCallback)
        }
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    private fun unregisterNetworkCallBackForApiGte21() {
        if(this::networkCallback.isInitialized) {
            this.connectivityManager.unregisterNetworkCallback(this.networkCallback)
        }
    }

}

 

Поэтому, запустив это, я подключил Wi-Fi, мобильные данные. Это вывод в Logcat Android Studio:

 2021-09-21 08:54:38.668 4008-4008/app.soumicslab.stackoverflow E/MainActivity: networkCallBack onAvailable
2021-09-21 08:54:43.284 4008-4008/app.soumicslab.stackoverflow E/MainActivity: networkCallBack onLost
2021-09-21 08:54:48.527 4008-4008/app.soumicslab.stackoverflow E/MainActivity: networkCallBack onAvailable
2021-09-21 08:54:52.782 4008-4008/app.soumicslab.stackoverflow E/MainActivity: networkCallBack onLost
2021-09-21 08:55:04.459 4008-4008/app.soumicslab.stackoverflow E/MainActivity: networkCallBack onAvailable
2021-09-21 08:55:06.685 4008-4008/app.soumicslab.stackoverflow E/MainActivity: networkCallBack onLost
2021-09-21 08:55:10.228 4008-4008/app.soumicslab.stackoverflow E/MainActivity: networkCallBack onAvailable
... ... ...
 

Комментарии:

1. Спасибо @Кази Фахим Фархан, но я хочу изучить решение, в котором серверная часть может синхронизироваться независимо от использования приложения, например, службы. Я думаю, что единственный путь вперед-это использовать приемник широковещательной передачи.