feat: support Android 8
Add support for Android 8. Fix shortcuts bug where it was toggling auto-tunneling without setting enabled. Fix shortcuts name not updating with config edits. Bump versions. Closes #25
This commit is contained in:
parent
e81066f508
commit
69b07eec6f
|
@ -17,12 +17,12 @@ android {
|
||||||
|
|
||||||
val versionMajor = 2
|
val versionMajor = 2
|
||||||
val versionMinor = 4
|
val versionMinor = 4
|
||||||
val versionPatch = 4
|
val versionPatch = 5
|
||||||
val versionBuild = 0
|
val versionBuild = 0
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "com.zaneschepke.wireguardautotunnel"
|
applicationId = "com.zaneschepke.wireguardautotunnel"
|
||||||
minSdk = 28
|
minSdk = 26
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = versionMajor * 10000 + versionMinor * 1000 + versionPatch * 100 + versionBuild
|
versionCode = versionMajor * 10000 + versionMinor * 1000 + versionPatch * 100 + versionBuild
|
||||||
versionName = "${versionMajor}.${versionMinor}.${versionPatch}"
|
versionName = "${versionMajor}.${versionMinor}.${versionPatch}"
|
||||||
|
@ -64,8 +64,8 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("androidx.core:core-ktx:1.10.1")
|
implementation("androidx.core:core-ktx:1.12.0")
|
||||||
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1")
|
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
|
||||||
implementation("androidx.activity:activity-compose:1.7.2")
|
implementation("androidx.activity:activity-compose:1.7.2")
|
||||||
implementation(platform("androidx.compose:compose-bom:2023.03.00"))
|
implementation(platform("androidx.compose:compose-bom:2023.03.00"))
|
||||||
implementation("androidx.compose.ui:ui")
|
implementation("androidx.compose.ui:ui")
|
||||||
|
@ -89,7 +89,7 @@ dependencies {
|
||||||
implementation("com.jakewharton.timber:timber:5.0.1")
|
implementation("com.jakewharton.timber:timber:5.0.1")
|
||||||
|
|
||||||
// compose navigation
|
// compose navigation
|
||||||
implementation("androidx.navigation:navigation-compose:2.7.1")
|
implementation("androidx.navigation:navigation-compose:2.7.2")
|
||||||
implementation("androidx.hilt:hilt-navigation-compose:1.0.0")
|
implementation("androidx.hilt:hilt-navigation-compose:1.0.0")
|
||||||
|
|
||||||
// hilt
|
// hilt
|
||||||
|
@ -107,10 +107,10 @@ dependencies {
|
||||||
implementation("io.objectbox:objectbox-kotlin:${rExtra.get("objectBoxVersion")}")
|
implementation("io.objectbox:objectbox-kotlin:${rExtra.get("objectBoxVersion")}")
|
||||||
|
|
||||||
//lifecycle
|
//lifecycle
|
||||||
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.1")
|
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.2")
|
||||||
|
|
||||||
//icons
|
//icons
|
||||||
implementation("androidx.compose.material:material-icons-extended:1.5.0")
|
implementation("androidx.compose.material:material-icons-extended:1.5.1")
|
||||||
|
|
||||||
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
|
||||||
|
|
|
@ -3,19 +3,44 @@ package com.zaneschepke.wireguardautotunnel.service.shortcut
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.zaneschepke.wireguardautotunnel.R
|
import com.zaneschepke.wireguardautotunnel.R
|
||||||
|
import com.zaneschepke.wireguardautotunnel.repository.Repository
|
||||||
import com.zaneschepke.wireguardautotunnel.service.foreground.Action
|
import com.zaneschepke.wireguardautotunnel.service.foreground.Action
|
||||||
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
|
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
|
||||||
import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardTunnelService
|
import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardTunnelService
|
||||||
|
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class ShortcutsActivity : AppCompatActivity() {
|
class ShortcutsActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var settingsRepo : Repository<Settings>
|
||||||
|
|
||||||
|
private val scope = CoroutineScope(Dispatchers.Main);
|
||||||
|
|
||||||
|
private fun attemptWatcherServiceToggle(tunnelConfig : String) {
|
||||||
|
scope.launch {
|
||||||
|
val settings = settingsRepo.getAll()
|
||||||
|
if (!settings.isNullOrEmpty()) {
|
||||||
|
val setting = settings.first()
|
||||||
|
if(setting.isAutoTunnelEnabled) {
|
||||||
|
ServiceManager.toggleWatcherServiceForeground(this@ShortcutsActivity, tunnelConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
if(intent.getStringExtra(ShortcutsManager.CLASS_NAME_EXTRA_KEY)
|
if(intent.getStringExtra(ShortcutsManager.CLASS_NAME_EXTRA_KEY)
|
||||||
.equals(WireGuardTunnelService::class.java.name)) {
|
.equals(WireGuardTunnelService::class.java.name)) {
|
||||||
|
|
||||||
intent.getStringExtra(getString(R.string.tunnel_extras_key))?.let {
|
intent.getStringExtra(getString(R.string.tunnel_extras_key))?.let {
|
||||||
ServiceManager.toggleWatcherService(this, it)
|
attemptWatcherServiceToggle(it)
|
||||||
}
|
}
|
||||||
when(intent.action){
|
when(intent.action){
|
||||||
Action.STOP.name -> ServiceManager.stopVpnService(this)
|
Action.STOP.name -> ServiceManager.stopVpnService(this)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import androidx.compose.runtime.toMutableStateList
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.zaneschepke.wireguardautotunnel.repository.Repository
|
import com.zaneschepke.wireguardautotunnel.repository.Repository
|
||||||
|
import com.zaneschepke.wireguardautotunnel.service.shortcut.ShortcutsManager
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings
|
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig
|
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
@ -114,12 +115,14 @@ class ConfigViewModel @Inject constructor(private val application : Application,
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
packageManager.getPackagesHoldingPermissions(permissions, PackageManager.PackageInfoFlags.of(0L))
|
packageManager.getPackagesHoldingPermissions(permissions, PackageManager.PackageInfoFlags.of(0L))
|
||||||
} else {
|
} else {
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
packageManager.getPackagesHoldingPermissions(permissions, 0)
|
packageManager.getPackagesHoldingPermissions(permissions, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun onSaveAllChanges() {
|
suspend fun onSaveAllChanges() {
|
||||||
|
if(_tunnel.value != null) {
|
||||||
|
ShortcutsManager.removeTunnelShortcuts(application, _tunnel.value!!)
|
||||||
|
}
|
||||||
var wgQuick = _tunnel.value?.wgQuick
|
var wgQuick = _tunnel.value?.wgQuick
|
||||||
if(wgQuick != null) {
|
if(wgQuick != null) {
|
||||||
wgQuick = if(_include.value) {
|
wgQuick = if(_include.value) {
|
||||||
|
@ -135,6 +138,7 @@ class ConfigViewModel @Inject constructor(private val application : Application,
|
||||||
wgQuick = wgQuick
|
wgQuick = wgQuick
|
||||||
)?.let {
|
)?.let {
|
||||||
tunnelRepo.save(it)
|
tunnelRepo.save(it)
|
||||||
|
ShortcutsManager.createTunnelShortcuts(application, it)
|
||||||
val settings = settingsRepo.getAll()
|
val settings = settingsRepo.getAll()
|
||||||
if(settings != null) {
|
if(settings != null) {
|
||||||
val setting = settings[0]
|
val setting = settings[0]
|
||||||
|
|
|
@ -249,7 +249,7 @@ fun MainScreen(
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.nestedScroll(nestedScrollConnection),
|
.nestedScroll(nestedScrollConnection),
|
||||||
) {
|
) {
|
||||||
itemsIndexed(tunnels.toList()) { index, tunnel ->
|
itemsIndexed(tunnels.toList()) { _, tunnel ->
|
||||||
val focusRequester = FocusRequester();
|
val focusRequester = FocusRequester();
|
||||||
RowListItem(leadingIcon = Icons.Rounded.Circle,
|
RowListItem(leadingIcon = Icons.Rounded.Circle,
|
||||||
leadingIconColor = if (tunnelName == tunnel.name) when (handshakeStatus) {
|
leadingIconColor = if (tunnelName == tunnel.name) when (handshakeStatus) {
|
||||||
|
|
|
@ -96,8 +96,6 @@ fun SettingsScreen(
|
||||||
val settings by viewModel.settings.collectAsStateWithLifecycle()
|
val settings by viewModel.settings.collectAsStateWithLifecycle()
|
||||||
val trustedSSIDs by viewModel.trustedSSIDs.collectAsStateWithLifecycle()
|
val trustedSSIDs by viewModel.trustedSSIDs.collectAsStateWithLifecycle()
|
||||||
val tunnels by viewModel.tunnels.collectAsStateWithLifecycle(mutableListOf())
|
val tunnels by viewModel.tunnels.collectAsStateWithLifecycle(mutableListOf())
|
||||||
val backgroundLocationState =
|
|
||||||
rememberPermissionState(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
|
|
||||||
val fineLocationState = rememberPermissionState(Manifest.permission.ACCESS_FINE_LOCATION)
|
val fineLocationState = rememberPermissionState(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||||
var currentText by remember { mutableStateOf("") }
|
var currentText by remember { mutableStateOf("") }
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
|
@ -135,41 +133,44 @@ fun SettingsScreen(
|
||||||
context.startActivity(intentSettings)
|
context.startActivity(intentSettings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
if(!backgroundLocationState.status.isGranted && Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
|
val backgroundLocationState =
|
||||||
Column(horizontalAlignment = Alignment.CenterHorizontally,
|
rememberPermissionState(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
|
||||||
verticalArrangement = Arrangement.Top,
|
if(!backgroundLocationState.status.isGranted) {
|
||||||
modifier = Modifier
|
Column(horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
.fillMaxSize()
|
verticalArrangement = Arrangement.Top,
|
||||||
.verticalScroll(scrollState)
|
modifier = Modifier
|
||||||
.padding(padding)) {
|
.fillMaxSize()
|
||||||
Icon(Icons.Rounded.LocationOff, contentDescription = stringResource(id = R.string.map), modifier = Modifier
|
.verticalScroll(scrollState)
|
||||||
.padding(30.dp)
|
.padding(padding)) {
|
||||||
.size(128.dp))
|
Icon(Icons.Rounded.LocationOff, contentDescription = stringResource(id = R.string.map), modifier = Modifier
|
||||||
Text(stringResource(R.string.prominent_background_location_title), textAlign = TextAlign.Center, modifier = Modifier.padding(30.dp), fontSize = 20.sp)
|
.padding(30.dp)
|
||||||
Text(stringResource(R.string.prominent_background_location_message), textAlign = TextAlign.Center, modifier = Modifier.padding(30.dp), fontSize = 15.sp)
|
.size(128.dp))
|
||||||
Row(
|
Text(stringResource(R.string.prominent_background_location_title), textAlign = TextAlign.Center, modifier = Modifier.padding(30.dp), fontSize = 20.sp)
|
||||||
modifier = if(WireGuardAutoTunnel.isRunningOnAndroidTv(context)) Modifier
|
Text(stringResource(R.string.prominent_background_location_message), textAlign = TextAlign.Center, modifier = Modifier.padding(30.dp), fontSize = 15.sp)
|
||||||
.fillMaxWidth()
|
Row(
|
||||||
.padding(10.dp) else Modifier
|
modifier = if(WireGuardAutoTunnel.isRunningOnAndroidTv(context)) Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(30.dp),
|
.padding(10.dp) else Modifier
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
.fillMaxWidth()
|
||||||
horizontalArrangement = Arrangement.SpaceEvenly
|
.padding(30.dp),
|
||||||
) {
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
Button(onClick = {
|
horizontalArrangement = Arrangement.SpaceEvenly
|
||||||
navController.navigate(Routes.Main.name)
|
) {
|
||||||
}) {
|
Button(onClick = {
|
||||||
Text(stringResource(id = R.string.no_thanks))
|
navController.navigate(Routes.Main.name)
|
||||||
}
|
}) {
|
||||||
Button(modifier = Modifier.focusRequester(focusRequester), onClick = {
|
Text(stringResource(id = R.string.no_thanks))
|
||||||
openSettings()
|
}
|
||||||
}) {
|
Button(modifier = Modifier.focusRequester(focusRequester), onClick = {
|
||||||
Text(stringResource(id = R.string.turn_on))
|
openSettings()
|
||||||
|
}) {
|
||||||
|
Text(stringResource(id = R.string.turn_on))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!fineLocationState.status.isGranted) {
|
if(!fineLocationState.status.isGranted) {
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
val objectBoxVersion by extra("3.5.1")
|
val objectBoxVersion by extra("3.7.0")
|
||||||
val hiltVersion by extra("2.47")
|
val hiltVersion by extra("2.48")
|
||||||
val accompanistVersion by extra("0.31.2-alpha")
|
val accompanistVersion by extra("0.31.2-alpha")
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath("io.objectbox:objectbox-gradle-plugin:$objectBoxVersion")
|
classpath("io.objectbox:objectbox-gradle-plugin:$objectBoxVersion")
|
||||||
classpath("com.google.gms:google-services:4.3.15")
|
classpath("com.google.gms:google-services:4.3.15")
|
||||||
classpath("com.google.firebase:firebase-crashlytics-gradle:2.9.7")
|
classpath("com.google.firebase:firebase-crashlytics-gradle:2.9.9")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application") version "8.2.0-beta03" apply false
|
id("com.android.application") version "8.2.0-beta03" apply false
|
||||||
id("org.jetbrains.kotlin.android") version "1.8.22" apply false
|
id("org.jetbrains.kotlin.android") version "1.8.22" apply false
|
||||||
id("com.google.dagger.hilt.android") version "2.44" apply false
|
id("com.google.dagger.hilt.android") version "2.48" apply false
|
||||||
kotlin("plugin.serialization") version "1.8.22" apply false
|
kotlin("plugin.serialization") version "1.8.22" apply false
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue