ソースを参照

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

132 embedding v2
flutter-beta
Julian Steenbakker 5年前
committed by GitHub
コミット
1e3e198e4a
この署名に対応する既知のキーがデータベースに存在しません GPGキーID: 4AEE18F83AFDEB23
9個のファイルの変更154行の追加95行の削除
  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 ファイルの表示

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


+ 103
- 10
android/src/main/kotlin/net/touchcapture/qr/flutterqr/FlutterQrPlugin.kt ファイルの表示

@@ -1,25 +1,118 @@
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.MethodChannel.MethodCallHandler
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 {
@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) {
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 ファイルの表示

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

import android.Manifest
import android.app.Activity
import android.app.Application
import android.content.Context
import android.content.pm.PackageManager
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.os.Build
import android.os.Bundle
import android.view.View
import com.google.zxing.ResultPoint
@@ -14,39 +11,34 @@ import android.hardware.Camera.CameraInfo
import com.journeyapps.barcodescanner.BarcodeCallback
import com.journeyapps.barcodescanner.BarcodeResult
import com.journeyapps.barcodescanner.BarcodeView
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 registrar: PluginRegistry.Registrar, id: Int) :
PlatformView,MethodChannel.MethodCallHandler {
class QRView(messenger: BinaryMessenger, id: Int, private val context: Context) :
PlatformView, MethodChannel.MethodCallHandler {

companion object {
const val CAMERA_REQUEST_ID = 513469796
}

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

private var isTorchOn: Boolean = false
val channel: MethodChannel

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)
checkAndRequestPermission(null)
registrar.activity().application.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
Shared.activity?.application?.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
override fun onActivityPaused(p0: Activity) {
if (p0 == registrar.activity()) {
if (p0 == Shared.activity) {
barcodeView?.pause()
}
}

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

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

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

private fun createBarCodeView(): BarcodeView? {
val barcode = BarcodeView(registrar.activity())
val barcode = BarcodeView(Shared.activity)
barcode.decodeContinuous(
object : BarcodeCallback {
override fun barcodeResult(result: BarcodeResult) {
@@ -138,27 +130,8 @@ class QRView(private val registrar: PluginRegistry.Registrar, id: Int) :
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) {
when(call?.method){
"checkAndRequestPermission" -> {
checkAndRequestPermission(result)
}
when(call.method){
"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 ファイルの表示

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

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.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory


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

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 ファイルの表示

@@ -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 ファイルの表示

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

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


+ 12
- 7
example/android/app/src/main/AndroidManifest.xml ファイルの表示

@@ -13,7 +13,6 @@
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="flutter_qr_example"
android:icon="@mipmap/ic_launcher">
<activity
@@ -23,13 +22,19 @@
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true"
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
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>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>


+ 1
- 8
example/android/app/src/main/kotlin/net/touchcapture/qr/flutterqrexample/MainActivity.kt ファイルの表示

@@ -1,13 +1,6 @@
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() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
}
}

+ 11
- 0
example/android/app/src/main/res/values/styles.xml ファイルの表示

@@ -1,8 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</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>

読み込み中…
キャンセル
保存