Bläddra i källkod

Merge pull request #174 from juliuscanute/13-embedding-v2

132 embedding v2
flutter-beta
Julian Steenbakker 5 år sedan
committed by GitHub
förälder
incheckning
1e3e198e4a
Ingen känd nyckel hittad för denna signaturen i databasen GPG-nyckel ID: 4AEE18F83AFDEB23
9 ändrade filer med 154 tillägg och 95 borttagningar
  1. +2
    -1
      android/build.gradle
  2. +103
    -10
      android/src/main/kotlin/net/touchcapture/qr/flutterqr/FlutterQrPlugin.kt
  3. +11
    -65
      android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRView.kt
  4. +3
    -3
      android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRViewFactory.kt
  5. +9
    -0
      android/src/main/kotlin/net/touchcapture/qr/flutterqr/Shared.kt
  6. +2
    -1
      example/android/app/build.gradle
  7. +12
    -7
      example/android/app/src/main/AndroidManifest.xml
  8. +1
    -8
      example/android/app/src/main/kotlin/net/touchcapture/qr/flutterqrexample/MainActivity.kt
  9. +11
    -0
      example/android/app/src/main/res/values/styles.xml

+ 2
- 1
android/build.gradle Visa fil

@@ -34,7 +34,8 @@ android {
main.java.srcDirs += 'src/main/kotlin' main.java.srcDirs += 'src/main/kotlin'
} }
defaultConfig { defaultConfig {
minSdkVersion 19
// minSdkVersion is determined by Native View.
minSdkVersion 20
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
lintOptions { lintOptions {


+ 103
- 10
android/src/main/kotlin/net/touchcapture/qr/flutterqr/FlutterQrPlugin.kt Visa fil

@@ -1,25 +1,118 @@
package net.touchcapture.qr.flutterqr package net.touchcapture.qr.flutterqr


import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
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
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel.MethodCallHandler import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.platform.PlatformViewRegistry


class FlutterQrPlugin : MethodCallHandler {

class FlutterQrPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {

var cameraPermissionContinuation: Runnable? = null
var requestingPermission = false

/** Plugin registration embedding v1 */
companion object { companion object {
@JvmStatic @JvmStatic
fun registerWith(registrar: Registrar) {
registrar
.platformViewRegistry()
.registerViewFactory(
"net.touchcapture.qr.flutterqr/qrview", QRViewFactory(registrar))
fun registerWith(registrar: PluginRegistry.Registrar) {
FlutterQrPlugin().onAttachedToV1(registrar)
} }
} }


private fun onAttachedToV1(registrar: PluginRegistry.Registrar) {
Shared.activity = registrar.activity()
registrar.addRequestPermissionsResultListener(CameraRequestPermissionsListener())
checkAndRequestPermission(null)
onAttachedToEngines(registrar.platformViewRegistry(), registrar.messenger())
}

/** Plugin registration embedding v2 */
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
onAttachedToEngines(flutterPluginBinding.platformViewRegistry, flutterPluginBinding.binaryMessenger)
}

override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
}

/** Plugin start for both embedding v1 & v2 */
private fun onAttachedToEngines(platformViewRegistry: PlatformViewRegistry, messenger: BinaryMessenger) {
platformViewRegistry
.registerViewFactory(
"net.touchcapture.qr.flutterqr/qrview", QRViewFactory(messenger))
}

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

override fun onAttachedToActivity(activityPluginBinding: ActivityPluginBinding) {
Shared.activity = activityPluginBinding.activity
activityPluginBinding.addRequestPermissionsResultListener(CameraRequestPermissionsListener())
checkAndRequestPermission(null)
}

override fun onDetachedFromActivityForConfigChanges() {
Shared.activity = null
}

override fun onReattachedToActivityForConfigChanges(activityPluginBinding: ActivityPluginBinding) {
Shared.activity = activityPluginBinding.activity
}

override fun onDetachedFromActivity() {
Shared.activity = null
}

private inner class CameraRequestPermissionsListener : PluginRegistry.RequestPermissionsResultListener {
override fun onRequestPermissionsResult(id: Int, permissions: Array<String>, grantResults: IntArray): Boolean {
if (id == QRView.CAMERA_REQUEST_ID && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
cameraPermissionContinuation?.run()
return true
}
return false
}
}

private fun hasCameraPermission(): Boolean {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
Shared.activity?.checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
}

private fun checkAndRequestPermission(result: Result?) {
if (cameraPermissionContinuation != null) {
result?.error("cameraPermission", "Camera permission request ongoing", null)
}

cameraPermissionContinuation = Runnable {
cameraPermissionContinuation = null
if (!hasCameraPermission()) {
result?.error(
"cameraPermission", "MediaRecorderCamera permission not granted", null)
return@Runnable
}
}

requestingPermission = false
if (hasCameraPermission()) {
cameraPermissionContinuation?.run()
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestingPermission = true
Shared.activity?.requestPermissions(
arrayOf(Manifest.permission.CAMERA),
QRView.CAMERA_REQUEST_ID)
}
} }
} }
} }

+ 11
- 65
android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRView.kt Visa fil

@@ -1,12 +1,9 @@
package net.touchcapture.qr.flutterqr package net.touchcapture.qr.flutterqr


import android.Manifest
import android.app.Activity import android.app.Activity
import android.app.Application import android.app.Application
import android.content.Context import android.content.Context
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import com.google.zxing.ResultPoint import com.google.zxing.ResultPoint
@@ -14,39 +11,34 @@ import android.hardware.Camera.CameraInfo
import com.journeyapps.barcodescanner.BarcodeCallback import com.journeyapps.barcodescanner.BarcodeCallback
import com.journeyapps.barcodescanner.BarcodeResult import com.journeyapps.barcodescanner.BarcodeResult
import com.journeyapps.barcodescanner.BarcodeView import com.journeyapps.barcodescanner.BarcodeView
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.platform.PlatformView import io.flutter.plugin.platform.PlatformView

class QRView(private val registrar: PluginRegistry.Registrar, id: Int) :
PlatformView,MethodChannel.MethodCallHandler {
class QRView(messenger: BinaryMessenger, id: Int, private val context: Context) :
PlatformView, MethodChannel.MethodCallHandler {


companion object { companion object {
const val CAMERA_REQUEST_ID = 513469796 const val CAMERA_REQUEST_ID = 513469796
} }


var barcodeView: BarcodeView? = null var barcodeView: BarcodeView? = null
private val activity = registrar.activity()
var cameraPermissionContinuation: Runnable? = null
var requestingPermission = false

private var isTorchOn: Boolean = false private var isTorchOn: Boolean = false
val channel: MethodChannel val channel: MethodChannel


init { init {
registrar.addRequestPermissionsResultListener(CameraRequestPermissionsListener())
channel = MethodChannel(registrar.messenger(), "net.touchcapture.qr.flutterqr/qrview_$id")
channel = MethodChannel(messenger, "net.touchcapture.qr.flutterqr/qrview_$id")
channel.setMethodCallHandler(this) channel.setMethodCallHandler(this)
checkAndRequestPermission(null)
registrar.activity().application.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
Shared.activity?.application?.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
override fun onActivityPaused(p0: Activity) { override fun onActivityPaused(p0: Activity) {
if (p0 == registrar.activity()) {
if (p0 == Shared.activity) {
barcodeView?.pause() barcodeView?.pause()
} }
} }


override fun onActivityResumed(p0: Activity) { override fun onActivityResumed(p0: Activity) {
if (p0 == registrar.activity()) {
if (p0 == Shared.activity) {
barcodeView?.resume() barcodeView?.resume()
} }
} }
@@ -102,7 +94,7 @@ class QRView(private val registrar: PluginRegistry.Registrar, id: Int) :
} }


private fun hasFlash(): Boolean { private fun hasFlash(): Boolean {
return registrar.activeContext().packageManager
return context.packageManager
.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH) .hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)
} }


@@ -120,7 +112,7 @@ class QRView(private val registrar: PluginRegistry.Registrar, id: Int) :
} }


