Change-Id: I10a646e8a17f81d96351e69d36f0cb6ccf28e05cpull/304/head
parent
14ae167b69
commit
c4debb74e7
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.data.test
|
||||
|
||||
import com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
class AlwaysOnlineNetworkMonitor @Inject constructor() : NetworkMonitor {
|
||||
override val isOnline: Flow<Boolean> = flowOf(true)
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.data.util
|
||||
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.ConnectivityManager.NetworkCallback
|
||||
import android.net.Network
|
||||
import android.net.NetworkCapabilities
|
||||
import android.net.NetworkRequest.Builder
|
||||
import android.os.Build.VERSION
|
||||
import android.os.Build.VERSION_CODES
|
||||
import androidx.core.content.getSystemService
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
|
||||
class ConnectivityManagerNetworkMonitor @Inject constructor(
|
||||
@ApplicationContext private val context: Context
|
||||
) : NetworkMonitor {
|
||||
override val isOnline: Flow<Boolean> = callbackFlow<Boolean> {
|
||||
val callback = object : NetworkCallback() {
|
||||
override fun onAvailable(network: Network) {
|
||||
channel.trySend(true)
|
||||
}
|
||||
|
||||
override fun onLost(network: Network) {
|
||||
channel.trySend(false)
|
||||
}
|
||||
}
|
||||
|
||||
val connectivityManager = context.getSystemService<ConnectivityManager>()
|
||||
|
||||
connectivityManager?.registerNetworkCallback(
|
||||
Builder()
|
||||
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||
.build(),
|
||||
callback
|
||||
)
|
||||
|
||||
channel.trySend(connectivityManager.isCurrentlyConnected())
|
||||
|
||||
awaitClose {
|
||||
connectivityManager?.unregisterNetworkCallback(callback)
|
||||
}
|
||||
}
|
||||
.conflate()
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
private fun ConnectivityManager?.isCurrentlyConnected() = when (this) {
|
||||
null -> false
|
||||
else -> when {
|
||||
VERSION.SDK_INT >= VERSION_CODES.M ->
|
||||
activeNetwork
|
||||
?.let(::getNetworkCapabilities)
|
||||
?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||
?: false
|
||||
else -> activeNetworkInfo?.isConnected ?: false
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.data.util
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
* Utility for reporting app connectivity status
|
||||
*/
|
||||
interface NetworkMonitor {
|
||||
val isOnline: Flow<Boolean>
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.data.util
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
* Reports on if synchronization is in progress
|
||||
*/
|
||||
interface SyncStatusMonitor {
|
||||
val isSyncing: Flow<Boolean>
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.testing.util
|
||||
|
||||
import com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
class TestNetworkMonitor : NetworkMonitor {
|
||||
|
||||
private val connectivityFlow = MutableStateFlow(true)
|
||||
|
||||
override val isOnline: Flow<Boolean> = connectivityFlow
|
||||
|
||||
/**
|
||||
* A test-only API to set the connectivity state from tests.
|
||||
*/
|
||||
fun setConnected(isConnected: Boolean) {
|
||||
connectivityFlow.value = isConnected
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.testing.util
|
||||
|
||||
import com.google.samples.apps.nowinandroid.core.data.util.SyncStatusMonitor
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
class TestSyncStatusMonitor : SyncStatusMonitor {
|
||||
|
||||
private val syncStatusFlow = MutableStateFlow(false)
|
||||
|
||||
override val isSyncing: Flow<Boolean> = syncStatusFlow
|
||||
|
||||
/**
|
||||
* A test-only API to set the sync status from tests.
|
||||
*/
|
||||
fun setSyncing(isSyncing: Boolean) {
|
||||
syncStatusFlow.value = isSyncing
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
plugins {
|
||||
id("nowinandroid.android.library")
|
||||
id("nowinandroid.android.hilt")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":sync:work"))
|
||||
implementation(project(":core:data"))
|
||||
implementation(project(":core:testing"))
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2022 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.samples.apps.nowinandroid.core.sync.test">
|
||||
|
||||
</manifest>
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.sync.test
|
||||
|
||||
import com.google.samples.apps.nowinandroid.core.data.util.SyncStatusMonitor
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
class NeverSyncingSyncStatusMonitor @Inject constructor() : SyncStatusMonitor {
|
||||
override val isSyncing: Flow<Boolean> = flowOf(false)
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.sync.test
|
||||
|
||||
import com.google.samples.apps.nowinandroid.core.data.util.SyncStatusMonitor
|
||||
import com.google.samples.apps.nowinandroid.sync.di.SyncModule
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import dagger.hilt.testing.TestInstallIn
|
||||
|
||||
@Module
|
||||
@TestInstallIn(
|
||||
components = [SingletonComponent::class],
|
||||
replaces = [SyncModule::class]
|
||||
)
|
||||
interface TestSyncModule {
|
||||
@Binds
|
||||
fun bindsSyncStatusMonitor(
|
||||
syncStatusMonitor: NeverSyncingSyncStatusMonitor
|
||||
): SyncStatusMonitor
|
||||
}
|
@ -0,0 +1 @@
|
||||
/build
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.sync.di
|
||||
|
||||
import com.google.samples.apps.nowinandroid.core.data.util.SyncStatusMonitor
|
||||
import com.google.samples.apps.nowinandroid.sync.status.WorkManagerSyncStatusMonitor
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
interface SyncModule {
|
||||
@Binds
|
||||
fun bindsSyncStatusMonitor(
|
||||
syncStatusMonitor: WorkManagerSyncStatusMonitor
|
||||
): SyncStatusMonitor
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.sync.status
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.Transformations
|
||||
import androidx.lifecycle.asFlow
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkInfo.State
|
||||
import androidx.work.WorkManager
|
||||
import com.google.samples.apps.nowinandroid.core.data.util.SyncStatusMonitor
|
||||
import com.google.samples.apps.nowinandroid.sync.initializers.SyncWorkName
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
|
||||
/**
|
||||
* [SyncStatusMonitor] backed by [WorkInfo] from [WorkManager]
|
||||
*/
|
||||
class WorkManagerSyncStatusMonitor @Inject constructor(
|
||||
@ApplicationContext context: Context
|
||||
) : SyncStatusMonitor {
|
||||
override val isSyncing: Flow<Boolean> =
|
||||
Transformations.map(
|
||||
WorkManager.getInstance(context).getWorkInfosForUniqueWorkLiveData(SyncWorkName),
|
||||
MutableList<WorkInfo>::anyRunning
|
||||
)
|
||||
.asFlow()
|
||||
.conflate()
|
||||
}
|
||||
|
||||
private val List<WorkInfo>.anyRunning get() = any { it.state == State.RUNNING }
|
Loading…
Reference in new issue