#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 ? Вы можете зарегистрировать диспетчер соединений.Обратный вызов сети в диспетчер соединений. Этот обратный вызов будет срабатывать при каждом изменении состояния сети.
Вот пример кода:
- В AndroidManifest.xml файл, добавить
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- В вашем файле 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. Спасибо @Кази Фахим Фархан, но я хочу изучить решение, в котором серверная часть может синхронизироваться независимо от использования приложения, например, службы. Я думаю, что единственный путь вперед-это использовать приемник широковещательной передачи.