refactor: change qrcode scanner
This commit is contained in:
parent
2174c3f48c
commit
f8bc264f30
|
@ -129,8 +129,6 @@ dependencies {
|
||||||
ksp(libs.androidx.room.compiler)
|
ksp(libs.androidx.room.compiler)
|
||||||
implementation(libs.androidx.room.ktx)
|
implementation(libs.androidx.room.ktx)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//lifecycle
|
//lifecycle
|
||||||
implementation(libs.lifecycle.runtime.compose)
|
implementation(libs.lifecycle.runtime.compose)
|
||||||
|
|
||||||
|
@ -145,5 +143,6 @@ dependencies {
|
||||||
generalImplementation(libs.google.firebase.analytics.ktx)
|
generalImplementation(libs.google.firebase.analytics.ktx)
|
||||||
|
|
||||||
//barcode scanning
|
//barcode scanning
|
||||||
implementation(libs.play.services.code.scanner)
|
implementation(libs.zxing.android.embedded)
|
||||||
|
implementation(libs.zxing.core)
|
||||||
}
|
}
|
|
@ -58,6 +58,12 @@
|
||||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".ui.CaptureActivityPortrait"
|
||||||
|
android:screenOrientation="fullSensor"
|
||||||
|
android:stateNotNeeded="true"
|
||||||
|
android:theme="@style/zxing_CaptureTheme"
|
||||||
|
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||||
<activity
|
<activity
|
||||||
android:finishOnTaskLaunch="true"
|
android:finishOnTaskLaunch="true"
|
||||||
android:theme="@android:style/Theme.NoDisplay"
|
android:theme="@android:style/Theme.NoDisplay"
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
package com.zaneschepke.wireguardautotunnel.module
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.google.mlkit.vision.barcode.common.Barcode
|
|
||||||
import com.google.mlkit.vision.codescanner.GmsBarcodeScanner
|
|
||||||
import com.google.mlkit.vision.codescanner.GmsBarcodeScannerOptions
|
|
||||||
import com.google.mlkit.vision.codescanner.GmsBarcodeScanning
|
|
||||||
import com.zaneschepke.wireguardautotunnel.service.barcode.CodeScanner
|
|
||||||
import com.zaneschepke.wireguardautotunnel.service.barcode.QRScanner
|
|
||||||
import dagger.Module
|
|
||||||
import dagger.Provides
|
|
||||||
import dagger.hilt.InstallIn
|
|
||||||
import dagger.hilt.android.components.ViewModelComponent
|
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
|
||||||
import dagger.hilt.android.scopes.ViewModelScoped
|
|
||||||
|
|
||||||
@Module
|
|
||||||
@InstallIn(ViewModelComponent::class)
|
|
||||||
class ScannerModule {
|
|
||||||
|
|
||||||
@ViewModelScoped
|
|
||||||
@Provides
|
|
||||||
fun provideBarCodeOptions() : GmsBarcodeScannerOptions {
|
|
||||||
return GmsBarcodeScannerOptions.Builder()
|
|
||||||
.setBarcodeFormats(Barcode.FORMAT_QR_CODE)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
@ViewModelScoped
|
|
||||||
@Provides
|
|
||||||
fun provideBarCodeScanner(@ApplicationContext context: Context, options: GmsBarcodeScannerOptions) : GmsBarcodeScanner {
|
|
||||||
return GmsBarcodeScanning.getClient(context, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
@ViewModelScoped
|
|
||||||
@Provides
|
|
||||||
fun provideQRScanner(gmsBarcodeScanner: GmsBarcodeScanner) : CodeScanner {
|
|
||||||
return QRScanner(gmsBarcodeScanner)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package com.zaneschepke.wireguardautotunnel.service.barcode
|
|
||||||
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
|
|
||||||
interface CodeScanner {
|
|
||||||
fun scan() : Flow<String?>
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
package com.zaneschepke.wireguardautotunnel.service.barcode
|
|
||||||
|
|
||||||
import com.google.mlkit.vision.codescanner.GmsBarcodeScanner
|
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.callbackFlow
|
|
||||||
import timber.log.Timber
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class QRScanner @Inject constructor(private val gmsBarcodeScanner: GmsBarcodeScanner) : CodeScanner {
|
|
||||||
override fun scan(): Flow<String?> {
|
|
||||||
return callbackFlow {
|
|
||||||
gmsBarcodeScanner.startScan().addOnSuccessListener {
|
|
||||||
trySend(it.rawValue)
|
|
||||||
}.addOnFailureListener {
|
|
||||||
trySend(it.message)
|
|
||||||
Timber.e(it.message)
|
|
||||||
}
|
|
||||||
awaitClose {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.zaneschepke.wireguardautotunnel.ui;
|
||||||
|
|
||||||
|
import com.journeyapps.barcodescanner.CaptureActivity;
|
||||||
|
|
||||||
|
public class CaptureActivityPortrait extends CaptureActivity {
|
||||||
|
}
|
|
@ -70,7 +70,10 @@ import androidx.compose.ui.unit.dp
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import com.journeyapps.barcodescanner.ScanContract
|
||||||
|
import com.journeyapps.barcodescanner.ScanOptions
|
||||||
import com.wireguard.android.backend.Tunnel
|
import com.wireguard.android.backend.Tunnel
|
||||||
|
import com.zaneschepke.wireguardautotunnel.ui.CaptureActivityPortrait
|
||||||
import com.zaneschepke.wireguardautotunnel.R
|
import com.zaneschepke.wireguardautotunnel.R
|
||||||
import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel
|
import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel
|
||||||
import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig
|
import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig
|
||||||
|
@ -141,6 +144,11 @@ fun MainScreen(
|
||||||
result.data?.data?.let { viewModel.onTunnelFileSelected(it) }
|
result.data?.data?.let { viewModel.onTunnelFileSelected(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val scanLauncher = rememberLauncherForActivityResult(
|
||||||
|
contract = ScanContract(),
|
||||||
|
onResult = { result -> viewModel.onTunnelQrResult(result.contents) }
|
||||||
|
)
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier.pointerInput(Unit) {
|
modifier = Modifier.pointerInput(Unit) {
|
||||||
detectTapGestures(onTap = {
|
detectTapGestures(onTap = {
|
||||||
|
@ -219,7 +227,13 @@ fun MainScreen(
|
||||||
.clickable {
|
.clickable {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
showBottomSheet = false
|
showBottomSheet = false
|
||||||
viewModel.onTunnelQRSelected()
|
val scanOptions = ScanOptions()
|
||||||
|
scanOptions.setDesiredBarcodeFormats(ScanOptions.QR_CODE)
|
||||||
|
scanOptions.setOrientationLocked(true)
|
||||||
|
scanOptions.setPrompt(context.getString(R.string.scanning_qr))
|
||||||
|
scanOptions.setBeepEnabled(false)
|
||||||
|
scanOptions.captureActivity = CaptureActivityPortrait().javaClass
|
||||||
|
scanLauncher.launch(scanOptions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(10.dp)
|
.padding(10.dp)
|
||||||
|
|
|
@ -13,14 +13,13 @@ import com.zaneschepke.wireguardautotunnel.Constants
|
||||||
import com.zaneschepke.wireguardautotunnel.R
|
import com.zaneschepke.wireguardautotunnel.R
|
||||||
import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa
|
import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa
|
||||||
import com.zaneschepke.wireguardautotunnel.repository.TunnelConfigDao
|
import com.zaneschepke.wireguardautotunnel.repository.TunnelConfigDao
|
||||||
import com.zaneschepke.wireguardautotunnel.service.barcode.CodeScanner
|
import com.zaneschepke.wireguardautotunnel.repository.model.Settings
|
||||||
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceState
|
import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig
|
||||||
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
|
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
|
||||||
|
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceState
|
||||||
import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardConnectivityWatcherService
|
import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardConnectivityWatcherService
|
||||||
import com.zaneschepke.wireguardautotunnel.service.shortcut.ShortcutsManager
|
import com.zaneschepke.wireguardautotunnel.service.shortcut.ShortcutsManager
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService
|
import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService
|
||||||
import com.zaneschepke.wireguardautotunnel.repository.model.Settings
|
|
||||||
import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig
|
|
||||||
import com.zaneschepke.wireguardautotunnel.ui.ViewState
|
import com.zaneschepke.wireguardautotunnel.ui.ViewState
|
||||||
import com.zaneschepke.wireguardautotunnel.util.NumberUtils
|
import com.zaneschepke.wireguardautotunnel.util.NumberUtils
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
@ -38,8 +37,7 @@ import javax.inject.Inject
|
||||||
class MainViewModel @Inject constructor(private val application : Application,
|
class MainViewModel @Inject constructor(private val application : Application,
|
||||||
private val tunnelRepo : TunnelConfigDao,
|
private val tunnelRepo : TunnelConfigDao,
|
||||||
private val settingsRepo : SettingsDoa,
|
private val settingsRepo : SettingsDoa,
|
||||||
private val vpnService: VpnService,
|
private val vpnService: VpnService
|
||||||
private val codeScanner: CodeScanner
|
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
private val _viewState = MutableStateFlow(ViewState())
|
private val _viewState = MutableStateFlow(ViewState())
|
||||||
|
@ -96,13 +94,12 @@ class MainViewModel @Inject constructor(private val application : Application,
|
||||||
ServiceManager.stopVpnService(application.applicationContext)
|
ServiceManager.stopVpnService(application.applicationContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun onTunnelQRSelected() {
|
fun onTunnelQrResult(result : String) {
|
||||||
codeScanner.scan().collect {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
if(!it.isNullOrEmpty() && it.contains(application.resources.getString(R.string.config_validation))) {
|
if(result.contains(application.resources.getString(R.string.config_validation))) {
|
||||||
val tunnelConfig = TunnelConfig(name = NumberUtils.generateRandomTunnelName(), wgQuick = it)
|
val tunnelConfig =
|
||||||
|
TunnelConfig(name = NumberUtils.generateRandomTunnelName(), wgQuick = result)
|
||||||
saveTunnel(tunnelConfig)
|
saveTunnel(tunnelConfig)
|
||||||
} else if(!it.isNullOrEmpty() && it.contains(application.resources.getString(R.string.barcode_downloading))) {
|
|
||||||
showSnackBarMessage(application.resources.getString(R.string.barcode_downloading_message))
|
|
||||||
} else {
|
} else {
|
||||||
showSnackBarMessage(application.resources.getString(R.string.barcode_error))
|
showSnackBarMessage(application.resources.getString(R.string.barcode_error))
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,4 +92,5 @@
|
||||||
<string name="attempt_connection">Attempting connection..</string>
|
<string name="attempt_connection">Attempting connection..</string>
|
||||||
<string name="vpn_starting">VPN Starting</string>
|
<string name="vpn_starting">VPN Starting</string>
|
||||||
<string name="db_name">wg-tunnel-db</string>
|
<string name="db_name">wg-tunnel-db</string>
|
||||||
|
<string name="scanning_qr">Reading QR code</string>
|
||||||
</resources>
|
</resources>
|
|
@ -15,7 +15,6 @@ lifecycle-runtime-compose = "2.6.2"
|
||||||
material-icons-extended = "1.5.1"
|
material-icons-extended = "1.5.1"
|
||||||
material3 = "1.1.1"
|
material3 = "1.1.1"
|
||||||
navigationCompose = "2.7.2"
|
navigationCompose = "2.7.2"
|
||||||
playServicesCodeScanner = "16.1.0"
|
|
||||||
roomVersion = "2.6.0-beta01"
|
roomVersion = "2.6.0-beta01"
|
||||||
timber = "5.0.1"
|
timber = "5.0.1"
|
||||||
tunnel = "1.0.20230706"
|
tunnel = "1.0.20230706"
|
||||||
|
@ -28,6 +27,8 @@ compose="1.5.1"
|
||||||
crashlytics="18.4.1"
|
crashlytics="18.4.1"
|
||||||
analytics="21.3.0"
|
analytics="21.3.0"
|
||||||
composeCompiler="1.5.3"
|
composeCompiler="1.5.3"
|
||||||
|
zxingAndroidEmbedded = "4.3.0"
|
||||||
|
zxingCore = "3.4.1"
|
||||||
|
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
|
@ -69,7 +70,6 @@ junit = { module = "junit:junit", version.ref = "junit" }
|
||||||
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization-json" }
|
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization-json" }
|
||||||
lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycle-runtime-compose" }
|
lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycle-runtime-compose" }
|
||||||
material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "material-icons-extended" }
|
material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "material-icons-extended" }
|
||||||
play-services-code-scanner = { module = "com.google.android.gms:play-services-code-scanner", version.ref = "playServicesCodeScanner" }
|
|
||||||
|
|
||||||
timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
|
timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
|
||||||
|
|
||||||
|
@ -82,6 +82,9 @@ firebase-crashlytics-gradle = { module = "com.google.firebase:firebase-crashlyti
|
||||||
firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom"}
|
firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom"}
|
||||||
google-services = { module = "com.google.gms:google-services", version.ref = "google-services" }
|
google-services = { module = "com.google.gms:google-services", version.ref = "google-services" }
|
||||||
|
|
||||||
|
zxing-core = { module = "com.google.zxing:core", version.ref = "zxingCore" }
|
||||||
|
zxing-android-embedded = { module = "com.journeyapps:zxing-android-embedded", version.ref = "zxingAndroidEmbedded" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
|
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
|
||||||
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||||
|
|
Loading…
Reference in New Issue