Drop dependency upon Merlin

Use ConnectivityManager to monitor network status. This does takes away the ability to
auto-retry requests when network is restored but we can look into that later on.

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2023-08-07 20:49:43 +05:30
parent 6e11229f49
commit 0030e959d1
7 changed files with 81 additions and 154 deletions

View File

@@ -155,9 +155,6 @@ dependencies {
implementation "com.airbnb.android:epoxy:$epoxy_version" implementation "com.airbnb.android:epoxy:$epoxy_version"
kapt "com.airbnb.android:epoxy-processor:$epoxy_version" kapt "com.airbnb.android:epoxy-processor:$epoxy_version"
//Merlin
implementation "com.novoda:merlin:1.2.1"
//HTTP Clients //HTTP Clients
implementation "com.squareup.okhttp3:okhttp:4.11.0" implementation "com.squareup.okhttp3:okhttp:4.11.0"
@@ -176,7 +173,6 @@ dependencies {
//Browser //Browser
implementation 'androidx.browser:browser:1.5.0' implementation 'androidx.browser:browser:1.5.0'
//Shizuku //Shizuku
def shizuku_version = '13.1.1' def shizuku_version = '13.1.1'
compileOnly "dev.rikka.hidden:stub:4.2.0" compileOnly "dev.rikka.hidden:stub:4.2.0"

View File

@@ -28,7 +28,6 @@ import androidx.appcompat.app.AppCompatDelegate
import com.aurora.Constants import com.aurora.Constants
import com.aurora.extensions.isPAndAbove import com.aurora.extensions.isPAndAbove
import com.aurora.store.data.downloader.DownloadManager import com.aurora.store.data.downloader.DownloadManager
import com.aurora.store.data.providers.NetworkProvider
import com.aurora.store.data.receiver.PackageManagerReceiver import com.aurora.store.data.receiver.PackageManagerReceiver
import com.aurora.store.data.service.NotificationService import com.aurora.store.data.service.NotificationService
import com.aurora.store.util.CommonUtil import com.aurora.store.util.CommonUtil
@@ -71,27 +70,9 @@ class AuroraApplication : Application() {
//Register broadcast receiver for package install/uninstall //Register broadcast receiver for package install/uninstall
registerReceiver(packageManagerReceiver, PackageUtil.getFilter()) registerReceiver(packageManagerReceiver, PackageUtil.getFilter())
NetworkProvider
.with(this)
.bind()
CommonUtil.cleanupInstallationSessions(applicationContext) CommonUtil.cleanupInstallationSessions(applicationContext)
} }
override fun onTerminate() {
NetworkProvider
.with(this)
.unbind()
super.onTerminate()
}
override fun onLowMemory() {
NetworkProvider
.with(this)
.unbind()
super.onLowMemory()
}
private fun createNotificationChannel() { private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager

View File

@@ -39,7 +39,9 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils import androidx.core.graphics.ColorUtils
import androidx.core.view.GravityCompat import androidx.core.view.GravityCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavDestination import androidx.navigation.NavDestination
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
@@ -50,6 +52,7 @@ import androidx.navigation.ui.setupWithNavController
import com.aurora.Constants import com.aurora.Constants
import com.aurora.extensions.* import com.aurora.extensions.*
import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.models.AuthData
import com.aurora.store.data.model.NetworkStatus
import com.aurora.store.data.model.SelfUpdate import com.aurora.store.data.model.SelfUpdate
import com.aurora.store.data.providers.AuthProvider import com.aurora.store.data.providers.AuthProvider
import com.aurora.store.data.providers.NetworkProvider import com.aurora.store.data.providers.NetworkProvider
@@ -68,7 +71,7 @@ import kotlinx.coroutines.launch
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
class MainActivity : AppCompatActivity(), NetworkProvider.NetworkListener { class MainActivity : AppCompatActivity() {
private lateinit var B: ActivityMainBinding private lateinit var B: ActivityMainBinding
private lateinit var navController: NavController private lateinit var navController: NavController
@@ -92,32 +95,6 @@ class MainActivity : AppCompatActivity(), NetworkProvider.NetworkListener {
private lateinit var appConfig: AppBarConfiguration private lateinit var appConfig: AppBarConfiguration
override fun onConnected() {
runOnUiThread {
if (!supportFragmentManager.isDestroyed) {
val fragment = supportFragmentManager.findFragmentByTag(NetworkDialogSheet.TAG)
fragment?.let {
supportFragmentManager.beginTransaction().remove(fragment)
.commitAllowingStateLoss()
}
}
}
}
override fun onDisconnected() {
runOnUiThread {
if (!supportFragmentManager.isDestroyed) {
supportFragmentManager.beginTransaction()
.add(NetworkDialogSheet.newInstance(), NetworkDialogSheet.TAG)
.commitAllowingStateLoss()
}
}
}
override fun onReconnected() {
}
companion object { companion object {
@JvmStatic @JvmStatic
private fun matchDestination( private fun matchDestination(
@@ -142,6 +119,31 @@ class MainActivity : AppCompatActivity(), NetworkProvider.NetworkListener {
setContentView(B.root) setContentView(B.root)
this.lifecycleScope.launch {
NetworkProvider(this@MainActivity).networkStatus.collect {
when(it) {
NetworkStatus.AVAILABLE -> {
if (!supportFragmentManager.isDestroyed) {
val fragment = supportFragmentManager
.findFragmentByTag(NetworkDialogSheet.TAG)
fragment?.let {
supportFragmentManager.beginTransaction()
.remove(fragment)
.commitAllowingStateLoss()
}
}
}
NetworkStatus.LOST -> {
if (!supportFragmentManager.isDestroyed) {
supportFragmentManager.beginTransaction()
.add(NetworkDialogSheet.newInstance(), NetworkDialogSheet.TAG)
.commitAllowingStateLoss()
}
}
}
}
}
authData = AuthProvider.with(this).getAuthData() authData = AuthProvider.with(this).getAuthData()
// Toolbar // Toolbar
@@ -290,14 +292,4 @@ class MainActivity : AppCompatActivity(), NetworkProvider.NetworkListener {
sheet.show(supportFragmentManager, SelfUpdateSheet.TAG) sheet.show(supportFragmentManager, SelfUpdateSheet.TAG)
} }
} }
override fun onStart() {
super.onStart()
NetworkProvider.addListener(this)
}
override fun onStop() {
NetworkProvider.removeListener(this)
super.onStop()
}
} }

View File

@@ -0,0 +1,6 @@
package com.aurora.store.data.model
enum class NetworkStatus {
AVAILABLE,
LOST
}

View File

@@ -20,82 +20,57 @@
package com.aurora.store.data.providers package com.aurora.store.data.providers
import android.content.Context import android.content.Context
import com.aurora.store.data.SingletonHolder import android.net.ConnectivityManager
import com.aurora.store.util.Log import android.net.Network
import com.novoda.merlin.Merlin import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.util.Log
import com.aurora.extensions.isMAndAbove
import com.aurora.store.data.model.NetworkStatus
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.launchIn
class NetworkProvider(var context: Context) { @OptIn(DelicateCoroutinesApi::class)
class NetworkProvider(context: Context) {
companion object : SingletonHolder<NetworkProvider, Context>(::NetworkProvider) { private val TAG = NetworkProvider::class.java.simpleName
private var networkListeners: MutableList<NetworkListener> = mutableListOf() private val _networkStatus = MutableStateFlow(NetworkStatus.AVAILABLE)
val networkStatus = _networkStatus.asStateFlow()
fun addListener(networkListener: NetworkListener) { private val connectivityManager =
Log.i("Network-Provider added to ${networkListener.javaClass.simpleName}") context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
networkListeners.add(networkListener)
}
fun removeListener(networkListener: NetworkListener) { init {
Log.i("Network-Provider removed from ${networkListener.javaClass.simpleName}") networkStatus.launchIn(GlobalScope)
networkListeners.remove(networkListener)
} // Monitor network
connectivityManager.registerNetworkCallback(getNetworkRequest(),
object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
Log.d(TAG, "Network available!")
_networkStatus.value = NetworkStatus.AVAILABLE
}
override fun onLost(network: Network) {
super.onLost(network)
Log.d(TAG, "Network unavailable!")
_networkStatus.value = NetworkStatus.LOST
}
})
} }
private var merlin: Merlin = Merlin.Builder() private fun getNetworkRequest(): NetworkRequest {
.withAllCallbacks() val networkRequest = NetworkRequest.Builder()
.build(context) .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
private var isDisconnected = true if (isMAndAbove()) {
networkRequest.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
fun bind() {
merlin.bind()
merlin.registerConnectable {
if (isDisconnected) {
isDisconnected = false
onReConnected()
} else {
onConnected()
}
} }
return networkRequest.build()
merlin.registerDisconnectable {
isDisconnected = true
onDisconnected()
}
}
fun unbind() {
networkListeners.clear()
merlin.unbind()
Log.i("Network-Provider destroyed")
}
private fun onConnected() {
Log.i("Network-Provider connected")
isDisconnected = false
networkListeners.forEach {
it.onConnected()
}
}
private fun onReConnected() {
Log.i("Network-Provider reconnected")
networkListeners.forEach {
it.onReconnected()
}
}
private fun onDisconnected() {
Log.e("Network-Provider disconnected")
networkListeners.forEach {
it.onDisconnected()
}
}
interface NetworkListener {
fun onConnected()
fun onDisconnected()
fun onReconnected()
} }
} }

View File

@@ -33,10 +33,7 @@ import java.lang.reflect.Modifier
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
abstract class BaseAndroidViewModel(application: Application) : AndroidViewModel(application), abstract class BaseAndroidViewModel(application: Application) : AndroidViewModel(application) {
NetworkProvider.NetworkListener {
private lateinit var networkListener: NetworkProvider.NetworkListener
val responseCode = HttpClient.getPreferredClient().responseCode val responseCode = HttpClient.getPreferredClient().responseCode
@@ -51,26 +48,12 @@ abstract class BaseAndroidViewModel(application: Application) : AndroidViewModel
requestState = RequestState.Init requestState = RequestState.Init
NetworkProvider.addListener(this)
// Start collecting response code for requests // Start collecting response code for requests
responseCode.launchIn(viewModelScope) responseCode.launchIn(viewModelScope)
} }
abstract fun observe() abstract fun observe()
override fun onConnected() {
}
override fun onDisconnected() {
}
override fun onReconnected() {
redoLastNetworkTask()
}
private fun redoLastNetworkTask() { private fun redoLastNetworkTask() {
when (requestState) { when (requestState) {
RequestState.Pending -> { RequestState.Pending -> {
@@ -81,10 +64,4 @@ abstract class BaseAndroidViewModel(application: Application) : AndroidViewModel
} }
} }
} }
override fun onCleared() {
Log.i("${javaClass.simpleName} Destroyed")
NetworkProvider.removeListener(this)
super.onCleared()
}
} }

View File

@@ -29,7 +29,7 @@ dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories { repositories {
google() google()
jcenter() // Required for com.novoda:merlin:1.2.0 jcenter() // Required for androidx.tonyodev.fetch2
mavenCentral() mavenCentral()
maven { maven {
name 'JitPack' name 'JitPack'
@@ -42,4 +42,4 @@ dependencyResolutionManagement {
} }
} }
include ':app' include ':app'
rootProject.name = "AuroraStore4" rootProject.name = "AuroraStore4"