mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-2831 Tech | Implement Device.Network.State.Set (#1915)
This commit is contained in:
parent
4a0aaa234a
commit
b4de6b4d0b
16 changed files with 204 additions and 5 deletions
|
@ -3,6 +3,10 @@ package com.anytypeio.anytype.di.main
|
|||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.anytypeio.anytype.device.network_type.NetworkConnectionStatusImpl
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import com.anytypeio.anytype.domain.device.NetworkConnectionStatus
|
||||
import com.anytypeio.anytype.persistence.networkmode.DefaultNetworkModeProvider
|
||||
import com.anytypeio.anytype.persistence.networkmode.DefaultNetworkModeProvider.NetworkModeConstants.NAMED_NETWORK_MODE_PREFS
|
||||
import com.anytypeio.anytype.persistence.networkmode.NetworkModeProvider
|
||||
|
@ -10,6 +14,7 @@ import dagger.Module
|
|||
import dagger.Provides
|
||||
import javax.inject.Named
|
||||
import javax.inject.Singleton
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
@Module
|
||||
object NetworkModeModule {
|
||||
|
@ -28,4 +33,19 @@ object NetworkModeModule {
|
|||
fun provider(
|
||||
@Named(NAMED_NETWORK_MODE_PREFS) sharedPreferences: SharedPreferences
|
||||
): NetworkModeProvider = DefaultNetworkModeProvider(sharedPreferences)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideNetworkConnectionStatus(
|
||||
context: Context,
|
||||
dispatcher: AppCoroutineDispatchers,
|
||||
blockRepository: BlockRepository,
|
||||
@Named(ConfigModule.DEFAULT_APP_COROUTINE_SCOPE) scope: CoroutineScope
|
||||
): NetworkConnectionStatus = NetworkConnectionStatusImpl(
|
||||
context = context,
|
||||
dispatchers = dispatcher,
|
||||
coroutineScope = scope,
|
||||
blockRepository = blockRepository
|
||||
)
|
||||
}
|
|
@ -10,6 +10,7 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
|||
import com.anytypeio.anytype.domain.config.ConfigStorage
|
||||
import com.anytypeio.anytype.domain.debugging.DebugAccountSelectTrace
|
||||
import com.anytypeio.anytype.domain.debugging.Logger
|
||||
import com.anytypeio.anytype.domain.device.NetworkConnectionStatus
|
||||
import com.anytypeio.anytype.domain.event.interactor.SpaceSyncAndP2PStatusProvider
|
||||
import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.multiplayer.ActiveSpaceMemberSubscriptionContainer
|
||||
|
@ -221,13 +222,15 @@ object SubscriptionsModule {
|
|||
relations: RelationsSubscriptionManager,
|
||||
permissions: UserPermissionProvider,
|
||||
isSpaceDeleted: SpaceDeletedStatusWatcher,
|
||||
profileSubscriptionManager: ProfileSubscriptionManager
|
||||
profileSubscriptionManager: ProfileSubscriptionManager,
|
||||
networkConnectionStatus: NetworkConnectionStatus
|
||||
): GlobalSubscriptionManager = GlobalSubscriptionManager.Default(
|
||||
types = types,
|
||||
relations = relations,
|
||||
permissions = permissions,
|
||||
isSpaceDeleted = isSpaceDeleted,
|
||||
profile = profileSubscriptionManager
|
||||
profile = profileSubscriptionManager,
|
||||
networkConnectionStatus = networkConnectionStatus
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package com.anytypeio.anytype.core_models
|
||||
|
||||
enum class DeviceNetworkType {
|
||||
WIFI,
|
||||
CELLULAR,
|
||||
NOT_CONNECTED
|
||||
}
|
|
@ -9,6 +9,7 @@ import com.anytypeio.anytype.core_models.DVFilter
|
|||
import com.anytypeio.anytype.core_models.DVSort
|
||||
import com.anytypeio.anytype.core_models.DVViewer
|
||||
import com.anytypeio.anytype.core_models.DVViewerType
|
||||
import com.anytypeio.anytype.core_models.DeviceNetworkType
|
||||
import com.anytypeio.anytype.core_models.Event
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
|
@ -1096,4 +1097,8 @@ class BlockDataRepository(
|
|||
override suspend fun objectDateByTimestamp(command: Command.ObjectDateByTimestamp): Struct? {
|
||||
return remote.objectDateByTimestamp(command)
|
||||
}
|
||||
|
||||
override suspend fun setDeviceNetworkState(type: DeviceNetworkType) {
|
||||
remote.setDeviceNetworkState(type)
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import com.anytypeio.anytype.core_models.DVFilter
|
|||
import com.anytypeio.anytype.core_models.DVSort
|
||||
import com.anytypeio.anytype.core_models.DVViewer
|
||||
import com.anytypeio.anytype.core_models.DVViewerType
|
||||
import com.anytypeio.anytype.core_models.DeviceNetworkType
|
||||
import com.anytypeio.anytype.core_models.Event
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
|
@ -465,4 +466,6 @@ interface BlockRemote {
|
|||
suspend fun objectRelationListWithValue(command: Command.RelationListWithValue): List<RelationListWithValueItem>
|
||||
|
||||
suspend fun debugAccountSelectTrace(dir: String): String
|
||||
|
||||
suspend fun setDeviceNetworkState(type: DeviceNetworkType)
|
||||
}
|
|
@ -1 +1,3 @@
|
|||
<manifest />
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
</manifest>
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
package com.anytypeio.anytype.device.network_type
|
||||
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Network
|
||||
import android.net.NetworkCapabilities
|
||||
import com.anytypeio.anytype.core_models.DeviceNetworkType
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import com.anytypeio.anytype.domain.device.NetworkConnectionStatus
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
|
||||
class NetworkConnectionStatusImpl(
|
||||
context: Context,
|
||||
private val coroutineScope: CoroutineScope,
|
||||
private val blockRepository: BlockRepository,
|
||||
private val dispatchers: AppCoroutineDispatchers
|
||||
) : NetworkConnectionStatus {
|
||||
|
||||
private val connectivityManager =
|
||||
context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
|
||||
private var isMonitoring = false
|
||||
|
||||
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
|
||||
override fun onAvailable(network: Network) {
|
||||
// Called when the network is available
|
||||
updateNetworkState(networkCapabilities = getNetworkCapabilities())
|
||||
}
|
||||
|
||||
override fun onLost(network: Network) {
|
||||
// Called when the network is disconnected
|
||||
updateNetworkState(networkCapabilities = getNetworkCapabilities())
|
||||
}
|
||||
|
||||
override fun onCapabilitiesChanged(
|
||||
network: Network,
|
||||
networkCapabilities: NetworkCapabilities
|
||||
) {
|
||||
// Called when the network capabilities (like Wi-Fi vs Cellular) change
|
||||
updateNetworkState(networkCapabilities)
|
||||
}
|
||||
}
|
||||
|
||||
override fun start() {
|
||||
if (!isMonitoring) {
|
||||
try {
|
||||
connectivityManager?.registerDefaultNetworkCallback(networkCallback)
|
||||
isMonitoring = true
|
||||
updateNetworkState(networkCapabilities = getNetworkCapabilities())
|
||||
} catch (
|
||||
e: RuntimeException
|
||||
) {
|
||||
Timber.w(e, "Failed to register network callback")
|
||||
isMonitoring = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
if (isMonitoring) {
|
||||
try {
|
||||
connectivityManager?.unregisterNetworkCallback(networkCallback)
|
||||
isMonitoring = false
|
||||
} catch (e: Throwable) {
|
||||
Timber.w(e, "Failed to unregister network callback")
|
||||
isMonitoring = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateNetworkState(networkCapabilities: NetworkCapabilities?) {
|
||||
coroutineScope.launch {
|
||||
val networkType = mapNetworkType(networkCapabilities)
|
||||
withContext(dispatchers.io) {
|
||||
try {
|
||||
blockRepository.setDeviceNetworkState(networkType)
|
||||
} catch (
|
||||
e: Throwable
|
||||
) {
|
||||
Timber.w(e, "Failed to update network state")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getNetworkCapabilities(): NetworkCapabilities? {
|
||||
try {
|
||||
return connectivityManager?.getNetworkCapabilities(connectivityManager.activeNetwork)
|
||||
} catch (e: Throwable) {
|
||||
Timber.w(e, "Failed to get network capabilities")
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun mapNetworkType(networkCapabilities: NetworkCapabilities?): DeviceNetworkType =
|
||||
when {
|
||||
networkCapabilities == null -> DeviceNetworkType.NOT_CONNECTED
|
||||
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> DeviceNetworkType.WIFI
|
||||
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> DeviceNetworkType.CELLULAR
|
||||
else -> DeviceNetworkType.NOT_CONNECTED
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import com.anytypeio.anytype.core_models.DVFilter
|
|||
import com.anytypeio.anytype.core_models.DVSort
|
||||
import com.anytypeio.anytype.core_models.DVViewer
|
||||
import com.anytypeio.anytype.core_models.DVViewerType
|
||||
import com.anytypeio.anytype.core_models.DeviceNetworkType
|
||||
import com.anytypeio.anytype.core_models.Event
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
|
@ -508,4 +509,6 @@ interface BlockRepository {
|
|||
suspend fun debugAccountSelectTrace(dir: String): String
|
||||
|
||||
suspend fun objectDateByTimestamp(command: Command.ObjectDateByTimestamp): Struct?
|
||||
|
||||
suspend fun setDeviceNetworkState(type: DeviceNetworkType)
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package com.anytypeio.anytype.domain.device
|
||||
|
||||
interface NetworkConnectionStatus {
|
||||
fun start()
|
||||
fun stop()
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package com.anytypeio.anytype.domain.subscriptions
|
||||
|
||||
import com.anytypeio.anytype.domain.device.NetworkConnectionStatus
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.search.ProfileSubscriptionManager
|
||||
|
@ -17,7 +18,8 @@ interface GlobalSubscriptionManager {
|
|||
private val relations: RelationsSubscriptionManager,
|
||||
private val permissions: UserPermissionProvider,
|
||||
private val isSpaceDeleted: SpaceDeletedStatusWatcher,
|
||||
private val profile: ProfileSubscriptionManager
|
||||
private val profile: ProfileSubscriptionManager,
|
||||
private val networkConnectionStatus: NetworkConnectionStatus
|
||||
) : GlobalSubscriptionManager {
|
||||
|
||||
override fun onStart() {
|
||||
|
@ -26,6 +28,7 @@ interface GlobalSubscriptionManager {
|
|||
permissions.start()
|
||||
isSpaceDeleted.onStart()
|
||||
profile.onStart()
|
||||
networkConnectionStatus.start()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
|
@ -34,6 +37,7 @@ interface GlobalSubscriptionManager {
|
|||
permissions.stop()
|
||||
isSpaceDeleted.onStop()
|
||||
profile.onStop()
|
||||
networkConnectionStatus.stop()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.anytypeio.anytype.core_models.DVFilter
|
|||
import com.anytypeio.anytype.core_models.DVSort
|
||||
import com.anytypeio.anytype.core_models.DVViewer
|
||||
import com.anytypeio.anytype.core_models.DVViewerType
|
||||
import com.anytypeio.anytype.core_models.DeviceNetworkType
|
||||
import com.anytypeio.anytype.core_models.Event
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
|
@ -1070,4 +1071,8 @@ class BlockMiddleware(
|
|||
override suspend fun objectDateByTimestamp(command: Command.ObjectDateByTimestamp): Struct? {
|
||||
return middleware.objectDateByTimestamp(command)
|
||||
}
|
||||
|
||||
override suspend fun setDeviceNetworkState(type: DeviceNetworkType) {
|
||||
middleware.setDeviceNetworkState(type)
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ import com.anytypeio.anytype.core_models.DVFilter
|
|||
import com.anytypeio.anytype.core_models.DVSort
|
||||
import com.anytypeio.anytype.core_models.DVViewer
|
||||
import com.anytypeio.anytype.core_models.DVViewerType
|
||||
import com.anytypeio.anytype.core_models.DeviceNetworkType
|
||||
import com.anytypeio.anytype.core_models.Event
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
|
@ -2856,6 +2857,16 @@ class Middleware @Inject constructor(
|
|||
return response.details
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun setDeviceNetworkState(type: DeviceNetworkType) {
|
||||
val request = Rpc.Device.NetworkState.Set.Request(
|
||||
deviceNetworkType = type.mw()
|
||||
)
|
||||
logRequestIfDebug(request)
|
||||
val (response, time) = measureTimedValue { service.deviceNetworkStateSet(request) }
|
||||
logResponseIfDebug(response, time)
|
||||
}
|
||||
|
||||
private fun logRequestIfDebug(request: Any) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
logger.logRequest(request).also {
|
||||
|
|
|
@ -109,4 +109,6 @@ typealias MSpaceSyncError = anytype.Event.Space.SyncError
|
|||
|
||||
typealias MP2PStatus = anytype.Event.P2PStatus.Status
|
||||
typealias MP2PStatusUpdate = P2PStatus.Update
|
||||
typealias MSyncStatusUpdate = Space.SyncStatus.Update
|
||||
typealias MSyncStatusUpdate = Space.SyncStatus.Update
|
||||
|
||||
typealias MDeviceNetworkType = anytype.model.DeviceNetworkType
|
|
@ -8,6 +8,7 @@ import com.anytypeio.anytype.core_models.Block
|
|||
import com.anytypeio.anytype.core_models.BlockSplitMode
|
||||
import com.anytypeio.anytype.core_models.Command
|
||||
import com.anytypeio.anytype.core_models.DVSortEmptyType
|
||||
import com.anytypeio.anytype.core_models.DeviceNetworkType
|
||||
import com.anytypeio.anytype.core_models.InternalFlags
|
||||
import com.anytypeio.anytype.core_models.NetworkMode
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
|
@ -630,3 +631,9 @@ fun Rpc.Object.SearchWithMeta.Response.toCoreModelSearchResults(): List<Command.
|
|||
}
|
||||
}
|
||||
|
||||
fun DeviceNetworkType.mw(): MDeviceNetworkType = when(this) {
|
||||
DeviceNetworkType.WIFI -> MDeviceNetworkType.WIFI
|
||||
DeviceNetworkType.CELLULAR -> MDeviceNetworkType.CELLULAR
|
||||
DeviceNetworkType.NOT_CONNECTED -> MDeviceNetworkType.NOT_CONNECTED
|
||||
}
|
||||
|
||||
|
|
|
@ -609,4 +609,7 @@ interface MiddlewareService {
|
|||
|
||||
@Throws(Exception::class)
|
||||
fun debugAccountSelectTrace(request: Rpc.Debug.AccountSelectTrace.Request): Rpc.Debug.AccountSelectTrace.Response
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun deviceNetworkStateSet(request: Rpc.Device.NetworkState.Set.Request): Rpc.Device.NetworkState.Set.Response
|
||||
}
|
|
@ -2450,4 +2450,17 @@ class MiddlewareServiceImplementation @Inject constructor(
|
|||
return response
|
||||
}
|
||||
}
|
||||
|
||||
override fun deviceNetworkStateSet(request: Rpc.Device.NetworkState.Set.Request): Rpc.Device.NetworkState.Set.Response {
|
||||
val encoded = Service.deviceNetworkStateSet(
|
||||
Rpc.Device.NetworkState.Set.Request.ADAPTER.encode(request)
|
||||
)
|
||||
val response = Rpc.Device.NetworkState.Set.Response.ADAPTER.decode(encoded)
|
||||
val error = response.error
|
||||
if (error != null && error.code != Rpc.Device.NetworkState.Set.Response.Error.Code.NULL) {
|
||||
throw Exception(error.description)
|
||||
} else {
|
||||
return response
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue