refactor: change qrcode scanner

This commit is contained in:
Zane Schepke 2023-09-15 14:51:38 -04:00
parent 2174c3f48c
commit f8bc264f30
10 changed files with 44 additions and 88 deletions

View File

@ -129,8 +129,6 @@ dependencies {
ksp(libs.androidx.room.compiler)
implementation(libs.androidx.room.ktx)
//lifecycle
implementation(libs.lifecycle.runtime.compose)
@ -145,5 +143,6 @@ dependencies {
generalImplementation(libs.google.firebase.analytics.ktx)
//barcode scanning
implementation(libs.play.services.code.scanner)
implementation(libs.zxing.android.embedded)
implementation(libs.zxing.core)
}

View File

@ -58,6 +58,12 @@
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.CaptureActivityPortrait"
android:screenOrientation="fullSensor"
android:stateNotNeeded="true"
android:theme="@style/zxing_CaptureTheme"
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:finishOnTaskLaunch="true"
android:theme="@android:style/Theme.NoDisplay"

View File

@ -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)
}
}

View File

@ -1,7 +0,0 @@
package com.zaneschepke.wireguardautotunnel.service.barcode
import kotlinx.coroutines.flow.Flow
interface CodeScanner {
fun scan() : Flow<String?>
}

View File

@ -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 {
}
}
}
}

View File

@ -0,0 +1,6 @@
package com.zaneschepke.wireguardautotunnel.ui;
import com.journeyapps.barcodescanner.CaptureActivity;
public class CaptureActivityPortrait extends CaptureActivity {
}

View File

@ -70,7 +70,10 @@ import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavController
import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanOptions
import com.wireguard.android.backend.Tunnel
import com.zaneschepke.wireguardautotunnel.ui.CaptureActivityPortrait
import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel
import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig
@ -141,6 +144,11 @@ fun MainScreen(
result.data?.data?.let { viewModel.onTunnelFileSelected(it) }
}
val scanLauncher = rememberLauncherForActivityResult(
contract = ScanContract(),
onResult = { result -> viewModel.onTunnelQrResult(result.contents) }
)
Scaffold(
modifier = Modifier.pointerInput(Unit) {
detectTapGestures(onTap = {
@ -219,7 +227,13 @@ fun MainScreen(
.clickable {
scope.launch {
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)

View File

@ -13,14 +13,13 @@ import com.zaneschepke.wireguardautotunnel.Constants
import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa
import com.zaneschepke.wireguardautotunnel.repository.TunnelConfigDao
import com.zaneschepke.wireguardautotunnel.service.barcode.CodeScanner
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceState
import com.zaneschepke.wireguardautotunnel.repository.model.Settings
import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig
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.shortcut.ShortcutsManager
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.util.NumberUtils
import dagger.hilt.android.lifecycle.HiltViewModel
@ -38,8 +37,7 @@ import javax.inject.Inject
class MainViewModel @Inject constructor(private val application : Application,
private val tunnelRepo : TunnelConfigDao,
private val settingsRepo : SettingsDoa,
private val vpnService: VpnService,
private val codeScanner: CodeScanner
private val vpnService: VpnService
) : ViewModel() {
private val _viewState = MutableStateFlow(ViewState())
@ -96,13 +94,12 @@ class MainViewModel @Inject constructor(private val application : Application,
ServiceManager.stopVpnService(application.applicationContext)
}
suspend fun onTunnelQRSelected() {
codeScanner.scan().collect {
if(!it.isNullOrEmpty() && it.contains(application.resources.getString(R.string.config_validation))) {
val tunnelConfig = TunnelConfig(name = NumberUtils.generateRandomTunnelName(), wgQuick = it)
fun onTunnelQrResult(result : String) {
viewModelScope.launch(Dispatchers.IO) {
if(result.contains(application.resources.getString(R.string.config_validation))) {
val tunnelConfig =
TunnelConfig(name = NumberUtils.generateRandomTunnelName(), wgQuick = result)
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 {
showSnackBarMessage(application.resources.getString(R.string.barcode_error))
}

View File

@ -92,4 +92,5 @@
<string name="attempt_connection">Attempting connection..</string>
<string name="vpn_starting">VPN Starting</string>
<string name="db_name">wg-tunnel-db</string>
<string name="scanning_qr">Reading QR code</string>
</resources>

View File

@ -15,7 +15,6 @@ lifecycle-runtime-compose = "2.6.2"
material-icons-extended = "1.5.1"
material3 = "1.1.1"
navigationCompose = "2.7.2"
playServicesCodeScanner = "16.1.0"
roomVersion = "2.6.0-beta01"
timber = "5.0.1"
tunnel = "1.0.20230706"
@ -28,6 +27,8 @@ compose="1.5.1"
crashlytics="18.4.1"
analytics="21.3.0"
composeCompiler="1.5.3"
zxingAndroidEmbedded = "4.3.0"
zxingCore = "3.4.1"
[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" }
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" }
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" }
@ -82,6 +82,9 @@ firebase-crashlytics-gradle = { module = "com.google.firebase:firebase-crashlyti
firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom"}
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]
android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }