-
Android) BroadcastReciever와 LiveData로 실시간 네트워크 연결 감지하기Android 2022. 1. 17. 19:23
NetworkInfo
class NetworkManager(private val context : Context) { fun isOnline(): Boolean { val connMgr = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val networkInfo: NetworkInfo? = connMgr.activeNetworkInfo return networkInfo?.isConnected == true } }
- 기존에 네트워크 연결 상태를 감지하는 위와 같은 코드가 많이 사용됩니다.
- activeNetworkInfo(getActiveNetworkInfo()) 메서드를 통해 처음 연결된 네트워크 인터페이스를 찾아서 이를 나타내는 NetworkInfo 인스턴스를 반환하거나 연결된 인터페이스가 없거나 사용 불가인 경우 null을 반환합니다.
- 단점은 실시간으로 네트워크 연결 상태를 감지할 수 없습니다. 해당 코드가 호출되는 시점에서만 체크가 되어, 중간에 인터넷 연결이 끊어진다면 체크할 수 없습니다.
- 또한, deprecated 되었습니다.
BroadcastReceiver + LiveData
- ViewModel에서는 Context 사용을 지양해야 합니다.
- 그래서 LiveData로 네트워크 연결을 감지하여 그 값을 ViewModel에 전달하는 방법을 택했습니다.
class ConnectivityWatcher( private val context: Context ) : LiveData<Boolean>() { private lateinit var networkCallback: ConnectivityManager.NetworkCallback private lateinit var broadcastReceiver: BroadcastReceiver override fun onActive() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { val cm = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager networkCallback = createNetworkCallback() cm.registerDefaultNetworkCallback(networkCallback) } else { val intentFilter = IntentFilter(CONNECTIVITY_ACTION) broadcastReceiver = createBroadcastReceiver() context.registerReceiver(broadcastReceiver, intentFilter) } } override fun onInactive() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { val cm = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager cm.unregisterNetworkCallback(networkCallback) } else { context.unregisterReceiver(broadcastReceiver) } } private fun createNetworkCallback() = object : ConnectivityManager.NetworkCallback() { @RequiresApi(Build.VERSION_CODES.M) override fun onCapabilitiesChanged( network: Network, networkCapabilities: NetworkCapabilities ) { val isInternet = networkCapabilities.hasCapability(NET_CAPABILITY_INTERNET) val isValidated = networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED) postValue(isInternet && isValidated) } override fun onLost(network: Network) { postValue(false) } } private fun createBroadcastReceiver() = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { val isNoConnectivity = intent?.extras?.getBoolean(EXTRA_NO_CONNECTIVITY) ?: true postValue(!isNoConnectivity) } } }
- BroadcastReceiver의 서브클래스인 NetworkReceiver로 네트워크의 연결이 변경되면 NetworkReceiver에서 CONNECTIVITY_ACTION을 활용해 현재 네트워크 상태를 가져와 그 값을 LiveData로 반환합니다.
- LiveData의 onActive, onInActive 상태에 NetworkCallback의 등록 및 해제를 시켜줍니다.
- NetworkCallback은 onAvailable, onLost, onLinkPropertiesChanged, onCapabilitiesChanged, onLosing 등의 메서드를 제공합니다.
- 콜백을 등록 후 registerDefaultNetworkCallback() 또는 registerNetworkCallback()을 사용할 수 있습니다.
- 전자는 네트워크를 대상으로 하도록 미리 정의된 반면 후자는 추가 설정이 필요하지만 더 고급 기능을 제공합니다.
※ 하지만 이 방법은 애매한 연결을 감지하지 못합니다. 네트워크의 연결이 불안정하거나 연결이 되려다 말았다 하는 상황 등..
Usage
// ViewModel val isNetworkAvailable = MutableLiveData<Boolean>() // Activity ConnectivityWatcher(this).observe(this) { connection -> viewModel.isNetworkAvailable.value = connection Toast.makeText(this, message, Toast.LENGTH_SHORT).show() })
반응형'Android' 카테고리의 다른 글
Android) Compose의 ConstraintLayout (0) 2022.06.01 Android) 안드로이드 12 Splash Screen 대응하기 (2) 2022.03.09 Android) Jetpack Compose에서 Paging 라이브러리 사용해보기 (0) 2021.12.04 Android) Jetpack Paging3 유닛 테스트 해보자 (0) 2021.11.28 Android) CodeLab - Layouts in Jetpack Compose (0) 2021.11.14