private fun createBarCodeView(): BarcodeView? { private fun createBarCodeView(): BarcodeView? {
val barcode = BarcodeView(registrar.activity())
val barcode = BarcodeView(Shared.activity)
barcode.decodeContinuous( barcode.decodeContinuous(
object : BarcodeCallback { object : BarcodeCallback {
override fun barcodeResult(result: BarcodeResult) { override fun barcodeResult(result: BarcodeResult) {
@@ -138,27 +130,8 @@ class QRView(private val registrar: PluginRegistry.Registrar, id: Int) :
barcodeView = null barcodeView = null
} }


private inner class CameraRequestPermissionsListener : PluginRegistry.RequestPermissionsResultListener {
override fun onRequestPermissionsResult(id: Int, permissions: Array<String>, grantResults: IntArray): Boolean {
if (id == CAMERA_REQUEST_ID && grantResults[0] == PERMISSION_GRANTED) {
cameraPermissionContinuation?.run()
return true
}
return false
}
}

private fun hasCameraPermission(): Boolean {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
activity.checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
}


override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when(call?.method){
"checkAndRequestPermission" -> {
checkAndRequestPermission(result)
}
when(call.method){
"flipCamera" -> { "flipCamera" -> {
flipCamera() flipCamera()
} }
@@ -174,33 +147,6 @@ class QRView(private val registrar: PluginRegistry.Registrar, id: Int) :
} }
} }


private fun checkAndRequestPermission(result: MethodChannel.Result?) {
if (cameraPermissionContinuation != null) {
result?.error("cameraPermission", "Camera permission request ongoing", null);
}

cameraPermissionContinuation = Runnable {
cameraPermissionContinuation = null
if (!hasCameraPermission()) {
result?.error(
"cameraPermission", "MediaRecorderCamera permission not granted", null)
return@Runnable
}
}


requestingPermission = false
if (hasCameraPermission()) {
cameraPermissionContinuation?.run()
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestingPermission = true
registrar
.activity()
.requestPermissions(
arrayOf(Manifest.permission.CAMERA),
CAMERA_REQUEST_ID)
}
}
}


} }

+ 3
- 3
android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRViewFactory.kt Visa fil

@@ -1,17 +1,17 @@
package net.touchcapture.qr.flutterqr package net.touchcapture.qr.flutterqr


import android.content.Context import android.content.Context
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.StandardMessageCodec import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory import io.flutter.plugin.platform.PlatformViewFactory




class QRViewFactory(private val registrar: PluginRegistry.Registrar) :
class QRViewFactory(private val messenger: BinaryMessenger) :
PlatformViewFactory(StandardMessageCodec.INSTANCE) { PlatformViewFactory(StandardMessageCodec.INSTANCE) {


override fun create(context: Context, id: Int, obj: Any?): PlatformView { override fun create(context: Context, id: Int, obj: Any?): PlatformView {
return QRView(registrar,id)
return QRView(messenger, id, context)
} }


} }

+ 9
- 0
android/src/main/kotlin/net/touchcapture/qr/flutterqr/Shared.kt Visa fil

@@ -0,0 +1,9 @@
package net.touchcapture.qr.flutterqr

import android.app.Activity
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding


object Shared {
var activity: Activity? = null
}

+ 2
- 1
example/android/app/build.gradle Visa fil

@@ -38,7 +38,8 @@ android {


defaultConfig { defaultConfig {
applicationId "net.touchcapture.qr.flutterqrexample" applicationId "net.touchcapture.qr.flutterqrexample"
minSdkVersion 19
// minSdkVersion is determined by Native View.
minSdkVersion 20
targetSdkVersion 30 targetSdkVersion 30
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName


+ 12
- 7
example/android/app/src/main/AndroidManifest.xml Visa fil

@@ -13,7 +13,6 @@
additional functionality it is fine to subclass or reimplement additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. --> FlutterApplication and put your custom class here. -->
<application <application
android:name="io.flutter.app.FlutterApplication"
android:label="flutter_qr_example" android:label="flutter_qr_example"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">
<activity <activity
@@ -23,13 +22,19 @@
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<!-- Specify that the launch screen should continue being displayed -->
<!-- until Flutter renders its first frame. -->
<meta-data <meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background" />
<!-- Theme to apply as soon as Flutter begins rendering frames -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>


+ 1
- 8
example/android/app/src/main/kotlin/net/touchcapture/qr/flutterqrexample/MainActivity.kt Visa fil

@@ -1,13 +1,6 @@
package net.touchcapture.qr.flutterqrexample package net.touchcapture.qr.flutterqrexample


import android.os.Bundle

import io.flutter.app.FlutterActivity
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.embedding.android.FlutterActivity


class MainActivity: FlutterActivity() { class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
}
} }

+ 11
- 0
example/android/app/src/main/res/values/styles.xml Visa fil

@@ -1,8 +1,19 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- Theme applied to the Android Window while the process is starting -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar"> <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when <!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame --> Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item> <item name="android:windowBackground">@drawable/launch_background</item>
</style> </style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.

This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">@drawable/launch_background</item>
</style>

</resources> </resources>

Laddar…
Avbryt
Spara