diff options
13 files changed, 222 insertions, 53 deletions
diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index cb5737e3ff..5fed7575d4 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -12,6 +12,7 @@ plugins { alias(libs.plugins.kotlin.parcelize) alias(libs.plugins.kotlin.ksp) alias(libs.plugins.compose) + alias(libs.plugins.protobuf.core) id(Dependencies.junit5AndroidPluginId) version Versions.junit5Plugin } @@ -55,11 +56,7 @@ android { } } - playConfigs { - register("playStagemoleRelease") { - enabled = true - } - } + playConfigs { register("playStagemoleRelease") { enabled = true } } androidResources { @Suppress("UnstableApiUsage") @@ -222,8 +219,7 @@ android { } val variantName = name - val capitalizedVariantName = - variantName.toString().capitalized() + val capitalizedVariantName = variantName.toString().capitalized() val artifactName = "MullvadVPN-${versionName}${artifactSuffix}" tasks.register<Copy>("create${capitalizedVariantName}DistApk") { @@ -316,7 +312,8 @@ tasks.create("printVersion") { play { serviceAccountCredentials.set(file("$credentialsPath/play-api-key.json")) - // Disable for all flavors by default. Only specific flavors should be enabled using PlayConfigs. + // Disable for all flavors by default. Only specific flavors should be enabled using + // PlayConfigs. enabled = false // This property refers to the Publishing API (not git). commit = true @@ -326,6 +323,19 @@ play { userFraction = 1.0 } +protobuf { + protoc { artifact = libs.plugins.protobuf.protoc.get().toString() } + plugins { + create("java") { artifact = libs.plugins.grpc.protoc.gen.grpc.java.get().toString() } + } + generateProtoTasks { + all().forEach { + it.plugins { create("java") { option("lite") } } + it.builtins { create("kotlin") { option("lite") } } + } + } +} + dependencies { implementation(projects.lib.common) implementation(projects.lib.daemonGrpc) @@ -345,6 +355,7 @@ dependencies { implementation(libs.commons.validator) implementation(libs.androidx.activity.compose) + implementation(libs.androidx.datastore) implementation(libs.androidx.ktx) implementation(libs.androidx.coresplashscreen) implementation(libs.androidx.lifecycle.runtime) @@ -370,6 +381,7 @@ dependencies { implementation(libs.kotlin.reflect) implementation(libs.kotlin.stdlib) implementation(libs.kotlinx.coroutines.android) + implementation(libs.protobuf.kotlin.lite) // UI tooling implementation(libs.compose.ui.tooling.preview) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt index b111db10b2..650ee67eaa 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt @@ -2,8 +2,9 @@ package net.mullvad.mullvadvpn.di import android.content.ComponentName import android.content.Context -import android.content.SharedPreferences import android.content.pm.PackageManager +import androidx.datastore.core.DataStore +import androidx.datastore.dataStore import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.MainScope import net.mullvad.mullvadvpn.BuildConfig @@ -20,7 +21,6 @@ import net.mullvad.mullvadvpn.repository.ChangelogRepository import net.mullvad.mullvadvpn.repository.CustomListsRepository import net.mullvad.mullvadvpn.repository.InAppNotificationController import net.mullvad.mullvadvpn.repository.NewDeviceRepository -import net.mullvad.mullvadvpn.repository.PrivacyDisclaimerRepository import net.mullvad.mullvadvpn.repository.ProblemReportRepository import net.mullvad.mullvadvpn.repository.RelayListFilterRepository import net.mullvad.mullvadvpn.repository.RelayListRepository @@ -28,6 +28,10 @@ import net.mullvad.mullvadvpn.repository.RelayOverridesRepository import net.mullvad.mullvadvpn.repository.SettingsRepository import net.mullvad.mullvadvpn.repository.SplashCompleteRepository import net.mullvad.mullvadvpn.repository.SplitTunnelingRepository +import net.mullvad.mullvadvpn.repository.UserPreferences +import net.mullvad.mullvadvpn.repository.UserPreferencesMigration +import net.mullvad.mullvadvpn.repository.UserPreferencesRepository +import net.mullvad.mullvadvpn.repository.UserPreferencesSerializer import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository import net.mullvad.mullvadvpn.ui.MainActivity import net.mullvad.mullvadvpn.ui.serviceconnection.AppVersionInfoRepository @@ -99,16 +103,13 @@ import net.mullvad.mullvadvpn.viewmodel.location.SearchLocationViewModel import net.mullvad.mullvadvpn.viewmodel.location.SelectLocationListViewModel import net.mullvad.mullvadvpn.viewmodel.location.SelectLocationViewModel import org.apache.commons.validator.routines.InetAddressValidator -import org.koin.android.ext.koin.androidApplication import org.koin.android.ext.koin.androidContext import org.koin.core.module.dsl.viewModel import org.koin.core.qualifier.named import org.koin.dsl.module val uiModule = module { - single<SharedPreferences>(named(APP_PREFERENCES_NAME)) { - androidApplication().getSharedPreferences(APP_PREFERENCES_NAME, Context.MODE_PRIVATE) - } + single<DataStore<UserPreferences>> { androidContext().userPreferencesStore } single<PackageManager> { androidContext().packageManager } single<String>(named(SELF_PACKAGE_NAME)) { androidContext().packageName } @@ -126,11 +127,7 @@ val uiModule = module { single { androidContext().contentResolver } single { ChangelogRepository(get()) } - single { - PrivacyDisclaimerRepository( - androidContext().getSharedPreferences(APP_PREFERENCES_NAME, Context.MODE_PRIVATE) - ) - } + single { UserPreferencesRepository(get()) } single { SettingsRepository(get()) } single { MullvadProblemReport(get()) } single { RelayOverridesRepository(get()) } @@ -272,3 +269,10 @@ val uiModule = module { const val SELF_PACKAGE_NAME = "SELF_PACKAGE_NAME" const val APP_PREFERENCES_NAME = "${BuildConfig.APPLICATION_ID}.app_preferences" const val BOOT_COMPLETED_RECEIVER_COMPONENT_NAME = "BOOT_COMPLETED_RECEIVER_COMPONENT_NAME" + +private val Context.userPreferencesStore: DataStore<UserPreferences> by + dataStore( + fileName = APP_PREFERENCES_NAME, + serializer = UserPreferencesSerializer, + produceMigrations = UserPreferencesMigration::migrations, + ) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/PrivacyDisclaimerRepository.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/PrivacyDisclaimerRepository.kt deleted file mode 100644 index db1ad220e3..0000000000 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/PrivacyDisclaimerRepository.kt +++ /dev/null @@ -1,15 +0,0 @@ -package net.mullvad.mullvadvpn.repository - -import android.content.SharedPreferences - -private const val IS_PRIVACY_DISCLOSURE_ACCEPTED_KEY = "is_privacy_disclosure_accepted" - -class PrivacyDisclaimerRepository(private val sharedPreferences: SharedPreferences) { - fun hasAcceptedPrivacyDisclosure(): Boolean { - return sharedPreferences.getBoolean(IS_PRIVACY_DISCLOSURE_ACCEPTED_KEY, false) - } - - fun setPrivacyDisclosureAccepted() { - sharedPreferences.edit().putBoolean(IS_PRIVACY_DISCLOSURE_ACCEPTED_KEY, true).apply() - } -} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/UserPreferencesMigration.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/UserPreferencesMigration.kt new file mode 100644 index 0000000000..c92d9d393a --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/UserPreferencesMigration.kt @@ -0,0 +1,31 @@ +package net.mullvad.mullvadvpn.repository + +import android.content.Context +import androidx.datastore.core.DataMigration +import androidx.datastore.migrations.SharedPreferencesMigration +import androidx.datastore.migrations.SharedPreferencesView +import net.mullvad.mullvadvpn.di.APP_PREFERENCES_NAME + +private const val IS_PRIVACY_DISCLOSURE_ACCEPTED_KEY_SHARED_PREF_KEY = + "is_privacy_disclosure_accepted" + +data object UserPreferencesMigration { + fun migrations(context: Context): List<DataMigration<UserPreferences>> = + listOf( + SharedPreferencesMigration( + context, + sharedPreferencesName = APP_PREFERENCES_NAME, + keysToMigrate = setOf(IS_PRIVACY_DISCLOSURE_ACCEPTED_KEY_SHARED_PREF_KEY), + ) { sharedPrefs: SharedPreferencesView, currentData: UserPreferences -> + val privacyDisclosureAccepted = + sharedPrefs.getBoolean( + IS_PRIVACY_DISCLOSURE_ACCEPTED_KEY_SHARED_PREF_KEY, + false, + ) + currentData + .toBuilder() + .setIsPrivacyDisclosureAccepted(privacyDisclosureAccepted) + .build() + } + ) +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/UserPreferencesRepository.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/UserPreferencesRepository.kt new file mode 100644 index 0000000000..f3e6a72b64 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/UserPreferencesRepository.kt @@ -0,0 +1,32 @@ +package net.mullvad.mullvadvpn.repository + +import androidx.datastore.core.DataStore +import co.touchlab.kermit.Logger +import java.io.IOException +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.first + +class UserPreferencesRepository(private val userPreferences: DataStore<UserPreferences>) { + + // Note: this should not be made into a StateFlow. See: + // https://developer.android.com/reference/kotlin/androidx/datastore/core/DataStore#data() + val preferencesFlow: Flow<UserPreferences> = + userPreferences.data.catch { exception -> + // dataStore.data throws an IOException when an error is encountered when reading data + if (exception is IOException) { + Logger.e("Error reading user preferences file, falling back to default.", exception) + emit(UserPreferences.getDefaultInstance()) + } else { + throw exception + } + } + + suspend fun preferences(): UserPreferences = preferencesFlow.first() + + suspend fun setPrivacyDisclosureAccepted() { + userPreferences.updateData { prefs -> + prefs.toBuilder().setIsPrivacyDisclosureAccepted(true).build() + } + } +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/UserPreferencesSerializer.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/UserPreferencesSerializer.kt new file mode 100644 index 0000000000..97348fd0cc --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/UserPreferencesSerializer.kt @@ -0,0 +1,21 @@ +package net.mullvad.mullvadvpn.repository + +import androidx.datastore.core.CorruptionException +import androidx.datastore.core.Serializer +import com.google.protobuf.InvalidProtocolBufferException +import java.io.InputStream +import java.io.OutputStream + +object UserPreferencesSerializer : Serializer<UserPreferences> { + override val defaultValue: UserPreferences = UserPreferences.getDefaultInstance() + + override suspend fun readFrom(input: InputStream): UserPreferences { + try { + return UserPreferences.parseFrom(input) + } catch (exception: InvalidProtocolBufferException) { + throw CorruptionException("Cannot read proto", exception) + } + } + + override suspend fun writeTo(t: UserPreferences, output: OutputStream) = t.writeTo(output) +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt index 4007b09ecd..76ec06d6cf 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt @@ -33,8 +33,8 @@ import net.mullvad.mullvadvpn.lib.endpoint.getApiEndpointConfigurationExtras import net.mullvad.mullvadvpn.lib.model.PrepareError import net.mullvad.mullvadvpn.lib.model.Prepared import net.mullvad.mullvadvpn.lib.theme.AppTheme -import net.mullvad.mullvadvpn.repository.PrivacyDisclaimerRepository import net.mullvad.mullvadvpn.repository.SplashCompleteRepository +import net.mullvad.mullvadvpn.repository.UserPreferencesRepository import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager import net.mullvad.mullvadvpn.viewmodel.MullvadAppViewModel import org.koin.android.ext.android.inject @@ -55,7 +55,7 @@ class MainActivity : ComponentActivity(), AndroidScopeComponent { private val apiEndpointFromIntentHolder by inject<ApiEndpointFromIntentHolder>() private val mullvadAppViewModel by inject<MullvadAppViewModel>() - private val privacyDisclaimerRepository by inject<PrivacyDisclaimerRepository>() + private val userPreferencesRepository by inject<UserPreferencesRepository>() private val serviceConnectionManager by inject<ServiceConnectionManager>() private val splashCompleteRepository by inject<SplashCompleteRepository>() private val managementService by inject<ManagementService>() @@ -93,7 +93,7 @@ class MainActivity : ComponentActivity(), AndroidScopeComponent { // https://medium.com/@lepicekmichal/android-background-service-without-hiccup-501e4479110f lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { - if (privacyDisclaimerRepository.hasAcceptedPrivacyDisclosure()) { + if (userPreferencesRepository.preferences().isPrivacyDisclosureAccepted) { bindService() } } @@ -103,7 +103,7 @@ class MainActivity : ComponentActivity(), AndroidScopeComponent { override fun onRestoreInstanceState(savedInstanceState: Bundle) { super.onRestoreInstanceState(savedInstanceState) lifecycleScope.launch { - if (privacyDisclaimerRepository.hasAcceptedPrivacyDisclosure()) { + if (userPreferencesRepository.preferences().isPrivacyDisclosureAccepted) { // If service is to be started wait for it to be connected before dismissing Splash // screen managementService.connectionState @@ -121,8 +121,10 @@ class MainActivity : ComponentActivity(), AndroidScopeComponent { override fun onStop() { super.onStop() - if (privacyDisclaimerRepository.hasAcceptedPrivacyDisclosure()) { - serviceConnectionManager.unbind() + lifecycleScope.launch { + if (userPreferencesRepository.preferences().isPrivacyDisclosureAccepted) { + serviceConnectionManager.unbind() + } } } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/PrivacyDisclaimerViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/PrivacyDisclaimerViewModel.kt index d2500bc94d..11800791d2 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/PrivacyDisclaimerViewModel.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/PrivacyDisclaimerViewModel.kt @@ -5,18 +5,17 @@ import androidx.lifecycle.viewModelScope import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.WhileSubscribed import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import net.mullvad.mullvadvpn.repository.PrivacyDisclaimerRepository +import net.mullvad.mullvadvpn.repository.UserPreferencesRepository data class PrivacyDisclaimerViewState(val isStartingService: Boolean, val isPlayBuild: Boolean) class PrivacyDisclaimerViewModel( - private val privacyDisclaimerRepository: PrivacyDisclaimerRepository, + private val userPreferencesRepository: UserPreferencesRepository, isPlayBuild: Boolean, ) : ViewModel() { @@ -40,8 +39,8 @@ class PrivacyDisclaimerViewModel( val uiSideEffect = _uiSideEffect.receiveAsFlow() fun setPrivacyDisclosureAccepted() { - privacyDisclaimerRepository.setPrivacyDisclosureAccepted() viewModelScope.launch { + userPreferencesRepository.setPrivacyDisclosureAccepted() if (!_isStartingService.value) { _isStartingService.update { true } _uiSideEffect.send(PrivacyDisclaimerUiSideEffect.StartService) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplashViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplashViewModel.kt index a196d4ae90..0ed85c94cd 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplashViewModel.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplashViewModel.kt @@ -16,13 +16,13 @@ import net.mullvad.mullvadvpn.constant.ACCOUNT_EXPIRY_TIMEOUT_MS import net.mullvad.mullvadvpn.lib.model.DeviceState import net.mullvad.mullvadvpn.lib.shared.AccountRepository import net.mullvad.mullvadvpn.lib.shared.DeviceRepository -import net.mullvad.mullvadvpn.repository.PrivacyDisclaimerRepository import net.mullvad.mullvadvpn.repository.SplashCompleteRepository +import net.mullvad.mullvadvpn.repository.UserPreferencesRepository data class SplashScreenState(val splashComplete: Boolean = false) class SplashViewModel( - private val privacyDisclaimerRepository: PrivacyDisclaimerRepository, + private val userPreferencesRepository: UserPreferencesRepository, private val accountRepository: AccountRepository, private val deviceRepository: DeviceRepository, private val splashCompleteRepository: SplashCompleteRepository, @@ -37,7 +37,7 @@ class SplashViewModel( val uiState: StateFlow<SplashScreenState> = _uiState private suspend fun getStartDestination(): SplashUiSideEffect { - if (!privacyDisclaimerRepository.hasAcceptedPrivacyDisclosure()) { + if (!userPreferencesRepository.preferences().isPrivacyDisclosureAccepted) { return SplashUiSideEffect.NavigateToPrivacyDisclaimer } diff --git a/android/app/src/main/proto/user_prefs.proto b/android/app/src/main/proto/user_prefs.proto new file mode 100644 index 0000000000..3a7e79285f --- /dev/null +++ b/android/app/src/main/proto/user_prefs.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; + +option java_package = "net.mullvad.mullvadvpn.repository"; +option java_multiple_files = true; + +message UserPreferences { bool is_privacy_disclosure_accepted = 1; } diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index 0a4b42d804..16a900284e 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -13,6 +13,7 @@ androidx-activitycompose = "1.9.3" androidx-appcompat = "1.7.0" androidx-ktx = "1.15.0" androidx-coresplashscreen = "1.1.0-rc01" +androidx-datastore = "1.1.1" androidx-espresso = "3.6.1" androidx-lifecycle = "2.8.7" androidx-test = "1.6.1" @@ -33,7 +34,6 @@ compose-material3 = "1.3.1" grpc = "1.69.0" grpc-kotlin = "1.4.1" grpc-kotlin-jar = "1.4.1:jdk8@jar" -grpc-protobuf = "4.29.1" # Koin koin = "4.0.0" @@ -51,7 +51,8 @@ kotlinx = "1.9.0" kotlinx-serialization = "2.1.0" # Protobuf -protobuf = "0.9.4" +protobuf-gradle-plugin = "0.9.4" +protobuf = "4.29.1" # Misc commonsvalidator = "1.9.0" @@ -81,6 +82,7 @@ android-volley = { module = "com.android.volley:volley", version.ref = "android- androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activitycompose" } androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" } androidx-coresplashscreen = { module = "androidx.core:core-splashscreen", version.ref = "androidx-coresplashscreen" } +androidx-datastore = { module = "androidx.datastore:datastore", version.ref = "androidx-datastore" } androidx-espresso = { module = "androidx.test.espresso:espresso-core", version.ref = "androidx-espresso" } androidx-ktx = { module = "androidx.core:core-ktx", version.ref = "androidx-ktx" } androidx-lifecycle-runtime = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidx-lifecycle" } @@ -119,7 +121,9 @@ grpc-okhttp = { module = "io.grpc:grpc-okhttp", version.ref = "grpc" } grpc-android = { module = "io.grpc:grpc-android", version.ref = "grpc" } grpc-kotlin-stub = { module = "io.grpc:grpc-kotlin-stub", version.ref = "grpc-kotlin" } grpc-protobuf-lite = { module = "io.grpc:grpc-protobuf-lite", version.ref = "grpc" } -grpc-protobuf-kotlin-lite = { module = "com.google.protobuf:protobuf-kotlin-lite", version.ref = "grpc-protobuf" } + +# Protobuf +protobuf-kotlin-lite = { module = "com.google.protobuf:protobuf-kotlin-lite", version.ref = "protobuf" } # Koin koin = { module = "io.insert-koin:koin-core", version.ref = "koin" } @@ -177,8 +181,8 @@ kotlin-ksp = { id = "com.google.devtools.ksp", version.ref = "kotlin-ksp" } kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlinx-serialization" } # Protobuf -protobuf-core = { id = "com.google.protobuf", version.ref = "protobuf" } -protobuf-protoc = { id = "com.google.protobuf:protoc", version.ref = "grpc-protobuf" } +protobuf-core = { id = "com.google.protobuf", version.ref = "protobuf-gradle-plugin" } +protobuf-protoc = { id = "com.google.protobuf:protoc", version.ref = "protobuf" } # gRPC grpc-protoc-gen-grpc-java = { id = "io.grpc:protoc-gen-grpc-java", version.ref = "grpc" } diff --git a/android/gradle/verification-metadata.xml b/android/gradle/verification-metadata.xml index f4f8e29109..bf6ad40f17 100644 --- a/android/gradle/verification-metadata.xml +++ b/android/gradle/verification-metadata.xml @@ -177,6 +177,7 @@ <trusting group="androidx.constraintlayout"/> <trusting group="androidx.core"/> <trusting group="androidx.databinding"/> + <trusting group="androidx.datastore"/> <trusting group="androidx.fragment"/> <trusting group="androidx.graphics"/> <trusting group="androidx.lifecycle"/> @@ -1478,6 +1479,70 @@ <sha256 value="b2431cbbe38d0a31e001b7c34f52f69a323fc9ec573b6afe5893daced5ab3285" origin="Generated by Gradle"/> </artifact> </component> + <component group="androidx.datastore" name="datastore" version="1.1.1"> + <artifact name="datastore-1.1.1.module"> + <sha256 value="2b621afac7661b553fffc1b1341a005ab077b2ea2908076ddbabe5fefbf89294" origin="Generated by Gradle"/> + </artifact> + <artifact name="datastore-metadata-1.1.1.jar"> + <sha256 value="4ab4086b6359ea81eb359451f0f005c78bc508d75c070555154cdf6313b0e1cb" origin="Generated by Gradle"/> + </artifact> + </component> + <component group="androidx.datastore" name="datastore-android" version="1.1.1"> + <artifact name="datastore-android-1.1.1.module"> + <sha256 value="723ee8ccf48382511221da21e0a3efdcdcf58b1de4894fddac405a1481119c25" origin="Generated by Gradle"/> + </artifact> + <artifact name="datastore-release.aar"> + <sha256 value="fce724038fea3bdef7b0d1aaf10cda6614b61bec66571750cc9be7048b950119" origin="Generated by Gradle"/> + </artifact> + </component> + <component group="androidx.datastore" name="datastore-core" version="1.1.1"> + <artifact name="datastore-core-1.1.1.module"> + <sha256 value="6ef39025e574d01a1aec000ef8d416368f1e8e15929c4fd746a383cefb36ae4e" origin="Generated by Gradle"/> + </artifact> + <artifact name="datastore-core-metadata-1.1.1.jar"> + <sha256 value="dfdcb0213751b038b5486a178d3e7f7f8cd0ce7d2888a0ba6a9f3bd1c9f16b7c" origin="Generated by Gradle"/> + </artifact> + </component> + <component group="androidx.datastore" name="datastore-core-android" version="1.1.1"> + <artifact name="datastore-core-android-1.1.1.module"> + <sha256 value="1df2659237979a7fb6a9ca8816b29ebda552bccf12b731a10ccd3ea296a5bc1a" origin="Generated by Gradle"/> + </artifact> + <artifact name="datastore-core-release.aar"> + <sha256 value="883abc911e4b14119959e44e20a520523f59c303e834d6b325007b3ee5e9cb6c" origin="Generated by Gradle"/> + </artifact> + </component> + <component group="androidx.datastore" name="datastore-core-jvm" version="1.1.1"> + <artifact name="datastore-core-jvm-1.1.1.jar"> + <sha256 value="30819f32f0cda25a2fc2e7c4a12045753e48b6b04cd126a1a42f010e441e022c" origin="Generated by Gradle"/> + </artifact> + <artifact name="datastore-core-jvm-1.1.1.module"> + <sha256 value="a4d1374322e61a0b6e517976f15c23519c3787069dd8de8577176b073af47b3a" origin="Generated by Gradle"/> + </artifact> + </component> + <component group="androidx.datastore" name="datastore-core-okio" version="1.1.1"> + <artifact name="datastore-core-okio-1.1.1.module"> + <sha256 value="e0e3e9e6429888f30c7e56e800decc0383a20e9baee505eea883574dfa0bd275" origin="Generated by Gradle"/> + </artifact> + <artifact name="datastore-core-okio-metadata-1.1.1.jar"> + <sha256 value="117beb462cad6a885864fe0296ed8cfee509da08d064c44d226efbd60538599b" origin="Generated by Gradle"/> + </artifact> + </component> + <component group="androidx.datastore" name="datastore-core-okio-jvm" version="1.1.1"> + <artifact name="datastore-core-okio-jvm-1.1.1.jar"> + <sha256 value="5071d03c7be9555fd81e5bd522b490a06a89694e4b937f307da72bc74e33c34a" origin="Generated by Gradle"/> + </artifact> + <artifact name="datastore-core-okio-jvm-1.1.1.module"> + <sha256 value="aef93f3081dbd8563e12ce375f065399fbc7563992c64be2214cefe2b4f1a2c2" origin="Generated by Gradle"/> + </artifact> + </component> + <component group="androidx.datastore" name="datastore-jvm" version="1.1.1"> + <artifact name="datastore-jvm-1.1.1.jar"> + <sha256 value="bbd2d9f6c8bcf5a7ae97b999bc6641ef304224b7392b4cea26b9cf87d7cb0281" origin="Generated by Gradle"/> + </artifact> + <artifact name="datastore-jvm-1.1.1.module"> + <sha256 value="e160533ba047931ddce738026f9189c1266f3e9c3d79ded9ec9404e84280a49a" origin="Generated by Gradle"/> + </artifact> + </component> <component group="androidx.drawerlayout" name="drawerlayout" version="1.0.0"> <artifact name="drawerlayout-1.0.0.aar"> <sha256 value="9402442cdc5a43cf62fb14f8cf98c63342d4d9d9b805c8033c6cf7e802749ac1" origin="Generated by Gradle"/> @@ -3707,6 +3772,9 @@ <artifact name="okio-3.4.0.module"> <sha256 value="69173608417a2113e6fa6afeb7b4540b20df70cfda3fa16c73aaa4fa702ffad3" origin="Generated by Gradle"/> </artifact> + <artifact name="okio-metadata-3.4.0-all.jar"> + <sha256 value="73570416f75fd20e1269c17c588884c3d1d1098a5cf4a15ccae3f4e1ab08329e" origin="Generated by Gradle"/> + </artifact> </component> <component group="com.squareup.okio" name="okio" version="3.6.0"> <artifact name="okio-3.6.0.module"> @@ -5810,6 +5878,11 @@ <sha256 value="858828bc5191b9e602affa14e01d66489dafb08c4c18d2faee3cbed7ba7d9992" origin="Generated by Gradle"/> </artifact> </component> + <component group="org.jetbrains.kotlin" name="kotlin-stdlib-common" version="1.9.21"> + <artifact name="kotlin-stdlib-common-1.9.21.module"> + <sha256 value="68dc8e84aa05f5278c16505247d71346d3512b9edadd41f613d657c94c59993b" origin="Generated by Gradle"/> + </artifact> + </component> <component group="org.jetbrains.kotlin" name="kotlin-stdlib-common" version="1.9.23"> <artifact name="kotlin-stdlib-common-1.9.23.module"> <sha256 value="8639f005fa9977aef08c32fc8e7a2779da22ee262464d7273298aafd483715cd" origin="Generated by Gradle"/> diff --git a/android/lib/daemon-grpc/build.gradle.kts b/android/lib/daemon-grpc/build.gradle.kts index e1807c9d34..9383121547 100644 --- a/android/lib/daemon-grpc/build.gradle.kts +++ b/android/lib/daemon-grpc/build.gradle.kts @@ -73,7 +73,7 @@ dependencies { implementation(libs.grpc.android) implementation(libs.grpc.kotlin.stub) implementation(libs.grpc.protobuf.lite) - implementation(libs.grpc.protobuf.kotlin.lite) + implementation(libs.protobuf.kotlin.lite) implementation(libs.arrow) implementation(libs.arrow.optics) |
