From 2abf681d17ae2bc579a04816f83d4caa3029d4a0 Mon Sep 17 00:00:00 2001 From: Zane Schepke Date: Fri, 4 Aug 2023 16:43:36 -0400 Subject: [PATCH] feat: support Android 9 Added support for Android 9 by updating permission checks and wifi SSID logic. Fix bug where setting screen was cut off on AndroidTV by updating padding values. Bump wireguard-android library version. Closes #13, Closes #16 --- app/build.gradle.kts | 6 +-- .../WireGuardAutoTunnel.kt | 8 ++++ .../service/network/BaseNetworkService.kt | 20 +++++----- .../ui/screens/main/MainScreen.kt | 11 +++--- .../ui/screens/settings/SettingsScreen.kt | 37 ++++++++++++------- .../ui/screens/support/SupportScreen.kt | 5 --- 6 files changed, 51 insertions(+), 36 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8115e8d..51e242f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -17,12 +17,12 @@ android { val versionMajor = 2 val versionMinor = 3 - val versionPatch = 2 + val versionPatch = 3 val versionBuild = 0 defaultConfig { applicationId = "com.zaneschepke.wireguardautotunnel" - minSdk = 29 + minSdk = 28 targetSdk = 34 versionCode = versionMajor * 10000 + versionMinor * 1000 + versionPatch * 100 + versionBuild versionName = "${versionMajor}.${versionMinor}.${versionPatch}" @@ -83,7 +83,7 @@ dependencies { debugImplementation("androidx.compose.ui:ui-test-manifest") //wireguard tunnel - implementation("com.wireguard.android:tunnel:1.0.20230427") + implementation("com.wireguard.android:tunnel:1.0.20230706") //logging implementation("com.jakewharton.timber:timber:5.0.1") diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt index b05cb9a..bdd6c40 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt @@ -1,6 +1,8 @@ package com.zaneschepke.wireguardautotunnel import android.app.Application +import android.content.Context +import android.content.pm.PackageManager import com.google.firebase.crashlytics.FirebaseCrashlytics import com.zaneschepke.wireguardautotunnel.repository.Repository import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings @@ -22,4 +24,10 @@ class WireGuardAutoTunnel : Application() { } settingsRepo.init() } + + companion object { + fun isRunningOnAndroidTv(context : Context) : Boolean { + return context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/BaseNetworkService.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/BaseNetworkService.kt index f6f3745..312617a 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/BaseNetworkService.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/network/BaseNetworkService.kt @@ -45,6 +45,7 @@ abstract class BaseNetworkService>(val context: Contex } } } + else -> { object : ConnectivityManager.NetworkCallback() { @@ -77,8 +78,8 @@ abstract class BaseNetworkService>(val context: Contex override fun getNetworkName(networkCapabilities: NetworkCapabilities): String? { - var ssid : String? = getWifiNameFromCapabilities(networkCapabilities) - if((Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) || (Build.VERSION.SDK_INT == Build.VERSION_CODES.R)) { + var ssid: String? = getWifiNameFromCapabilities(networkCapabilities) + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { val info = wifiManager.connectionInfo if (info.supplicantState === SupplicantState.COMPLETED) { ssid = info.ssid @@ -89,14 +90,15 @@ abstract class BaseNetworkService>(val context: Contex companion object { - private fun getWifiNameFromCapabilities(networkCapabilities: NetworkCapabilities) : String? { - val info : WifiInfo - if(networkCapabilities.transportInfo is WifiInfo) { - info = networkCapabilities.transportInfo as WifiInfo - } else { - return null + private fun getWifiNameFromCapabilities(networkCapabilities: NetworkCapabilities): String? { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + val info: WifiInfo + if (networkCapabilities.transportInfo is WifiInfo) { + info = networkCapabilities.transportInfo as WifiInfo + return info.ssid + } } - return info.ssid + return null } } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt index 9842faf..2cb3e0a 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt @@ -1,7 +1,6 @@ package com.zaneschepke.wireguardautotunnel.ui.screens.main import android.annotation.SuppressLint -import android.content.pm.PackageManager import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.animation.AnimatedVisibility @@ -52,7 +51,6 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment -import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester @@ -73,6 +71,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController import com.wireguard.android.backend.Tunnel import com.zaneschepke.wireguardautotunnel.R +import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel import com.zaneschepke.wireguardautotunnel.service.tunnel.HandshakeStatus import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig import com.zaneschepke.wireguardautotunnel.ui.Routes @@ -246,12 +245,12 @@ fun MainScreen( .nestedScroll(nestedScrollConnection),) { items(tunnels.toList()) { tunnel -> RowListItem(leadingIcon = Icons.Rounded.Circle, - leadingIconColor = when (handshakeStatus) { + leadingIconColor = if (tunnelName == tunnel.name) when (handshakeStatus) { HandshakeStatus.HEALTHY -> mint HandshakeStatus.UNHEALTHY -> brickRed HandshakeStatus.NOT_STARTED -> Color.Gray HandshakeStatus.NEVER_CONNECTED -> brickRed - }, + } else Color.Gray, text = tunnel.name, onHold = { if (state == Tunnel.State.UP && tunnel.name == tunnelName) { @@ -264,7 +263,7 @@ fun MainScreen( selectedTunnel = tunnel; }, onClick = { - if(!context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)){ + if(!WireGuardAutoTunnel.isRunningOnAndroidTv(context)){ navController.navigate("${Routes.Detail.name}/${tunnel.id}") } else { focusRequester.requestFocus() @@ -288,7 +287,7 @@ fun MainScreen( } } } else { - if(context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)){ + if(WireGuardAutoTunnel.isRunningOnAndroidTv(context)){ Row() { IconButton(modifier = Modifier.focusRequester(focusRequester),onClick = { navController.navigate("${Routes.Detail.name}/${tunnel.id}") diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsScreen.kt index 77659ce..713ac6e 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsScreen.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsScreen.kt @@ -2,8 +2,8 @@ package com.zaneschepke.wireguardautotunnel.ui.screens.settings import android.Manifest import android.content.Intent -import android.content.pm.PackageManager import android.net.Uri +import android.os.Build import android.provider.Settings import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource @@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -67,6 +68,7 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.isGranted import com.google.accompanist.permissions.rememberPermissionState import com.zaneschepke.wireguardautotunnel.R +import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig import com.zaneschepke.wireguardautotunnel.ui.Routes import com.zaneschepke.wireguardautotunnel.ui.common.ClickableIconButton @@ -134,7 +136,7 @@ fun SettingsScreen( } } - if(!backgroundLocationState.status.isGranted) { + if(!backgroundLocationState.status.isGranted && Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Top, modifier = Modifier @@ -147,7 +149,9 @@ fun SettingsScreen( Text(stringResource(R.string.prominent_background_location_title), textAlign = TextAlign.Center, modifier = Modifier.padding(30.dp), fontSize = 20.sp) Text(stringResource(R.string.prominent_background_location_message), textAlign = TextAlign.Center, modifier = Modifier.padding(30.dp), fontSize = 15.sp) Row( - modifier = Modifier + modifier = if(WireGuardAutoTunnel.isRunningOnAndroidTv(context)) Modifier + .fillMaxWidth() + .padding(10.dp) else Modifier .fillMaxWidth() .padding(30.dp), verticalAlignment = Alignment.CenterVertically, @@ -209,7 +213,7 @@ fun SettingsScreen( } return } - if(!isLocationServicesEnabled) { + if(!isLocationServicesEnabled && Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, @@ -237,11 +241,18 @@ fun SettingsScreen( } return } - + val screenPadding = if(WireGuardAutoTunnel.isRunningOnAndroidTv(context)) 5.dp else 15.dp Column( horizontalAlignment = Alignment.Start, verticalArrangement = Arrangement.Top, - modifier = Modifier + modifier = if(WireGuardAutoTunnel.isRunningOnAndroidTv(context)) Modifier + .fillMaxHeight(.85f) + .fillMaxWidth() + .verticalScroll(scrollState) + .clickable(indication = null, interactionSource = interactionSource) { + focusManager.clearFocus() + } + .padding(padding) else Modifier .fillMaxSize() .verticalScroll(scrollState) .clickable(indication = null, interactionSource = interactionSource) { @@ -252,7 +263,7 @@ fun SettingsScreen( Row( modifier = Modifier .fillMaxWidth() - .padding(14.dp), + .padding(screenPadding), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { @@ -271,7 +282,7 @@ fun SettingsScreen( Text( stringResource(id = R.string.select_tunnel), textAlign = TextAlign.Center, - modifier = Modifier.padding(15.dp, bottom = 5.dp, top = 5.dp) + modifier = Modifier.padding(screenPadding, bottom = 5.dp, top = 5.dp) ) ExposedDropdownMenuBox( expanded = expanded, @@ -319,10 +330,10 @@ fun SettingsScreen( Text( stringResource(R.string.trusted_ssid), textAlign = TextAlign.Center, - modifier = Modifier.padding(15.dp, bottom = 5.dp, top = 5.dp) + modifier = Modifier.padding(screenPadding, bottom = 5.dp, top = 5.dp) ) FlowRow( - modifier = Modifier.padding(15.dp), + modifier = Modifier.padding(screenPadding), horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically ) { @@ -339,7 +350,7 @@ fun SettingsScreen( value = currentText, onValueChange = { currentText = it }, label = { Text(stringResource(R.string.add_trusted_ssid)) }, - modifier = Modifier.padding(start = 15.dp, top = 5.dp), + modifier = Modifier.padding(start = screenPadding, top = 5.dp), maxLines = 1, keyboardOptions = KeyboardOptions( capitalization = KeyboardCapitalization.None, @@ -365,7 +376,7 @@ fun SettingsScreen( Row( modifier = Modifier .fillMaxWidth() - .padding(14.dp), + .padding(screenPadding), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { @@ -383,7 +394,7 @@ fun SettingsScreen( Row( modifier = Modifier .fillMaxWidth() - .padding(14.dp), + .padding(screenPadding), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/support/SupportScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/support/SupportScreen.kt index 5ab5b13..c219eee 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/support/SupportScreen.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/support/SupportScreen.kt @@ -72,11 +72,6 @@ fun SupportScreen(padding : PaddingValues, focusRequester: FocusRequester) { }) { Icon(imageVector = ImageVector.vectorResource(R.drawable.github), "Github") } -// LaunchedEffect(Unit) { -// if(context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) { -// focusRequester.requestFocus() -// } -// } } Spacer(modifier = Modifier.weight(1f)) Text(stringResource(id = R.string.privacy_policy), style = TextStyle(textDecoration = TextDecoration.Underline),