大幅変更&環境バージョンアップ
This commit is contained in:
67
plugin/qr_code_scanner/android/.gitignore
vendored
Normal file
67
plugin/qr_code_scanner/android/.gitignore
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
# Built application files
|
||||
*.apk
|
||||
*.ap_
|
||||
*.aab
|
||||
|
||||
# Files for the ART/Dalvik VM
|
||||
*.dex
|
||||
|
||||
# Java class files
|
||||
*.class
|
||||
|
||||
# Generated files
|
||||
bin/
|
||||
gen/
|
||||
out/
|
||||
|
||||
# Gradle files
|
||||
.gradle/
|
||||
build/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
# Proguard folder generated by Eclipse
|
||||
proguard/
|
||||
|
||||
# Log Files
|
||||
*.log
|
||||
|
||||
# Android Studio Navigation editor temp files
|
||||
.navigation/
|
||||
|
||||
# Android Studio captures folder
|
||||
captures/
|
||||
|
||||
# IntelliJ
|
||||
*.iml
|
||||
.idea/workspace.xml
|
||||
.idea/tasks.xml
|
||||
.idea/gradle.xml
|
||||
.idea/assetWizardSettings.xml
|
||||
.idea/dictionaries
|
||||
.idea/libraries
|
||||
.idea/caches
|
||||
|
||||
# Keystore files
|
||||
# Uncomment the following lines if you do not want to check your keystore files in.
|
||||
#*.jks
|
||||
#*.keystore
|
||||
|
||||
# External native build folder generated in Android Studio 2.2 and later
|
||||
.externalNativeBuild
|
||||
|
||||
# Google Services (e.g. APIs or Firebase)
|
||||
google-services.json
|
||||
|
||||
# Freeline
|
||||
freeline.py
|
||||
freeline/
|
||||
freeline_project_description.json
|
||||
|
||||
# fastlane
|
||||
fastlane/report.xml
|
||||
fastlane/Preview.html
|
||||
fastlane/screenshots
|
||||
fastlane/test_output
|
||||
fastlane/readme.md
|
||||
64
plugin/qr_code_scanner/android/build.gradle
Normal file
64
plugin/qr_code_scanner/android/build.gradle
Normal file
@ -0,0 +1,64 @@
|
||||
group 'net.touchcapture.qr.flutterqr'
|
||||
version '1.0-SNAPSHOT'
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.8.22' //''1.9.0'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.3.0' //8.1.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
namespace 'net.touchcapture.qr.flutterqr'
|
||||
compileSdk 34
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
}
|
||||
defaultConfig {
|
||||
// minSdkVersion is determined by Native View.
|
||||
minSdkVersion 20
|
||||
targetSdkVersion 34
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
multiDexEnabled true
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = '11'
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
// Flag to enable support for the new language APIs
|
||||
coreLibraryDesugaringEnabled true
|
||||
// Sets Java compatibility to Java 11
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
if (project.android.hasProperty('namespace')) {
|
||||
namespace 'net.touchcapture.qr.flutterqr'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation('com.journeyapps:zxing-android-embedded:4.3.0') { transitive = false }
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'com.google.zxing:core:3.5.2'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
|
||||
}
|
||||
3
plugin/qr_code_scanner/android/gradle.properties
Normal file
3
plugin/qr_code_scanner/android/gradle.properties
Normal file
@ -0,0 +1,3 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.enableJetifier=true
|
||||
android.useAndroidX=true
|
||||
5
plugin/qr_code_scanner/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
plugin/qr_code_scanner/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
1
plugin/qr_code_scanner/android/settings.gradle
Normal file
1
plugin/qr_code_scanner/android/settings.gradle
Normal file
@ -0,0 +1 @@
|
||||
rootProject.name = 'flutter_qr'
|
||||
@ -0,0 +1,4 @@
|
||||
<manifest package="net.touchcapture.qr.flutterqr"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<uses-sdk tools:overrideLibrary="com.google.zxing.client.android" />
|
||||
</manifest>
|
||||
@ -0,0 +1,45 @@
|
||||
package net.touchcapture.qr.flutterqr
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import android.util.AttributeSet
|
||||
import com.journeyapps.barcodescanner.BarcodeView
|
||||
import com.journeyapps.barcodescanner.Size
|
||||
|
||||
class CustomFramingRectBarcodeView : BarcodeView {
|
||||
private var bottomOffset = BOTTOM_OFFSET_NOT_SET_VALUE
|
||||
|
||||
constructor(context: Context?) : super(context)
|
||||
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
|
||||
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
|
||||
context,
|
||||
attrs,
|
||||
defStyleAttr
|
||||
)
|
||||
|
||||
override fun calculateFramingRect(container: Rect, surface: Rect): Rect {
|
||||
val containerArea = Rect(container)
|
||||
val intersects =
|
||||
containerArea.intersect(surface) //adjusts the containerArea (code from super.calculateFramingRect)
|
||||
val scanAreaRect = super.calculateFramingRect(container, surface)
|
||||
if (bottomOffset != BOTTOM_OFFSET_NOT_SET_VALUE) { //if the setFramingRect function was called, then we shift the scan area by Y
|
||||
val scanAreaRectWithOffset = Rect(scanAreaRect)
|
||||
scanAreaRectWithOffset.bottom -= bottomOffset
|
||||
scanAreaRectWithOffset.top -= bottomOffset
|
||||
val belongsToContainer = scanAreaRectWithOffset.intersect(containerArea)
|
||||
if (belongsToContainer) {
|
||||
return scanAreaRectWithOffset
|
||||
}
|
||||
}
|
||||
return scanAreaRect
|
||||
}
|
||||
|
||||
fun setFramingRect(rectWidth: Int, rectHeight: Int, bottomOffset: Int) {
|
||||
this.bottomOffset = bottomOffset
|
||||
framingRectSize = Size(rectWidth, rectHeight)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val BOTTOM_OFFSET_NOT_SET_VALUE = -1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package net.touchcapture.qr.flutterqr
|
||||
|
||||
import androidx.annotation.NonNull
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
||||
|
||||
class FlutterQrPlugin : FlutterPlugin, ActivityAware {
|
||||
|
||||
/** Plugin registration embedding v2 */
|
||||
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
||||
flutterPluginBinding.platformViewRegistry
|
||||
.registerViewFactory(
|
||||
VIEW_TYPE_ID,
|
||||
QRViewFactory(flutterPluginBinding.binaryMessenger)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
|
||||
// Leave empty
|
||||
// Nullifying QrShared.activity and QrShared.binding here will cause errors if plugin is detached by another plugin
|
||||
}
|
||||
|
||||
override fun onAttachedToActivity(activityPluginBinding: ActivityPluginBinding) {
|
||||
QrShared.activity = activityPluginBinding.activity
|
||||
QrShared.binding = activityPluginBinding
|
||||
}
|
||||
|
||||
override fun onDetachedFromActivityForConfigChanges() {
|
||||
QrShared.activity = null
|
||||
QrShared.binding = null
|
||||
}
|
||||
|
||||
override fun onReattachedToActivityForConfigChanges(activityPluginBinding: ActivityPluginBinding) {
|
||||
QrShared.activity = activityPluginBinding.activity
|
||||
QrShared.binding = activityPluginBinding
|
||||
}
|
||||
|
||||
override fun onDetachedFromActivity() {
|
||||
QrShared.activity = null
|
||||
QrShared.binding = null
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val VIEW_TYPE_ID = "net.touchcapture.qr.flutterqr/qrview"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,386 @@
|
||||
package net.touchcapture.qr.flutterqr
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.google.zxing.BarcodeFormat
|
||||
import com.google.zxing.ResultPoint
|
||||
import com.journeyapps.barcodescanner.BarcodeCallback
|
||||
import com.journeyapps.barcodescanner.BarcodeResult
|
||||
import com.journeyapps.barcodescanner.DefaultDecoderFactory
|
||||
import io.flutter.plugin.common.BinaryMessenger
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import io.flutter.plugin.common.PluginRegistry
|
||||
import io.flutter.plugin.platform.PlatformView
|
||||
|
||||
class QRView(
|
||||
private val context: Context,
|
||||
messenger: BinaryMessenger,
|
||||
private val id: Int,
|
||||
private val params: HashMap<String, Any>
|
||||
) : PlatformView, MethodChannel.MethodCallHandler, PluginRegistry.RequestPermissionsResultListener {
|
||||
|
||||
private val cameraRequestCode = QrShared.CAMERA_REQUEST_ID + this.id
|
||||
|
||||
private val channel: MethodChannel = MethodChannel(
|
||||
messenger, "net.touchcapture.qr.flutterqr/qrview_$id"
|
||||
)
|
||||
private val cameraFacingBack = 0
|
||||
private val cameraFacingFront = 1
|
||||
|
||||
private var isRequestingPermission = false
|
||||
private var isTorchOn = false
|
||||
private var isPaused = false
|
||||
private var barcodeView: CustomFramingRectBarcodeView? = null
|
||||
private var unRegisterLifecycleCallback: UnRegisterLifecycleCallback? = null
|
||||
|
||||
init {
|
||||
QrShared.binding?.addRequestPermissionsResultListener(this)
|
||||
|
||||
channel.setMethodCallHandler(this)
|
||||
|
||||
unRegisterLifecycleCallback = QrShared.activity?.registerLifecycleCallbacks(
|
||||
onPause = {
|
||||
if (!isPaused && hasCameraPermission) barcodeView?.pause()
|
||||
|
||||
},
|
||||
onResume = {
|
||||
if (!hasCameraPermission && !isRequestingPermission) checkAndRequestPermission()
|
||||
else if (!isPaused && hasCameraPermission) barcodeView?.resume()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
unRegisterLifecycleCallback?.invoke()
|
||||
|
||||
QrShared.binding?.removeRequestPermissionsResultListener(this)
|
||||
|
||||
barcodeView?.pause()
|
||||
barcodeView = null
|
||||
}
|
||||
|
||||
override fun getView(): View = initBarCodeView()
|
||||
|
||||
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
when (call.method) {
|
||||
"startScan" -> startScan(call.arguments as? List<Int>, result)
|
||||
|
||||
"stopScan" -> stopScan()
|
||||
|
||||
"flipCamera" -> flipCamera(result)
|
||||
|
||||
"toggleFlash" -> toggleFlash(result)
|
||||
|
||||
"pauseCamera" -> pauseCamera(result)
|
||||
|
||||
// Stopping camera is the same as pausing camera
|
||||
"stopCamera" -> pauseCamera(result)
|
||||
|
||||
"resumeCamera" -> resumeCamera(result)
|
||||
|
||||
"requestPermissions" -> checkAndRequestPermission()
|
||||
|
||||
"getCameraInfo" -> getCameraInfo(result)
|
||||
|
||||
"getFlashInfo" -> getFlashInfo(result)
|
||||
|
||||
"getSystemFeatures" -> getSystemFeatures(result)
|
||||
|
||||
"changeScanArea" -> changeScanArea(
|
||||
dpScanAreaWidth = requireNotNull(call.argument<Double>("scanAreaWidth")),
|
||||
dpScanAreaHeight = requireNotNull(call.argument<Double>("scanAreaHeight")),
|
||||
cutOutBottomOffset = requireNotNull(call.argument<Double>("cutOutBottomOffset")),
|
||||
result = result,
|
||||
)
|
||||
|
||||
"invertScan" -> setInvertScan(
|
||||
isInvert = call.argument<Boolean>("isInvertScan") ?: false,
|
||||
)
|
||||
|
||||
else -> result.notImplemented()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initBarCodeView(): CustomFramingRectBarcodeView {
|
||||
var barcodeView = barcodeView
|
||||
|
||||
if (barcodeView == null) {
|
||||
barcodeView = CustomFramingRectBarcodeView(QrShared.activity).also {
|
||||
this.barcodeView = it
|
||||
}
|
||||
|
||||
barcodeView.decoderFactory = DefaultDecoderFactory(null, null, null, 2)
|
||||
|
||||
if (params[PARAMS_CAMERA_FACING] as Int == 1) {
|
||||
barcodeView.cameraSettings?.requestedCameraId = cameraFacingFront
|
||||
}
|
||||
} else if (!isPaused) {
|
||||
barcodeView.resume()
|
||||
}
|
||||
|
||||
return barcodeView
|
||||
}
|
||||
|
||||
// region Camera Info
|
||||
|
||||
private fun getCameraInfo(result: MethodChannel.Result) {
|
||||
val barcodeView = barcodeView ?: return barCodeViewNotSet(result)
|
||||
|
||||
result.success(barcodeView.cameraSettings.requestedCameraId)
|
||||
}
|
||||
|
||||
private fun getFlashInfo(result: MethodChannel.Result) {
|
||||
if (barcodeView == null) return barCodeViewNotSet(result)
|
||||
|
||||
result.success(isTorchOn)
|
||||
}
|
||||
|
||||
private fun hasFlash(): Boolean {
|
||||
return hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)
|
||||
}
|
||||
|
||||
@SuppressLint("UnsupportedChromeOsCameraSystemFeature")
|
||||
private fun hasBackCamera(): Boolean {
|
||||
return hasSystemFeature(PackageManager.FEATURE_CAMERA)
|
||||
}
|
||||
|
||||
private fun hasFrontCamera(): Boolean {
|
||||
return hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)
|
||||
}
|
||||
|
||||
private fun hasSystemFeature(feature: String): Boolean =
|
||||
context.packageManager.hasSystemFeature(feature)
|
||||
|
||||
private fun getSystemFeatures(result: MethodChannel.Result) {
|
||||
try {
|
||||
result.success(
|
||||
mapOf(
|
||||
"hasFrontCamera" to hasFrontCamera(),
|
||||
"hasBackCamera" to hasBackCamera(),
|
||||
"hasFlash" to hasFlash(),
|
||||
"activeCamera" to barcodeView?.cameraSettings?.requestedCameraId
|
||||
)
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
result.error("", e.message, null)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Camera Controls
|
||||
|
||||
private fun flipCamera(result: MethodChannel.Result) {
|
||||
val barcodeView = barcodeView ?: return barCodeViewNotSet(result)
|
||||
|
||||
barcodeView.pause()
|
||||
|
||||
val settings = barcodeView.cameraSettings
|
||||
if (settings.requestedCameraId == cameraFacingFront) {
|
||||
settings.requestedCameraId = cameraFacingBack
|
||||
} else settings.requestedCameraId = cameraFacingFront
|
||||
|
||||
barcodeView.resume()
|
||||
|
||||
result.success(settings.requestedCameraId)
|
||||
}
|
||||
|
||||
private fun toggleFlash(result: MethodChannel.Result) {
|
||||
val barcodeView = barcodeView ?: return barCodeViewNotSet(result)
|
||||
|
||||
if (hasFlash()) {
|
||||
barcodeView.setTorch(!isTorchOn)
|
||||
isTorchOn = !isTorchOn
|
||||
result.success(isTorchOn)
|
||||
} else {
|
||||
result.error(ERROR_CODE_NOT_SET, ERROR_MESSAGE_FLASH_NOT_FOUND, null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun pauseCamera(result: MethodChannel.Result) {
|
||||
val barcodeView = barcodeView ?: return barCodeViewNotSet(result)
|
||||
|
||||
if (barcodeView.isPreviewActive) {
|
||||
isPaused = true
|
||||
barcodeView.pause()
|
||||
}
|
||||
|
||||
result.success(true)
|
||||
}
|
||||
|
||||
private fun resumeCamera(result: MethodChannel.Result) {
|
||||
val barcodeView = barcodeView ?: return barCodeViewNotSet(result)
|
||||
|
||||
if (!barcodeView.isPreviewActive) {
|
||||
isPaused = false
|
||||
barcodeView.resume()
|
||||
}
|
||||
|
||||
result.success(true)
|
||||
}
|
||||
|
||||
private fun startScan(arguments: List<Int>?, result: MethodChannel.Result) {
|
||||
checkAndRequestPermission()
|
||||
|
||||
val allowedBarcodeTypes = getAllowedBarcodeTypes(arguments, result)
|
||||
|
||||
if (arguments == null) {
|
||||
barcodeView?.decoderFactory = DefaultDecoderFactory(null, null, null, 2)
|
||||
} else {
|
||||
barcodeView?.decoderFactory = DefaultDecoderFactory(allowedBarcodeTypes, null, null, 2)
|
||||
}
|
||||
|
||||
barcodeView?.decodeContinuous(
|
||||
object : BarcodeCallback {
|
||||
override fun barcodeResult(result: BarcodeResult) {
|
||||
if (allowedBarcodeTypes.isEmpty() || allowedBarcodeTypes.contains(result.barcodeFormat)) {
|
||||
val code = mapOf(
|
||||
"code" to result.text,
|
||||
"type" to result.barcodeFormat.name,
|
||||
"rawBytes" to result.rawBytes
|
||||
)
|
||||
|
||||
channel.invokeMethod(CHANNEL_METHOD_ON_RECOGNIZE_QR, code)
|
||||
}
|
||||
}
|
||||
|
||||
override fun possibleResultPoints(resultPoints: List<ResultPoint>) = Unit
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun stopScan() {
|
||||
barcodeView?.stopDecoding()
|
||||
}
|
||||
|
||||
private fun setInvertScan(isInvert: Boolean) {
|
||||
val barcodeView = barcodeView ?: return
|
||||
with(barcodeView) {
|
||||
pause()
|
||||
cameraSettings.isScanInverted = isInvert
|
||||
resume()
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeScanArea(
|
||||
dpScanAreaWidth: Double,
|
||||
dpScanAreaHeight: Double,
|
||||
cutOutBottomOffset: Double,
|
||||
result: MethodChannel.Result
|
||||
) {
|
||||
setScanAreaSize(dpScanAreaWidth, dpScanAreaHeight, cutOutBottomOffset)
|
||||
|
||||
result.success(true)
|
||||
}
|
||||
|
||||
private fun setScanAreaSize(
|
||||
dpScanAreaWidth: Double,
|
||||
dpScanAreaHeight: Double,
|
||||
dpCutOutBottomOffset: Double
|
||||
) {
|
||||
barcodeView?.setFramingRect(
|
||||
dpScanAreaWidth.convertDpToPixels(),
|
||||
dpScanAreaHeight.convertDpToPixels(),
|
||||
dpCutOutBottomOffset.convertDpToPixels(),
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region permissions
|
||||
|
||||
private val hasCameraPermission: Boolean
|
||||
get() = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
|
||||
ContextCompat.checkSelfPermission(
|
||||
context,
|
||||
Manifest.permission.CAMERA
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<out String>,
|
||||
grantResults: IntArray
|
||||
): Boolean {
|
||||
if (requestCode != cameraRequestCode) return false
|
||||
isRequestingPermission = false
|
||||
|
||||
val permissionGranted =
|
||||
grantResults.firstOrNull() == PackageManager.PERMISSION_GRANTED
|
||||
|
||||
channel.invokeMethod(CHANNEL_METHOD_ON_PERMISSION_SET, permissionGranted)
|
||||
|
||||
return permissionGranted
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun checkAndRequestPermission() {
|
||||
if (hasCameraPermission) {
|
||||
channel.invokeMethod(CHANNEL_METHOD_ON_PERMISSION_SET, true)
|
||||
return
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !isRequestingPermission) {
|
||||
QrShared.activity?.requestPermissions(
|
||||
arrayOf(Manifest.permission.CAMERA),
|
||||
cameraRequestCode
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region barcode common
|
||||
|
||||
private fun getAllowedBarcodeTypes(
|
||||
arguments: List<Int>?,
|
||||
result: MethodChannel.Result
|
||||
): List<BarcodeFormat> {
|
||||
return try {
|
||||
arguments?.map {
|
||||
BarcodeFormat.values()[it]
|
||||
}.orEmpty()
|
||||
} catch (e: Exception) {
|
||||
result.error("", e.message, null)
|
||||
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun barCodeViewNotSet(result: MethodChannel.Result) {
|
||||
result.error(
|
||||
ERROR_CODE_NOT_SET,
|
||||
ERROR_MESSAGE_NOT_SET,
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region helpers
|
||||
|
||||
private fun Double.convertDpToPixels() =
|
||||
(this * context.resources.displayMetrics.density).toInt()
|
||||
|
||||
// endregion
|
||||
|
||||
companion object {
|
||||
private const val CHANNEL_METHOD_ON_PERMISSION_SET = "onPermissionSet"
|
||||
private const val CHANNEL_METHOD_ON_RECOGNIZE_QR = "onRecognizeQR"
|
||||
|
||||
private const val PARAMS_CAMERA_FACING = "cameraFacing"
|
||||
|
||||
private const val ERROR_CODE_NOT_SET = "404"
|
||||
|
||||
private const val ERROR_MESSAGE_NOT_SET = "No barcode view found"
|
||||
private const val ERROR_MESSAGE_FLASH_NOT_FOUND = "This device doesn't support flash"
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
package net.touchcapture.qr.flutterqr
|
||||
|
||||
import android.content.Context
|
||||
import io.flutter.plugin.common.BinaryMessenger
|
||||
import io.flutter.plugin.common.StandardMessageCodec
|
||||
import io.flutter.plugin.platform.PlatformView
|
||||
import io.flutter.plugin.platform.PlatformViewFactory
|
||||
|
||||
|
||||
class QRViewFactory(
|
||||
private val messenger: BinaryMessenger
|
||||
) : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
|
||||
|
||||
override fun create(
|
||||
context: Context?,
|
||||
viewId: Int,
|
||||
args: Any?
|
||||
): PlatformView {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val params = args as HashMap<String, Any>
|
||||
|
||||
return QRView(
|
||||
context = requireNotNull(context),
|
||||
id = viewId,
|
||||
messenger = messenger,
|
||||
params = params
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package net.touchcapture.qr.flutterqr
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.os.Bundle
|
||||
|
||||
class UnRegisterLifecycleCallback(
|
||||
private val application: Application,
|
||||
private val callback: Application.ActivityLifecycleCallbacks,
|
||||
) {
|
||||
operator fun invoke() = application.unregisterActivityLifecycleCallbacks(callback)
|
||||
}
|
||||
|
||||
fun Activity.registerLifecycleCallbacks(
|
||||
onPause: (() -> Unit)? = null,
|
||||
onResume: (() -> Unit)? = null,
|
||||
): UnRegisterLifecycleCallback {
|
||||
val callback = object : Application.ActivityLifecycleCallbacks {
|
||||
override fun onActivityPaused(p0: Activity) {
|
||||
if (p0 == this@registerLifecycleCallbacks) onPause?.invoke()
|
||||
}
|
||||
|
||||
override fun onActivityResumed(p0: Activity) {
|
||||
if (p0 == this@registerLifecycleCallbacks) onResume?.invoke()
|
||||
}
|
||||
|
||||
override fun onActivityStarted(p0: Activity) = Unit
|
||||
|
||||
override fun onActivityDestroyed(p0: Activity) = Unit
|
||||
|
||||
override fun onActivitySaveInstanceState(p0: Activity, p1: Bundle) = Unit
|
||||
|
||||
override fun onActivityStopped(p0: Activity) = Unit
|
||||
|
||||
override fun onActivityCreated(p0: Activity, p1: Bundle?) = Unit
|
||||
}
|
||||
|
||||
application.registerActivityLifecycleCallbacks(callback)
|
||||
|
||||
return UnRegisterLifecycleCallback(application, callback)
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package net.touchcapture.qr.flutterqr
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
object QrShared {
|
||||
const val CAMERA_REQUEST_ID = 513469796
|
||||
|
||||
var activity: Activity? = null
|
||||
|
||||
var binding: ActivityPluginBinding? = null
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user