Просмотр исходного кода

Merge remote-tracking branch 'origin/master' into codeformat

flutter-beta
Timo von Holtz 5 лет назад
Родитель
Сommit
1125aef18c
32 измененных файлов: 471 добавлений и 272 удалений
  1. +24
    -0
      .github/ISSUE_TEMPLATE/bug_report.md
  2. +17
    -0
      .github/ISSUE_TEMPLATE/feature_request.md
  3. Двоичные данные
      .resources/android_back_camera_flash.gif
  4. Двоичные данные
      .resources/android_front_camera_scan.gif
  5. Двоичные данные
      .resources/ios_back_camera_flash.gif
  6. Двоичные данные
      .resources/ios_front_camera_scan.gif
  7. +11
    -0
      CHANGELOG.md
  8. +17
    -6
      README.md
  9. +2
    -1
      analysis_options.yaml
  10. +6
    -5
      android/build.gradle
  11. +103
    -10
      android/src/main/kotlin/net/touchcapture/qr/flutterqr/FlutterQrPlugin.kt
  12. +18
    -72
      android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRView.kt
  13. +3
    -3
      android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRViewFactory.kt
  14. +9
    -0
      android/src/main/kotlin/net/touchcapture/qr/flutterqr/Shared.kt
  15. +133
    -35
      example/README.md
  16. +5
    -6
      example/android/app/build.gradle
  17. +12
    -7
      example/android/app/src/main/AndroidManifest.xml
  18. +1
    -8
      example/android/app/src/main/kotlin/net/touchcapture/qr/flutterqrexample/MainActivity.kt
  19. +11
    -0
      example/android/app/src/main/res/values/styles.xml
  20. +2
    -2
      example/android/build.gradle
  21. +1
    -0
      example/android/gradle.properties
  22. +2
    -2
      example/android/gradle/wrapper/gradle-wrapper.properties
  23. +17
    -48
      example/ios/Podfile
  24. +17
    -29
      example/ios/Runner.xcodeproj/project.pbxproj
  25. +0
    -8
      example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
  26. +24
    -14
      example/lib/main.dart
  27. +1
    -1
      example/pubspec.yaml
  28. +13
    -6
      ios/Classes/QRView.swift
  29. +1
    -1
      ios/Classes/QRViewFactory.swift
  30. +12
    -5
      lib/src/qr_code_scanner.dart
  31. +7
    -1
      lib/src/qr_scanner_overlay_shape.dart
  32. +2
    -2
      pubspec.yaml

+ 24
- 0
.github/ISSUE_TEMPLATE/bug_report.md Просмотреть файл

@@ -0,0 +1,24 @@
---
name: Bug report
about: Create a report to help us improve
title: "[BUG] "
labels: bug
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**Flutter information**
Always provide the output of `flutter doctor -v` as it is needed in order to know on which Flutter versions the bug exists in.

**Device (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Additional context**
Add any other context about the problem here.

+ 17
- 0
.github/ISSUE_TEMPLATE/feature_request.md Просмотреть файл

@@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
title: "[FEATURE] "
labels: enhancement
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Additional context**
Add any other context or screenshots about the feature request here.

Двоичные данные
.resources/android_back_camera_flash.gif Просмотреть файл

До После
Ширина: 320  |  Высота: 646  |  Размер: 12 MiB

Двоичные данные
.resources/android_front_camera_scan.gif Просмотреть файл

До После
Ширина: 320  |  Высота: 646  |  Размер: 4.7 MiB

Двоичные данные
.resources/ios_back_camera_flash.gif Просмотреть файл

До После
Ширина: 320  |  Высота: 566  |  Размер: 6.6 MiB

Двоичные данные
.resources/ios_front_camera_scan.gif Просмотреть файл

До После
Ширина: 320  |  Высота: 535  |  Размер: 6.9 MiB

+ 11
- 0
CHANGELOG.md Просмотреть файл

@@ -1,3 +1,14 @@
## 0.1.0
* Changed Android minSDKversion from 24 to 21 (#170)
* Fix preview size after iPad rotation (#125)
* Implemented Android Embedding V2 (#132)
* Added cutout bottom offset (#115)
* Fix Android ActivityLifecycleCallbacks (#166)
* Fix some other small bugs

## 0.0.14
* Fix disposing camera on iOS 14 (#113)

## 0.0.13
* Fix misalignment when QRView doesn't start from the top left (#45)
* Fix crash on iOS when scanning returns nil (#69, #72)


+ 17
- 6
README.md Просмотреть файл

@@ -63,9 +63,20 @@ class _QRViewExampleState extends State<QRViewExample> {
children: <Widget>[
Expanded(
flex: 5,
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
// To ensure the Scanner view is properly sizes after rotation
// we need to listen for Flutter SizeChanged notification and update controller
child: NotificationListener<SizeChangedLayoutNotification>(
onNotification: (notification) {
Future.microtask(() => controller?.updateDimensions(qrKey));
return false;
},
child: SizeChangedLayoutNotifier(
key: const Key('qr-size-notifier'),
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
),
),
),
),
Expanded(
@@ -120,16 +131,16 @@ controller.toggleFlash();
## Resume/Pause
Pause camera stream and scanner.
```dart
controller.pause();
controller.pauseCamera();
```
Resume camera stream and scanner.
```dart
controller.resume();
controller.resumeCamera();
```


# SDK
Requires at least SDK 24 (Android 7.0).
Requires at least SDK 21 (Android 5.0).

# TODOs
* iOS Native embedding is written to match what is supported in the framework as of the date of publication of this package. It needs to be improved as the framework support improves.


+ 2
- 1
analysis_options.yaml Просмотреть файл

@@ -1,4 +1,5 @@
include: package:pedantic/analysis_options.1.9.0.yaml
include: package:pedantic/analysis_options.yaml

linter:
rules:
- always_put_required_named_parameters_first


+ 6
- 5
android/build.gradle Просмотреть файл

@@ -2,14 +2,14 @@ group 'net.touchcapture.qr.flutterqr'
version '1.0-SNAPSHOT'

buildscript {
ext.kotlin_version = '1.3.21'
ext.kotlin_version = '1.4.21'
repositories {
google()
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:3.3.2'
classpath 'com.android.tools.build:gradle:4.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
@@ -27,14 +27,15 @@ apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

android {
compileSdkVersion 28
compileSdkVersion 30


sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
minSdkVersion 19
// minSdkVersion is determined by Native View.
minSdkVersion 20
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
lintOptions {
@@ -48,6 +49,6 @@ android {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation('com.journeyapps:zxing-android-embedded:4.1.0') { transitive = false }
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.zxing:core:3.3.0'
}

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

+ 18
- 72
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,56 +11,51 @@ 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 {
override fun onActivityPaused(p0: Activity?) {
if (p0 == registrar.activity()) {
Shared.activity?.application?.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
override fun onActivityPaused(p0: Activity) {
if (p0 == Shared.activity) {
barcodeView?.pause()
}
}

override fun onActivityResumed(p0: Activity?) {
if (p0 == registrar.activity()) {
override fun onActivityResumed(p0: Activity) {
if (p0 == Shared.activity) {
barcodeView?.resume()
}
}

override fun onActivityStarted(p0: Activity?) {
override fun onActivityStarted(p0: Activity) {
}

override fun onActivityDestroyed(p0: Activity?) {
override fun onActivityDestroyed(p0: Activity) {
}

override fun onActivitySaveInstanceState(p0: Activity?, p1: Bundle?) {
override fun onActivitySaveInstanceState(p0: Activity, p1: Bundle) {
}

override fun onActivityStopped(p0: Activity?) {
override fun onActivityStopped(p0: Activity) {
}

override fun onActivityCreated(p0: Activity?, p1: Bundle?) {
override fun onActivityCreated(p0: Activity, p1: Bundle?) {
}
})
}
@@ -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) {
@@ -139,27 +131,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()
}
@@ -175,33 +148,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
}

+ 133
- 35
example/README.md Просмотреть файл

@@ -22,11 +22,15 @@ Demonstrates how to use the qr_code_scanner plugin.
## Example:
```dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';

void main() => runApp(MaterialApp(home: QRViewExample()));

const flashOn = 'FLASH ON';
const flashOff = 'FLASH OFF';
const frontCamera = 'FRONT CAMERA';
const backCamera = 'BACK CAMERA';

class QRViewExample extends StatefulWidget {
const QRViewExample({
Key key,
@@ -37,60 +41,154 @@ class QRViewExample extends StatefulWidget {
}

class _QRViewExampleState extends State<QRViewExample> {
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
var qrText = "";
var qrText = '';
var flashState = flashOn;
var cameraState = frontCamera;
QRViewController controller;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');

@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(flex: 4, child: _buildQrView(context)),
Expanded(
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
),
flex: 4,
),
Expanded(
child: Column(children:
<Widget>[
Text("This is the result of scan: $qrText"),
RaisedButton(
onPressed: (){
if(controller != null){
controller.flipCamera();
}
},
child: Text(
'Flip',
style: TextStyle(fontSize: 20)
flex: 1,
child: FittedBox(
fit: BoxFit.contain,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text('This is the result of scan: $qrText'),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.all(8),
child: RaisedButton(
onPressed: () {
if (controller != null) {
controller.toggleFlash();
if (_isFlashOn(flashState)) {
setState(() {
flashState = flashOff;
});
} else {
setState(() {
flashState = flashOn;
});
}
}
},
child:
Text(flashState, style: TextStyle(fontSize: 20)),
),
),
Container(
margin: EdgeInsets.all(8),
child: RaisedButton(
onPressed: () {
if (controller != null) {
controller.flipCamera();
if (_isBackCamera(cameraState)) {
setState(() {
cameraState = frontCamera;
});
} else {
setState(() {
cameraState = backCamera;
});
}
}
},
child:
Text(cameraState, style: TextStyle(fontSize: 20)),
),
)
],
),
)
],
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.all(8),
child: RaisedButton(
onPressed: () {
controller?.pauseCamera();
},
child: Text('pause', style: TextStyle(fontSize: 20)),
),
),
Container(
margin: EdgeInsets.all(8),
child: RaisedButton(
onPressed: () {
controller?.resumeCamera();
},
child: Text('resume', style: TextStyle(fontSize: 20)),
),
)
],
),
],
),
),
flex: 1,
)
],
),
);
}

bool _isFlashOn(String current) {
return flashOn == current;
}

bool _isBackCamera(String current) {
return backCamera == current;
}

Widget _buildQrView(BuildContext context) {
// To ensure the Scanner view is properly sizes after rotation
// we need to listen for Flutter SizeChanged notification and update controller
return NotificationListener<SizeChangedLayoutNotification>(
onNotification: (notification) {
Future.microtask(() => controller?.updateDimensions(qrKey));
return false;
},
child: SizeChangedLayoutNotifier(
key: const Key('qr-size-notifier'),
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.red,
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: 300,
),
)));
}

void _onQRViewCreated(QRViewController controller) {
final channel = controller.channel;
controller.init(qrKey);
this.controller = controller;
channel.setMethodCallHandler((MethodCall call) async {
switch (call.method) {
case "onRecognizeQR":
dynamic arguments = call.arguments;
setState(() {
qrText = arguments.toString();
});
}
controller.scannedDataStream.listen((scanData) {
setState(() {
qrText = scanData;
});
});
}

@override
void dispose() {
controller.dispose();
super.dispose();
}
}

```




+ 5
- 6
example/android/app/build.gradle Просмотреть файл

@@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
compileSdkVersion 28
compileSdkVersion 30

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
@@ -37,10 +37,10 @@ android {
}

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "net.touchcapture.qr.flutterqrexample"
minSdkVersion 19
targetSdkVersion 27
// minSdkVersion is determined by Native View.
minSdkVersion 20
targetSdkVersion 30
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -48,7 +48,6 @@ android {

buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
@@ -61,7 +60,7 @@ flutter {

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.12'
testImplementation 'junit:junit:4.13.1'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

+ 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>

+ 2
- 2
example/android/build.gradle Просмотреть файл

@@ -1,12 +1,12 @@
buildscript {
ext.kotlin_version = '1.3.50'
ext.kotlin_version = '1.4.21'
repositories {
google()
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:3.6.3'
classpath 'com.android.tools.build:gradle:4.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}


+ 1
- 0
example/android/gradle.properties Просмотреть файл

@@ -1,3 +1,4 @@
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
android.enableR8=true

+ 2
- 2
example/android/gradle/wrapper/gradle-wrapper.properties Просмотреть файл

@@ -1,6 +1,6 @@
#Thu May 14 12:19:05 CEST 2020
#Thu Dec 10 21:49:57 CET 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip

+ 17
- 48
example/ios/Podfile Просмотреть файл

@@ -4,69 +4,38 @@
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'


project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}

def parse_KV_file(file, separator='=')
file_abs_path = File.expand_path(file)
if !File.exists? file_abs_path
return [];
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end

File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
pods_ary = []
skip_line_start_symbols = ["#", "/"]
File.foreach(file_abs_path) { |line|
next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
plugin = line.split(pattern=separator)
if plugin.length == 2
podname = plugin[0].strip()
path = plugin[1].strip()
podpath = File.expand_path("#{path}", file_abs_path)
pods_ary.push({:name => podname, :path => podpath});
else
puts "Invalid plugin specification: #{line}"
end
}
return pods_ary
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end

target 'Runner' do
use_frameworks!
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

# Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
# referring to absolute paths on developers' machines.
system('rm -rf .symlinks')
system('mkdir -p .symlinks/plugins')
flutter_ios_podfile_setup

# Flutter Pods
generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
if generated_xcode_build_settings.empty?
puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first."
end
generated_xcode_build_settings.map { |p|
if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
symlink = File.join('.symlinks', 'flutter')
File.symlink(File.dirname(p[:path]), symlink)
pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
end
}
target 'Runner' do
use_frameworks!
use_modular_headers!

# Plugin Pods
plugin_pods = parse_KV_file('../.flutter-plugins')
plugin_pods.map { |p|
symlink = File.join('.symlinks', 'plugins', p[:name])
File.symlink(p[:path], symlink)
pod p[:name], :path => File.join(symlink, 'ios')
}
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end

post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
flutter_additional_ios_build_settings(target)
end
end

+ 17
- 29
example/ios/Runner.xcodeproj/project.pbxproj Просмотреть файл

@@ -9,12 +9,8 @@
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
72CA4F8FC83C02C1B0C5292A /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D115C5DD3945F9758AB33CE2 /* Pods_Runner.framework */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
@@ -27,8 +23,6 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@@ -39,18 +33,19 @@
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
4465DBB6FCA236431DE34346 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
87B204D37F3832F9BE4979B0 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9994328F3BE8CB44F875A29E /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
D115C5DD3945F9758AB33CE2 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */

@@ -59,8 +54,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
72CA4F8FC83C02C1B0C5292A /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -71,6 +64,9 @@
0972BCF1757D16A75C3EC240 /* Pods */ = {
isa = PBXGroup;
children = (
4465DBB6FCA236431DE34346 /* Pods-Runner.debug.xcconfig */,
9994328F3BE8CB44F875A29E /* Pods-Runner.release.xcconfig */,
87B204D37F3832F9BE4979B0 /* Pods-Runner.profile.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
@@ -78,9 +74,7 @@
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEBA1CF902C7004384FC /* Flutter.framework */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
@@ -174,6 +168,7 @@
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
DevelopmentTeam = 5LSCTACHT8;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
@@ -224,7 +219,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
3C208BB7148E708611B40C3B /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
@@ -253,17 +248,13 @@
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../Flutter/Flutter.framework",
"${BUILT_PRODUCTS_DIR}/MTBBarcodeScanner/MTBBarcodeScanner.framework",
"${BUILT_PRODUCTS_DIR}/qr_code_scanner/qr_code_scanner.framework",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
);
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MTBBarcodeScanner.framework",
@@ -271,7 +262,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
@@ -324,7 +315,6 @@
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
@@ -382,7 +372,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = 5LSCTACHT8;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -394,7 +384,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = net.touch.capture;
PRODUCT_BUNDLE_IDENTIFIER = dev.steenbakker.capture;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 4.0;
@@ -404,7 +394,6 @@
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
@@ -462,7 +451,6 @@
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
@@ -522,7 +510,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = 5LSCTACHT8;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -534,7 +522,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = net.touch.capture;
PRODUCT_BUNDLE_IDENTIFIER = dev.steenbakker.capture;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -553,7 +541,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = 5LSCTACHT8;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -565,7 +553,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = net.touch.capture;
PRODUCT_BUNDLE_IDENTIFIER = dev.steenbakker.capture;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";


+ 0
- 8
example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings Просмотреть файл

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildSystemType</key>
<string>Original</string>
</dict>
</plist>

+ 24
- 14
example/lib/main.dart Просмотреть файл

@@ -37,20 +37,7 @@ class _QRViewExampleState extends State<QRViewExample> {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(
flex: 4,
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.red,
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: 300,
),
),
),
Expanded(flex: 4, child: _buildQrView(context)),
Expanded(
flex: 1,
child: FittedBox(
@@ -148,6 +135,29 @@ class _QRViewExampleState extends State<QRViewExample> {
return backCamera == current;
}

Widget _buildQrView(BuildContext context) {
// To ensure the Scanner view is properly sizes after rotation
// we need to listen for Flutter SizeChanged notification and update controller
return NotificationListener<SizeChangedLayoutNotification>(
onNotification: (notification) {
Future.microtask(() => controller?.updateDimensions(qrKey));
return false;
},
child: SizeChangedLayoutNotifier(
key: const Key('qr-size-notifier'),
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.red,
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: 300,
),
)));
}

void _onQRViewCreated(QRViewController controller) {
this.controller = controller;
controller.scannedDataStream.listen((scanData) {


+ 1
- 1
example/pubspec.yaml Просмотреть файл

@@ -3,7 +3,7 @@ description: Demonstrates how to use the flutter_qr plugin.
publish_to: 'none'

environment:
sdk: ">=2.0.0-dev.68.0 <3.0.0"
sdk: ">=2.3.0 <3.0.0"

dependencies:
flutter:


+ 13
- 6
ios/Classes/QRView.swift Просмотреть файл

@@ -23,7 +23,7 @@ public class QRView:NSObject,FlutterPlatformView {
func isCameraAvailable(success: Bool) -> Void {
if success {
do {
try scanner?.startScanning(resultBlock: { codes in
try scanner?.startScanning(resultBlock: { [weak self] codes in
if let codes = codes {
for code in codes {
var typeString: String;
@@ -56,7 +56,7 @@ public class QRView:NSObject,FlutterPlatformView {

guard let stringValue = code.stringValue else { continue }
let result = ["code": stringValue, "type": typeString]
self.channel.invokeMethod("onRecognizeQR", arguments: result)
self?.channel.invokeMethod("onRecognizeQR", arguments: result)
}
}
})
@@ -73,7 +73,7 @@ public class QRView:NSObject,FlutterPlatformView {
[weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
switch(call.method){
case "setDimensions":
var arguments = call.arguments as! Dictionary<String, Double>
let arguments = call.arguments as! Dictionary<String, Double>
self?.setDimensions(width: arguments["width"] ?? 0,height: arguments["height"] ?? 0)
case "flipCamera":
self?.flipCamera()
@@ -92,9 +92,16 @@ public class QRView:NSObject,FlutterPlatformView {
}
func setDimensions(width: Double, height: Double) -> Void {
previewView.frame = CGRect(x: 0, y: 0, width: width, height: height)
scanner = MTBBarcodeScanner(previewView: previewView)
MTBBarcodeScanner.requestCameraPermission(success: isCameraAvailable)
previewView.frame = CGRect(x: 0, y: 0, width: width, height: height)

if let sc: MTBBarcodeScanner = scanner {
if let previewLayer = sc.previewLayer {
previewLayer.frame = previewView.bounds;
}
} else {
scanner = MTBBarcodeScanner(previewView: previewView)
MTBBarcodeScanner.requestCameraPermission(success: isCameraAvailable)
}
}
func flipCamera(){


+ 1
- 1
ios/Classes/QRViewFactory.swift Просмотреть файл

@@ -17,7 +17,7 @@ public class QRViewFactory: NSObject, FlutterPlatformViewFactory {
}
public func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
var dictionary = args as! Dictionary<String, Double>
let dictionary = args as! Dictionary<String, Double>
return QRView(withFrame: CGRect(x: 0, y: 0, width: dictionary["width"] ?? 0, height: dictionary["height"] ?? 0), withRegistrar: registrar!,withId: viewId)
}


+ 12
- 5
lib/src/qr_code_scanner.dart Просмотреть файл

@@ -91,6 +91,7 @@ class QRView extends StatefulWidget {
@required Key key,
@required this.onQRViewCreated,
this.overlay,
this.overlayMargin = EdgeInsets.zero,
}) : assert(key != null),
assert(onQRViewCreated != null),
super(key: key);
@@ -98,6 +99,7 @@ class QRView extends StatefulWidget {
final QRViewCreatedCallback onQRViewCreated;

final ShapeBorder overlay;
final EdgeInsetsGeometry overlayMargin;

@override
State<StatefulWidget> createState() => _QRViewState();
@@ -111,6 +113,7 @@ class _QRViewState extends State<QRView> {
_getPlatformQrView(),
if (widget.overlay != null)
Container(
padding: widget.overlayMargin,
decoration: ShapeDecoration(
shape: widget.overlay,
),
@@ -177,11 +180,7 @@ class _CreationParams {
class QRViewController {
QRViewController._(int id, GlobalKey qrKey)
: _channel = MethodChannel('net.touchcapture.qr.flutterqr/qrview_$id') {
if (defaultTargetPlatform == TargetPlatform.iOS) {
final RenderBox renderBox = qrKey.currentContext.findRenderObject();
_channel.invokeMethod('setDimensions',
{'width': renderBox.size.width, 'height': renderBox.size.height});
}
updateDimensions(qrKey);
_channel.setMethodCallHandler(
(call) async {
switch (call.method) {
@@ -231,4 +230,12 @@ class QRViewController {
void dispose() {
_scanUpdateController.close();
}

void updateDimensions(GlobalKey key) {
if (defaultTargetPlatform == TargetPlatform.iOS) {
final RenderBox renderBox = key.currentContext.findRenderObject();
_channel.invokeMethod('setDimensions',
{'width': renderBox.size.width, 'height': renderBox.size.height});
}
}
}

+ 7
- 1
lib/src/qr_scanner_overlay_shape.dart Просмотреть файл

@@ -10,6 +10,7 @@ class QrScannerOverlayShape extends ShapeBorder {
this.borderRadius = 0,
this.borderLength = 40,
this.cutOutSize = 250,
this.cutOutBottomOffset = 0,
}) : assert(
cutOutSize != null ??
cutOutSize != null ??
@@ -22,6 +23,7 @@ class QrScannerOverlayShape extends ShapeBorder {
final double borderRadius;
final double borderLength;
final double cutOutSize;
final double cutOutBottomOffset;

@override
EdgeInsetsGeometry get dimensions => const EdgeInsets.all(10);
@@ -86,7 +88,11 @@ class QrScannerOverlayShape extends ShapeBorder {

final cutOutRect = Rect.fromLTWH(
rect.left + width / 2 - _cutOutSize / 2 + borderOffset,
rect.top + height / 2 - _cutOutSize / 2 + borderOffset,
-cutOutBottomOffset +
rect.top +
height / 2 -
_cutOutSize / 2 +
borderOffset,
_cutOutSize - borderOffset * 2,
_cutOutSize - borderOffset * 2,
);


+ 2
- 2
pubspec.yaml Просмотреть файл

@@ -1,6 +1,6 @@
name: qr_code_scanner
description: QR code scanner that can be embedded inside flutter. It uses zxing in Android and MTBBarcode scanner in iOS.
version: 0.0.13
version: 0.1.0
author: Julius Canute <juliuscanute at touchcapture.net>
homepage: https://juliuscanute.com
repository: https://github.com/juliuscanute/qr_code_scanner
@@ -14,7 +14,7 @@ dependencies:
sdk: flutter

dev_dependencies:
pedantic: ^1.9.0
pedantic: ^1.9.2

flutter:
plugin:


Загрузка…
Отмена
Сохранить