Skip to content

Commit

Permalink
Merge branch 'main' into translate
Browse files Browse the repository at this point in the history
  • Loading branch information
Daviteusz committed Nov 1, 2023
2 parents dca6eaa + 505272f commit 65e95db
Show file tree
Hide file tree
Showing 60 changed files with 1,194 additions and 479 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class ActivityUtil(private val activity: Activity) {
MAIN_ACTIVITY_ALIAS,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED
)
logger.debug("Enabled USB discovery by setting state of $MAIN_ACTIVITY_ALIAS to ENABLED")
}

/**
Expand All @@ -55,6 +56,7 @@ class ActivityUtil(private val activity: Activity) {
MAIN_ACTIVITY_ALIAS,
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
)
logger.debug("Disabled USB discovery by setting state of $MAIN_ACTIVITY_ALIAS to DEFAULT")
}

/**
Expand All @@ -73,6 +75,7 @@ class ActivityUtil(private val activity: Activity) {
NDEF_ACTIVITY_ALIAS,
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
)
logger.debug("Enabled NFC discovery by setting state of $NDEF_ACTIVITY_ALIAS to DEFAULT")
}

/**
Expand All @@ -88,6 +91,7 @@ class ActivityUtil(private val activity: Activity) {
NDEF_ACTIVITY_ALIAS,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED
)
logger.debug("Disabled NFC discovery by setting state of $NDEF_ACTIVITY_ALIAS to DISABLED")
}

private fun setState(aliasName: String, enabledState: Int) {
Expand Down
114 changes: 67 additions & 47 deletions android/app/src/main/kotlin/com/yubico/authenticator/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ class MainActivity : FlutterFragmentActivity() {

private lateinit var yubikit: YubiKitManager

private var preserveConnectionOnPause: Boolean = false

// receives broadcasts when QR Scanner camera is closed
private val qrScannerCameraClosedBR = QRScannerCameraClosedBR()
private val nfcAdapterStateChangeBR = NfcAdapterStateChangedBR()
Expand Down Expand Up @@ -158,8 +160,12 @@ class MainActivity : FlutterFragmentActivity() {

appPreferences.unregisterListener(sharedPreferencesListener)

stopUsbDiscovery()
stopNfcDiscovery()
if (!preserveConnectionOnPause) {
stopUsbDiscovery()
stopNfcDiscovery()
} else {
logger.debug("Any existing connections are preserved")
}

if (!appPreferences.openAppOnUsb) {
activityUtil.disableSystemUsbDiscovery()
Expand All @@ -179,62 +185,68 @@ class MainActivity : FlutterFragmentActivity() {

activityUtil.enableSystemUsbDiscovery()

// Handle opening through otpauth:// link
val intentData = intent.data
if (intentData != null &&
(intentData.scheme == "otpauth" ||
intentData.scheme == "otpauth-migration")
) {
intent.data = null
appLinkMethodChannel.handleUri(intentData)
}

// Handle existing tag when launched from NDEF
val tag = intent.parcelableExtra<Tag>(NfcAdapter.EXTRA_TAG)
if (tag != null) {
intent.removeExtra(NfcAdapter.EXTRA_TAG)
if (!preserveConnectionOnPause) {
// Handle opening through otpauth:// link
val intentData = intent.data
if (intentData != null &&
(intentData.scheme == "otpauth" ||
intentData.scheme == "otpauth-migration")
) {
intent.data = null
appLinkMethodChannel.handleUri(intentData)
}

val executor = Executors.newSingleThreadExecutor()
val device = NfcYubiKeyDevice(tag, nfcConfiguration.timeout, executor)
lifecycleScope.launch {
try {
contextManager?.processYubiKey(device)
device.remove {
executor.shutdown()
startNfcDiscovery()
// Handle existing tag when launched from NDEF
val tag = intent.parcelableExtra<Tag>(NfcAdapter.EXTRA_TAG)
if (tag != null) {
intent.removeExtra(NfcAdapter.EXTRA_TAG)

val executor = Executors.newSingleThreadExecutor()
val device = NfcYubiKeyDevice(tag, nfcConfiguration.timeout, executor)
lifecycleScope.launch {
try {
contextManager?.processYubiKey(device)
device.remove {
executor.shutdown()
startNfcDiscovery()
}
} catch (e: Throwable) {
logger.error("Error processing YubiKey in AppContextManager", e)
}
} catch (e: Throwable) {
logger.error("Error processing YubiKey in AppContextManager", e)
}
} else {
startNfcDiscovery()
}
} else {
startNfcDiscovery()
}

val usbManager = getSystemService(Context.USB_SERVICE) as UsbManager
if (UsbManager.ACTION_USB_DEVICE_ATTACHED == intent.action) {
val device = intent.parcelableExtra<UsbDevice>(UsbManager.EXTRA_DEVICE)
if (device != null) {
// start the USB discover only if the user approved the app to use the device
if (usbManager.hasPermission(device)) {
startUsbDiscovery()
val usbManager = getSystemService(Context.USB_SERVICE) as UsbManager
if (UsbManager.ACTION_USB_DEVICE_ATTACHED == intent.action) {
val device = intent.parcelableExtra<UsbDevice>(UsbManager.EXTRA_DEVICE)
if (device != null) {
// start the USB discover only if the user approved the app to use the device
if (usbManager.hasPermission(device)) {
startUsbDiscovery()
}
}
}
} else {
// if any YubiKeys are connected, use them directly
val deviceIterator = usbManager.deviceList.values.iterator()
while (deviceIterator.hasNext()) {
val device = deviceIterator.next()
if (device.vendorId == YUBICO_VENDOR_ID) {
// the device might not have a USB permission
// it will be requested during during the UsbDiscovery
startUsbDiscovery()
break
} else {
// if any YubiKeys are connected, use them directly
val deviceIterator = usbManager.deviceList.values.iterator()
while (deviceIterator.hasNext()) {
val device = deviceIterator.next()
if (device.vendorId == YUBICO_VENDOR_ID) {
// the device might not have a USB permission
// it will be requested during during the UsbDiscovery
startUsbDiscovery()
break
}
}
}
} else {
logger.debug("Resume with preserved connection")
}

appPreferences.registerListener(sharedPreferencesListener)

preserveConnectionOnPause = false
}

override fun onMultiWindowModeChanged(isInMultiWindowMode: Boolean, newConfig: Configuration) {
Expand Down Expand Up @@ -374,6 +386,14 @@ class MainActivity : FlutterFragmentActivity() {
"getAndroidSdkVersion" -> result.success(
Build.VERSION.SDK_INT
)

"preserveConnectionOnPause" -> {
preserveConnectionOnPause = true
result.success(
true
)
}

"setPrimaryClip" -> {
val toClipboard = methodCall.argument<String>("toClipboard")
val isSensitive = methodCall.argument<Boolean>("isSensitive")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ class OathManager(
delay(delayMs)
}
val currentState = lifecycleOwner.lifecycle.currentState
if (currentState.isAtLeast(Lifecycle.State.RESUMED)) {
if (currentState.isAtLeast(Lifecycle.State.STARTED)) {
requestRefresh()
} else {
logger.debug(
Expand Down
8 changes: 4 additions & 4 deletions android/flutter_plugins/qrscanner_zxing/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,16 @@ android {

defaultConfig {
minSdkVersion 21
targetSdk 34
}
}

dependencies {
def camerax_version = "1.2.3"
def camerax_version = "1.3.0"
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
implementation "androidx.camera:camera-view:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"

//noinspection GradleDependency
implementation "com.google.zxing:core:3.3.3"

implementation "com.google.zxing:core:3.5.2"
implementation "com.google.zxing:android-core:3.3.0"
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Fri Jun 23 08:50:38 CEST 2017
#Mon Oct 16 08:48:17 CEST 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022 Yubico.
* Copyright (C) 2022-2023 Yubico.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -22,8 +22,6 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.provider.Settings
import android.util.Log
import android.util.Size
Expand All @@ -36,14 +34,19 @@ import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.startActivity
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.Observer
import com.google.zxing.*
import com.google.zxing.BinaryBitmap
import com.google.zxing.NotFoundException
import com.google.zxing.RGBLuminanceSource
import com.google.zxing.common.HybridBinarizer
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.json.JSONObject
import java.nio.ByteBuffer
import java.util.concurrent.ExecutorService
Expand Down Expand Up @@ -80,7 +83,7 @@ internal class QRScannerView(
) : PlatformView {

private val stateChangeObserver = StateChangeObserver(context)
private val uiThreadHandler = Handler(Looper.getMainLooper())
private val coroutineScope = CoroutineScope(Dispatchers.Main)

companion object {
const val TAG = "QRScannerView"
Expand All @@ -104,11 +107,17 @@ internal class QRScannerView(
}

private fun requestPermissions(activity: Activity) {
ActivityCompat.requestPermissions(
activity,
PERMISSIONS_TO_REQUEST,
PERMISSION_REQUEST_CODE
)
coroutineScope.launch {
methodChannel.invokeMethod(
"beforePermissionsRequest", null
)

ActivityCompat.requestPermissions(
activity,
PERMISSIONS_TO_REQUEST,
PERMISSION_REQUEST_CODE
)
}
}

private val qrScannerView = View.inflate(context, R.layout.qr_scanner_view, null)
Expand Down Expand Up @@ -147,7 +156,6 @@ internal class QRScannerView(
return qrScannerView
}


override fun dispose() {
cameraProvider?.unbindAll()
preview = null
Expand Down Expand Up @@ -229,7 +237,7 @@ internal class QRScannerView(
}

private fun reportViewInitialized(permissionsGranted: Boolean) {
uiThreadHandler.post {
coroutineScope.launch {
methodChannel.invokeMethod(
"viewInitialized",
JSONObject(mapOf("permissionsGranted" to permissionsGranted)).toString()
Expand All @@ -238,7 +246,7 @@ internal class QRScannerView(
}

private fun reportCodeFound(code: String) {
uiThreadHandler.post {
coroutineScope.launch {
methodChannel.invokeMethod(
"codeFound", JSONObject(
mapOf("value" to code)
Expand Down Expand Up @@ -290,11 +298,6 @@ internal class QRScannerView(
) : ImageAnalysis.Analyzer {

var analysisPaused = false

val multiFormatReader = MultiFormatReader().also {
it.setHints(mapOf(DecodeHintType.POSSIBLE_FORMATS to listOf(BarcodeFormat.QR_CODE)))
}

var analyzedImagesCount = 0

private fun ByteBuffer.toByteArray(lastRowPadding: Int): ByteArray {
Expand Down Expand Up @@ -392,14 +395,14 @@ internal class QRScannerView(
fullSize
}

val result: com.google.zxing.Result = multiFormatReader.decode(bitmapToProcess)
val result = QrCodeScanner.decodeFromBinaryBitmap(bitmapToProcess)
if (analysisPaused) {
return
}

analysisPaused = true // pause
Log.v(TAG, "Analysis result: ${result.text}")
listener.invoke(Result.success(result.text))
Log.v(TAG, "Analysis result: $result")
listener.invoke(Result.success(result))
} catch (_: NotFoundException) {
if (analyzedImagesCount == 0) {
Log.v(TAG, " No QR code found (NotFoundException)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,24 @@ class QRScannerZxingPlugin : FlutterPlugin, MethodCallHandler, ActivityAware,
}

override fun onMethodCall(call: MethodCall, result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else {
result.notImplemented()
when (call.method) {
"getPlatformVersion" -> {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
}

"scanBitmap" -> {
val bytes = call.argument<ByteArray>("bytes")
if (bytes != null) {
val scanResult = QrCodeScanner.decodeFromBytes(bytes)
result.success(scanResult)
} else {
result.error("Failure", "Invalid image", null)
}
}

else -> {
result.notImplemented()
}
}
}

Expand Down
Loading

0 comments on commit 65e95db

Please sign in to comment.