Committed by
GitHub
Merge branch 'master' into master
Showing
26 changed files
with
448 additions
and
112 deletions
.github/CODEOWNERS
0 → 100644
| 1 | +# These owners will be the default owners for everything in | ||
| 2 | +# the repo. Unless a later match takes precedence, | ||
| 3 | +# review when someone opens a pull request. | ||
| 4 | +# For more on how to customize the CODEOWNERS file - https://help.github.com/en/articles/about-code-owners | ||
| 5 | + | ||
| 6 | +* @juliansteenbakker |
| @@ -6,15 +6,33 @@ updates: | @@ -6,15 +6,33 @@ updates: | ||
| 6 | interval: "weekly" | 6 | interval: "weekly" |
| 7 | reviewers: | 7 | reviewers: |
| 8 | - "juliansteenbakker" | 8 | - "juliansteenbakker" |
| 9 | + commit-message: | ||
| 10 | + prefix: "chore" | ||
| 11 | + include: "scope" | ||
| 9 | - package-ecosystem: gradle | 12 | - package-ecosystem: gradle |
| 10 | directory: "/android" | 13 | directory: "/android" |
| 11 | schedule: | 14 | schedule: |
| 12 | interval: "weekly" | 15 | interval: "weekly" |
| 13 | reviewers: | 16 | reviewers: |
| 14 | - "juliansteenbakker" | 17 | - "juliansteenbakker" |
| 18 | + commit-message: | ||
| 19 | + prefix: "chore" | ||
| 20 | + include: "scope" | ||
| 15 | - package-ecosystem: gradle | 21 | - package-ecosystem: gradle |
| 16 | directory: "/example/android" | 22 | directory: "/example/android" |
| 17 | schedule: | 23 | schedule: |
| 18 | interval: "weekly" | 24 | interval: "weekly" |
| 19 | reviewers: | 25 | reviewers: |
| 20 | - "juliansteenbakker" | 26 | - "juliansteenbakker" |
| 27 | + commit-message: | ||
| 28 | + prefix: "chore" | ||
| 29 | + include: "scope" | ||
| 30 | + - package-ecosystem: "pub" | ||
| 31 | + directory: "/" | ||
| 32 | + schedule: | ||
| 33 | + interval: "weekly" | ||
| 34 | + commit-message: | ||
| 35 | + prefix: "chore" | ||
| 36 | + include: "scope" | ||
| 37 | + reviewers: | ||
| 38 | + - "juliansteenbakker" |
.github/workflows/auto-assign-pr.yml
0 → 100644
| 1 | +# .github/workflows/auto-author-assign.yml | ||
| 2 | +name: 'Auto Author Assign' | ||
| 3 | + | ||
| 4 | +on: | ||
| 5 | + pull_request_target: | ||
| 6 | + types: [opened, reopened] | ||
| 7 | + | ||
| 8 | +permissions: | ||
| 9 | + pull-requests: write | ||
| 10 | + | ||
| 11 | +jobs: | ||
| 12 | + assign-author: | ||
| 13 | + runs-on: ubuntu-latest | ||
| 14 | + steps: | ||
| 15 | + - uses: toshimaru/auto-author-assign@v1.6.1 |
| 1 | name: code analysis & formatting | 1 | name: code analysis & formatting |
| 2 | 2 | ||
| 3 | -on: [push, pull_request] | 3 | +on: |
| 4 | + push: | ||
| 5 | + branches: | ||
| 6 | + - master | ||
| 7 | + pull_request: | ||
| 8 | + types: [ opened, labeled, unlabeled, synchronize ] | ||
| 4 | 9 | ||
| 5 | jobs: | 10 | jobs: |
| 6 | analysis: | 11 | analysis: |
| 7 | runs-on: ubuntu-latest | 12 | runs-on: ubuntu-latest |
| 8 | steps: | 13 | steps: |
| 9 | - - uses: actions/checkout@v3 | ||
| 10 | - - uses: actions/setup-java@v3 | 14 | + - uses: actions/checkout@v3.0.2 |
| 15 | + - uses: actions/setup-java@v3.4.1 | ||
| 11 | with: | 16 | with: |
| 12 | - distribution: 'temurin' | ||
| 13 | - java-version: '11' | ||
| 14 | - - uses: subosito/flutter-action@v2.4.0 | 17 | + java-version: 11 |
| 18 | + distribution: temurin | ||
| 19 | + - uses: subosito/flutter-action@v2.6.1 | ||
| 20 | + with: | ||
| 21 | + cache: true | ||
| 15 | - name: Version | 22 | - name: Version |
| 16 | run: flutter doctor -v | 23 | run: flutter doctor -v |
| 17 | - name: Install dependencies | 24 | - name: Install dependencies |
| @@ -21,11 +28,13 @@ jobs: | @@ -21,11 +28,13 @@ jobs: | ||
| 21 | formatting: | 28 | formatting: |
| 22 | runs-on: ubuntu-latest | 29 | runs-on: ubuntu-latest |
| 23 | steps: | 30 | steps: |
| 24 | - - uses: actions/checkout@v3 | ||
| 25 | - - uses: actions/setup-java@v3 | 31 | + - uses: actions/checkout@v3.0.2 |
| 32 | + - uses: actions/setup-java@v3.4.1 | ||
| 33 | + with: | ||
| 34 | + java-version: 11 | ||
| 35 | + distribution: temurin | ||
| 36 | + - uses: subosito/flutter-action@v2.6.1 | ||
| 26 | with: | 37 | with: |
| 27 | - distribution: 'temurin' | ||
| 28 | - java-version: '11' | ||
| 29 | - - uses: subosito/flutter-action@v2.4.0 | 38 | + cache: true |
| 30 | - name: Format | 39 | - name: Format |
| 31 | run: flutter format -n --set-exit-if-changed . | 40 | run: flutter format -n --set-exit-if-changed . |
.github/workflows/release-please.yml
0 → 100644
.github/workflows/semantic-pr.yml
0 → 100644
| 1 | +name: "Semantic PRs" | ||
| 2 | + | ||
| 3 | +on: | ||
| 4 | + pull_request_target: | ||
| 5 | + types: | ||
| 6 | + - opened | ||
| 7 | + - edited | ||
| 8 | + - synchronize | ||
| 9 | + | ||
| 10 | +jobs: | ||
| 11 | + main: | ||
| 12 | + name: Validate PR title | ||
| 13 | + runs-on: ubuntu-latest | ||
| 14 | + steps: | ||
| 15 | + - uses: amannn/action-semantic-pull-request@v4 | ||
| 16 | + env: | ||
| 17 | + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 1 | +## 3.0.0 | ||
| 2 | +Breaking changes: | ||
| 3 | +* [Android] SDK updated to SDK 33. | ||
| 4 | + | ||
| 5 | +Other changes: | ||
| 6 | +* [Android] Revert camera2 dependency to stable release | ||
| 7 | +* [iOS] Update barcode scanning library to latest version | ||
| 8 | + | ||
| 1 | ## 2.0.0 | 9 | ## 2.0.0 |
| 2 | Breaking changes: | 10 | Breaking changes: |
| 3 | This version is only compatible with flutter 3.0.0 and later. | 11 | This version is only compatible with flutter 3.0.0 and later. |
| @@ -169,3 +169,41 @@ import 'package:mobile_scanner/mobile_scanner.dart'; | @@ -169,3 +169,41 @@ import 'package:mobile_scanner/mobile_scanner.dart'; | ||
| 169 | })); | 169 | })); |
| 170 | } | 170 | } |
| 171 | ``` | 171 | ``` |
| 172 | + | ||
| 173 | +Example with controller and returning images | ||
| 174 | + | ||
| 175 | +```dart | ||
| 176 | +import 'package:mobile_scanner/mobile_scanner.dart'; | ||
| 177 | + | ||
| 178 | + @override | ||
| 179 | + Widget build(BuildContext context) { | ||
| 180 | + return Scaffold( | ||
| 181 | + appBar: AppBar(title: const Text('Mobile Scanner')), | ||
| 182 | + body: MobileScanner( | ||
| 183 | + controller: MobileScannerController( | ||
| 184 | + facing: CameraFacing.front, | ||
| 185 | + torchEnabled: true, | ||
| 186 | + returnImage: true, | ||
| 187 | + ), | ||
| 188 | + onDetect: (barcode, args) { | ||
| 189 | + if (barcode.rawValue == null) { | ||
| 190 | + debugPrint('Failed to scan Barcode'); | ||
| 191 | + } else { | ||
| 192 | + final String code = barcode.rawValue!; | ||
| 193 | + debugPrint('Barcode found! $code'); | ||
| 194 | + | ||
| 195 | + debugPrint( | ||
| 196 | + 'Image returned! length: ${barcode.image!.lengthInBytes}b'); | ||
| 197 | + showDialog( | ||
| 198 | + context: context, | ||
| 199 | + builder: (context) => Image(image: MemoryImage(barcode.image!)), | ||
| 200 | + ); | ||
| 201 | + Future.delayed(const Duration(seconds: 2), () { | ||
| 202 | + Navigator.pop(context); | ||
| 203 | + }); | ||
| 204 | + } | ||
| 205 | + }, | ||
| 206 | + ), | ||
| 207 | + ); | ||
| 208 | + } | ||
| 209 | +``` |
| @@ -2,14 +2,14 @@ group 'dev.steenbakker.mobile_scanner' | @@ -2,14 +2,14 @@ group 'dev.steenbakker.mobile_scanner' | ||
| 2 | version '1.0-SNAPSHOT' | 2 | version '1.0-SNAPSHOT' |
| 3 | 3 | ||
| 4 | buildscript { | 4 | buildscript { |
| 5 | - ext.kotlin_version = '1.6.21' | 5 | + ext.kotlin_version = '1.7.10' |
| 6 | repositories { | 6 | repositories { |
| 7 | google() | 7 | google() |
| 8 | mavenCentral() | 8 | mavenCentral() |
| 9 | } | 9 | } |
| 10 | 10 | ||
| 11 | dependencies { | 11 | dependencies { |
| 12 | - classpath 'com.android.tools.build:gradle:7.2.1' | 12 | + classpath 'com.android.tools.build:gradle:7.2.2' |
| 13 | } | 13 | } |
| 14 | } | 14 | } |
| 15 | 15 | ||
| @@ -24,7 +24,7 @@ apply plugin: 'com.android.library' | @@ -24,7 +24,7 @@ apply plugin: 'com.android.library' | ||
| 24 | apply plugin: 'kotlin-android' | 24 | apply plugin: 'kotlin-android' |
| 25 | 25 | ||
| 26 | android { | 26 | android { |
| 27 | - compileSdkVersion 32 | 27 | + compileSdkVersion 33 |
| 28 | 28 | ||
| 29 | compileOptions { | 29 | compileOptions { |
| 30 | sourceCompatibility JavaVersion.VERSION_1_8 | 30 | sourceCompatibility JavaVersion.VERSION_1_8 |
| @@ -52,16 +52,6 @@ dependencies { | @@ -52,16 +52,6 @@ dependencies { | ||
| 52 | // Use this dependency to use the dynamically downloaded model in Google Play Services | 52 | // Use this dependency to use the dynamically downloaded model in Google Play Services |
| 53 | // implementation 'com.google.android.gms:play-services-mlkit-barcode-scanning:18.0.0' | 53 | // implementation 'com.google.android.gms:play-services-mlkit-barcode-scanning:18.0.0' |
| 54 | 54 | ||
| 55 | - implementation "androidx.camera:camera-camera2:1.2.0-alpha01" | ||
| 56 | - implementation 'androidx.camera:camera-lifecycle:1.2.0-alpha01' | ||
| 57 | - | ||
| 58 | -// // The following line is optional, as the core library is included indirectly by camera-camera2 | ||
| 59 | -// implementation "androidx.camera:camera-core:1.1.0-alpha11" | ||
| 60 | -// implementation "androidx.camera:camera-camera2:1.1.0-alpha11" | ||
| 61 | -// // If you want to additionally use the CameraX Lifecycle library | ||
| 62 | -// implementation "androidx.camera:camera-lifecycle:1.1.0-alpha11" | ||
| 63 | -// // If you want to additionally use the CameraX View class | ||
| 64 | -// implementation "androidx.camera:camera-view:1.0.0-alpha31" | ||
| 65 | -// // If you want to additionally use the CameraX Extensions library | ||
| 66 | -// implementation "androidx.camera:camera-extensions:1.0.0-alpha31" | 55 | + implementation 'androidx.camera:camera-camera2:1.1.0' |
| 56 | + implementation 'androidx.camera:camera-lifecycle:1.1.0' | ||
| 67 | } | 57 | } |
| @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' | @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' | ||
| 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" | 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" |
| 27 | 27 | ||
| 28 | android { | 28 | android { |
| 29 | - compileSdkVersion 32 | 29 | + compileSdkVersion 33 |
| 30 | 30 | ||
| 31 | compileOptions { | 31 | compileOptions { |
| 32 | sourceCompatibility JavaVersion.VERSION_1_8 | 32 | sourceCompatibility JavaVersion.VERSION_1_8 |
| @@ -45,7 +45,7 @@ android { | @@ -45,7 +45,7 @@ android { | ||
| 45 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). | 45 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). |
| 46 | applicationId "dev.steenbakker.mobile_scanner_example" | 46 | applicationId "dev.steenbakker.mobile_scanner_example" |
| 47 | minSdkVersion 21 | 47 | minSdkVersion 21 |
| 48 | - targetSdkVersion 32 | 48 | + targetSdkVersion 33 |
| 49 | versionCode flutterVersionCode.toInteger() | 49 | versionCode flutterVersionCode.toInteger() |
| 50 | versionName flutterVersionName | 50 | versionName flutterVersionName |
| 51 | } | 51 | } |
| 1 | buildscript { | 1 | buildscript { |
| 2 | - ext.kotlin_version = '1.6.21' | 2 | + ext.kotlin_version = '1.7.10' |
| 3 | repositories { | 3 | repositories { |
| 4 | google() | 4 | google() |
| 5 | mavenCentral() | 5 | mavenCentral() |
| 6 | } | 6 | } |
| 7 | 7 | ||
| 8 | dependencies { | 8 | dependencies { |
| 9 | - classpath 'com.android.tools.build:gradle:7.2.1' | 9 | + classpath 'com.android.tools.build:gradle:7.2.2' |
| 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" | 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" |
| 11 | } | 11 | } |
| 12 | } | 12 | } |
| 1 | -#Tue May 31 10:34:01 CEST 2022 | 1 | +#Tue Aug 23 15:51:00 CEST 2022 |
| 2 | distributionBase=GRADLE_USER_HOME | 2 | distributionBase=GRADLE_USER_HOME |
| 3 | -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip | 3 | +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip |
| 4 | distributionPath=wrapper/dists | 4 | distributionPath=wrapper/dists |
| 5 | zipStorePath=wrapper/dists | 5 | zipStorePath=wrapper/dists |
| 6 | zipStoreBase=GRADLE_USER_HOME | 6 | zipStoreBase=GRADLE_USER_HOME |
| @@ -13,7 +13,7 @@ | @@ -13,7 +13,7 @@ | ||
| 13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; | 13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; |
| 14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; | 14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; |
| 15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; | 15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; |
| 16 | - C80F46710D9B9F4F17AD4E3D /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E133769572782C32D37D8AC /* Pods_Runner.framework */; }; | 16 | + A5A2C2B73A9F26060DE9FB22 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54E006799E73DEAB41FD3623 /* Pods_Runner.framework */; }; |
| 17 | /* End PBXBuildFile section */ | 17 | /* End PBXBuildFile section */ |
| 18 | 18 | ||
| 19 | /* Begin PBXCopyFilesBuildPhase section */ | 19 | /* Begin PBXCopyFilesBuildPhase section */ |
| @@ -32,9 +32,9 @@ | @@ -32,9 +32,9 @@ | ||
| 32 | /* Begin PBXFileReference section */ | 32 | /* Begin PBXFileReference section */ |
| 33 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; }; | 33 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; }; |
| 34 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; }; | 34 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; }; |
| 35 | - 1CD9C88F6BFEF6CB7CA6746B /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; }; | 35 | + 32FD382A786B3A0080FE63FD /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; }; |
| 36 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; | 36 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; |
| 37 | - 5E133769572782C32D37D8AC /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; | 37 | + 54E006799E73DEAB41FD3623 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; |
| 38 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; }; | 38 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; }; |
| 39 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; | 39 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; |
| 40 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; }; | 40 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; }; |
| @@ -45,8 +45,8 @@ | @@ -45,8 +45,8 @@ | ||
| 45 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; | 45 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; |
| 46 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; | 46 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; |
| 47 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; | 47 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; |
| 48 | - E29A089CD1D61281C49DBB79 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; }; | ||
| 49 | - E33BE6AC5C06F7A45470ADE0 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; }; | 48 | + D5B36FCD262B39F867CFDEEE /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; }; |
| 49 | + F0D5742F0690BE32D07B033A /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; }; | ||
| 50 | /* End PBXFileReference section */ | 50 | /* End PBXFileReference section */ |
| 51 | 51 | ||
| 52 | /* Begin PBXFrameworksBuildPhase section */ | 52 | /* Begin PBXFrameworksBuildPhase section */ |
| @@ -54,27 +54,19 @@ | @@ -54,27 +54,19 @@ | ||
| 54 | isa = PBXFrameworksBuildPhase; | 54 | isa = PBXFrameworksBuildPhase; |
| 55 | buildActionMask = 2147483647; | 55 | buildActionMask = 2147483647; |
| 56 | files = ( | 56 | files = ( |
| 57 | - C80F46710D9B9F4F17AD4E3D /* Pods_Runner.framework in Frameworks */, | 57 | + A5A2C2B73A9F26060DE9FB22 /* Pods_Runner.framework in Frameworks */, |
| 58 | ); | 58 | ); |
| 59 | runOnlyForDeploymentPostprocessing = 0; | 59 | runOnlyForDeploymentPostprocessing = 0; |
| 60 | }; | 60 | }; |
| 61 | /* End PBXFrameworksBuildPhase section */ | 61 | /* End PBXFrameworksBuildPhase section */ |
| 62 | 62 | ||
| 63 | /* Begin PBXGroup section */ | 63 | /* Begin PBXGroup section */ |
| 64 | - 0F766276E0F46921DEBF581B /* Frameworks */ = { | ||
| 65 | - isa = PBXGroup; | ||
| 66 | - children = ( | ||
| 67 | - 5E133769572782C32D37D8AC /* Pods_Runner.framework */, | ||
| 68 | - ); | ||
| 69 | - name = Frameworks; | ||
| 70 | - sourceTree = "<group>"; | ||
| 71 | - }; | ||
| 72 | 203D5C95A734778D93D18369 /* Pods */ = { | 64 | 203D5C95A734778D93D18369 /* Pods */ = { |
| 73 | isa = PBXGroup; | 65 | isa = PBXGroup; |
| 74 | children = ( | 66 | children = ( |
| 75 | - E33BE6AC5C06F7A45470ADE0 /* Pods-Runner.debug.xcconfig */, | ||
| 76 | - 1CD9C88F6BFEF6CB7CA6746B /* Pods-Runner.release.xcconfig */, | ||
| 77 | - E29A089CD1D61281C49DBB79 /* Pods-Runner.profile.xcconfig */, | 67 | + D5B36FCD262B39F867CFDEEE /* Pods-Runner.debug.xcconfig */, |
| 68 | + 32FD382A786B3A0080FE63FD /* Pods-Runner.release.xcconfig */, | ||
| 69 | + F0D5742F0690BE32D07B033A /* Pods-Runner.profile.xcconfig */, | ||
| 78 | ); | 70 | ); |
| 79 | path = Pods; | 71 | path = Pods; |
| 80 | sourceTree = "<group>"; | 72 | sourceTree = "<group>"; |
| @@ -97,7 +89,7 @@ | @@ -97,7 +89,7 @@ | ||
| 97 | 97C146F01CF9000F007C117D /* Runner */, | 89 | 97C146F01CF9000F007C117D /* Runner */, |
| 98 | 97C146EF1CF9000F007C117D /* Products */, | 90 | 97C146EF1CF9000F007C117D /* Products */, |
| 99 | 203D5C95A734778D93D18369 /* Pods */, | 91 | 203D5C95A734778D93D18369 /* Pods */, |
| 100 | - 0F766276E0F46921DEBF581B /* Frameworks */, | 92 | + FF36E403CAC9E06A5A96BB9F /* Frameworks */, |
| 101 | ); | 93 | ); |
| 102 | sourceTree = "<group>"; | 94 | sourceTree = "<group>"; |
| 103 | }; | 95 | }; |
| @@ -124,6 +116,14 @@ | @@ -124,6 +116,14 @@ | ||
| 124 | path = Runner; | 116 | path = Runner; |
| 125 | sourceTree = "<group>"; | 117 | sourceTree = "<group>"; |
| 126 | }; | 118 | }; |
| 119 | + FF36E403CAC9E06A5A96BB9F /* Frameworks */ = { | ||
| 120 | + isa = PBXGroup; | ||
| 121 | + children = ( | ||
| 122 | + 54E006799E73DEAB41FD3623 /* Pods_Runner.framework */, | ||
| 123 | + ); | ||
| 124 | + name = Frameworks; | ||
| 125 | + sourceTree = "<group>"; | ||
| 126 | + }; | ||
| 127 | /* End PBXGroup section */ | 127 | /* End PBXGroup section */ |
| 128 | 128 | ||
| 129 | /* Begin PBXNativeTarget section */ | 129 | /* Begin PBXNativeTarget section */ |
| @@ -131,14 +131,14 @@ | @@ -131,14 +131,14 @@ | ||
| 131 | isa = PBXNativeTarget; | 131 | isa = PBXNativeTarget; |
| 132 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; | 132 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; |
| 133 | buildPhases = ( | 133 | buildPhases = ( |
| 134 | - 1C759CA63421B131D22BB688 /* [CP] Check Pods Manifest.lock */, | 134 | + B086C54F5791A4E759CB6822 /* [CP] Check Pods Manifest.lock */, |
| 135 | 9740EEB61CF901F6004384FC /* Run Script */, | 135 | 9740EEB61CF901F6004384FC /* Run Script */, |
| 136 | 97C146EA1CF9000F007C117D /* Sources */, | 136 | 97C146EA1CF9000F007C117D /* Sources */, |
| 137 | 97C146EB1CF9000F007C117D /* Frameworks */, | 137 | 97C146EB1CF9000F007C117D /* Frameworks */, |
| 138 | 97C146EC1CF9000F007C117D /* Resources */, | 138 | 97C146EC1CF9000F007C117D /* Resources */, |
| 139 | 9705A1C41CF9048500538489 /* Embed Frameworks */, | 139 | 9705A1C41CF9048500538489 /* Embed Frameworks */, |
| 140 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, | 140 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, |
| 141 | - EE97B31B239E017B5516C6AD /* [CP] Embed Pods Frameworks */, | 141 | + F825A499E8C466DB9DC6247D /* [CP] Embed Pods Frameworks */, |
| 142 | ); | 142 | ); |
| 143 | buildRules = ( | 143 | buildRules = ( |
| 144 | ); | 144 | ); |
| @@ -197,57 +197,57 @@ | @@ -197,57 +197,57 @@ | ||
| 197 | /* End PBXResourcesBuildPhase section */ | 197 | /* End PBXResourcesBuildPhase section */ |
| 198 | 198 | ||
| 199 | /* Begin PBXShellScriptBuildPhase section */ | 199 | /* Begin PBXShellScriptBuildPhase section */ |
| 200 | - 1C759CA63421B131D22BB688 /* [CP] Check Pods Manifest.lock */ = { | 200 | + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { |
| 201 | isa = PBXShellScriptBuildPhase; | 201 | isa = PBXShellScriptBuildPhase; |
| 202 | buildActionMask = 2147483647; | 202 | buildActionMask = 2147483647; |
| 203 | files = ( | 203 | files = ( |
| 204 | ); | 204 | ); |
| 205 | - inputFileListPaths = ( | ||
| 206 | - ); | ||
| 207 | inputPaths = ( | 205 | inputPaths = ( |
| 208 | - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", | ||
| 209 | - "${PODS_ROOT}/Manifest.lock", | ||
| 210 | - ); | ||
| 211 | - name = "[CP] Check Pods Manifest.lock"; | ||
| 212 | - outputFileListPaths = ( | ||
| 213 | ); | 206 | ); |
| 207 | + name = "Thin Binary"; | ||
| 214 | outputPaths = ( | 208 | outputPaths = ( |
| 215 | - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", | ||
| 216 | ); | 209 | ); |
| 217 | runOnlyForDeploymentPostprocessing = 0; | 210 | runOnlyForDeploymentPostprocessing = 0; |
| 218 | shellPath = /bin/sh; | 211 | shellPath = /bin/sh; |
| 219 | - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; | ||
| 220 | - showEnvVarsInLog = 0; | 212 | + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; |
| 221 | }; | 213 | }; |
| 222 | - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { | 214 | + 9740EEB61CF901F6004384FC /* Run Script */ = { |
| 223 | isa = PBXShellScriptBuildPhase; | 215 | isa = PBXShellScriptBuildPhase; |
| 224 | buildActionMask = 2147483647; | 216 | buildActionMask = 2147483647; |
| 225 | files = ( | 217 | files = ( |
| 226 | ); | 218 | ); |
| 227 | inputPaths = ( | 219 | inputPaths = ( |
| 228 | ); | 220 | ); |
| 229 | - name = "Thin Binary"; | 221 | + name = "Run Script"; |
| 230 | outputPaths = ( | 222 | outputPaths = ( |
| 231 | ); | 223 | ); |
| 232 | runOnlyForDeploymentPostprocessing = 0; | 224 | runOnlyForDeploymentPostprocessing = 0; |
| 233 | shellPath = /bin/sh; | 225 | shellPath = /bin/sh; |
| 234 | - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; | 226 | + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; |
| 235 | }; | 227 | }; |
| 236 | - 9740EEB61CF901F6004384FC /* Run Script */ = { | 228 | + B086C54F5791A4E759CB6822 /* [CP] Check Pods Manifest.lock */ = { |
| 237 | isa = PBXShellScriptBuildPhase; | 229 | isa = PBXShellScriptBuildPhase; |
| 238 | buildActionMask = 2147483647; | 230 | buildActionMask = 2147483647; |
| 239 | files = ( | 231 | files = ( |
| 240 | ); | 232 | ); |
| 233 | + inputFileListPaths = ( | ||
| 234 | + ); | ||
| 241 | inputPaths = ( | 235 | inputPaths = ( |
| 236 | + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", | ||
| 237 | + "${PODS_ROOT}/Manifest.lock", | ||
| 238 | + ); | ||
| 239 | + name = "[CP] Check Pods Manifest.lock"; | ||
| 240 | + outputFileListPaths = ( | ||
| 242 | ); | 241 | ); |
| 243 | - name = "Run Script"; | ||
| 244 | outputPaths = ( | 242 | outputPaths = ( |
| 243 | + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", | ||
| 245 | ); | 244 | ); |
| 246 | runOnlyForDeploymentPostprocessing = 0; | 245 | runOnlyForDeploymentPostprocessing = 0; |
| 247 | shellPath = /bin/sh; | 246 | shellPath = /bin/sh; |
| 248 | - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; | 247 | + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; |
| 248 | + showEnvVarsInLog = 0; | ||
| 249 | }; | 249 | }; |
| 250 | - EE97B31B239E017B5516C6AD /* [CP] Embed Pods Frameworks */ = { | 250 | + F825A499E8C466DB9DC6247D /* [CP] Embed Pods Frameworks */ = { |
| 251 | isa = PBXShellScriptBuildPhase; | 251 | isa = PBXShellScriptBuildPhase; |
| 252 | buildActionMask = 2147483647; | 252 | buildActionMask = 2147483647; |
| 253 | files = ( | 253 | files = ( |
| @@ -355,14 +355,14 @@ | @@ -355,14 +355,14 @@ | ||
| 355 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | 355 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
| 356 | CLANG_ENABLE_MODULES = YES; | 356 | CLANG_ENABLE_MODULES = YES; |
| 357 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; | 357 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; |
| 358 | - DEVELOPMENT_TEAM = 75Y2P2WSQQ; | 358 | + DEVELOPMENT_TEAM = RCH2VG82SH; |
| 359 | ENABLE_BITCODE = NO; | 359 | ENABLE_BITCODE = NO; |
| 360 | INFOPLIST_FILE = Runner/Info.plist; | 360 | INFOPLIST_FILE = Runner/Info.plist; |
| 361 | LD_RUNPATH_SEARCH_PATHS = ( | 361 | LD_RUNPATH_SEARCH_PATHS = ( |
| 362 | "$(inherited)", | 362 | "$(inherited)", |
| 363 | "@executable_path/Frameworks", | 363 | "@executable_path/Frameworks", |
| 364 | ); | 364 | ); |
| 365 | - PRODUCT_BUNDLE_IDENTIFIER = dev.steenbakker.mobileScannerExample; | 365 | + PRODUCT_BUNDLE_IDENTIFIER = dev.steenbakker.mobileScanner; |
| 366 | PRODUCT_NAME = "$(TARGET_NAME)"; | 366 | PRODUCT_NAME = "$(TARGET_NAME)"; |
| 367 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; | 367 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; |
| 368 | SWIFT_VERSION = 5.0; | 368 | SWIFT_VERSION = 5.0; |
| @@ -484,14 +484,14 @@ | @@ -484,14 +484,14 @@ | ||
| 484 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | 484 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
| 485 | CLANG_ENABLE_MODULES = YES; | 485 | CLANG_ENABLE_MODULES = YES; |
| 486 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; | 486 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; |
| 487 | - DEVELOPMENT_TEAM = 75Y2P2WSQQ; | 487 | + DEVELOPMENT_TEAM = RCH2VG82SH; |
| 488 | ENABLE_BITCODE = NO; | 488 | ENABLE_BITCODE = NO; |
| 489 | INFOPLIST_FILE = Runner/Info.plist; | 489 | INFOPLIST_FILE = Runner/Info.plist; |
| 490 | LD_RUNPATH_SEARCH_PATHS = ( | 490 | LD_RUNPATH_SEARCH_PATHS = ( |
| 491 | "$(inherited)", | 491 | "$(inherited)", |
| 492 | "@executable_path/Frameworks", | 492 | "@executable_path/Frameworks", |
| 493 | ); | 493 | ); |
| 494 | - PRODUCT_BUNDLE_IDENTIFIER = dev.steenbakker.mobileScannerExample; | 494 | + PRODUCT_BUNDLE_IDENTIFIER = dev.steenbakker.mobileScanner; |
| 495 | PRODUCT_NAME = "$(TARGET_NAME)"; | 495 | PRODUCT_NAME = "$(TARGET_NAME)"; |
| 496 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; | 496 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; |
| 497 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; | 497 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; |
| @@ -507,14 +507,14 @@ | @@ -507,14 +507,14 @@ | ||
| 507 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | 507 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
| 508 | CLANG_ENABLE_MODULES = YES; | 508 | CLANG_ENABLE_MODULES = YES; |
| 509 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; | 509 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; |
| 510 | - DEVELOPMENT_TEAM = 75Y2P2WSQQ; | 510 | + DEVELOPMENT_TEAM = RCH2VG82SH; |
| 511 | ENABLE_BITCODE = NO; | 511 | ENABLE_BITCODE = NO; |
| 512 | INFOPLIST_FILE = Runner/Info.plist; | 512 | INFOPLIST_FILE = Runner/Info.plist; |
| 513 | LD_RUNPATH_SEARCH_PATHS = ( | 513 | LD_RUNPATH_SEARCH_PATHS = ( |
| 514 | "$(inherited)", | 514 | "$(inherited)", |
| 515 | "@executable_path/Frameworks", | 515 | "@executable_path/Frameworks", |
| 516 | ); | 516 | ); |
| 517 | - PRODUCT_BUNDLE_IDENTIFIER = dev.steenbakker.mobileScannerExample; | 517 | + PRODUCT_BUNDLE_IDENTIFIER = dev.steenbakker.mobileScanner; |
| 518 | PRODUCT_NAME = "$(TARGET_NAME)"; | 518 | PRODUCT_NAME = "$(TARGET_NAME)"; |
| 519 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; | 519 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; |
| 520 | SWIFT_VERSION = 5.0; | 520 | SWIFT_VERSION = 5.0; |
| @@ -2,10 +2,8 @@ | @@ -2,10 +2,8 @@ | ||
| 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| 3 | <plist version="1.0"> | 3 | <plist version="1.0"> |
| 4 | <dict> | 4 | <dict> |
| 5 | - <key>NSPhotoLibraryUsageDescription</key> | ||
| 6 | - <string>We need access in order to open photos of barcodes</string> | ||
| 7 | - <key>NSCameraUsageDescription</key> | ||
| 8 | - <string>We use the camera to scan barcodes</string> | 5 | + <key>CADisableMinimumFrameDurationOnPhone</key> |
| 6 | + <true/> | ||
| 9 | <key>CFBundleDevelopmentRegion</key> | 7 | <key>CFBundleDevelopmentRegion</key> |
| 10 | <string>$(DEVELOPMENT_LANGUAGE)</string> | 8 | <string>$(DEVELOPMENT_LANGUAGE)</string> |
| 11 | <key>CFBundleDisplayName</key> | 9 | <key>CFBundleDisplayName</key> |
| @@ -28,6 +26,10 @@ | @@ -28,6 +26,10 @@ | ||
| 28 | <string>$(FLUTTER_BUILD_NUMBER)</string> | 26 | <string>$(FLUTTER_BUILD_NUMBER)</string> |
| 29 | <key>LSRequiresIPhoneOS</key> | 27 | <key>LSRequiresIPhoneOS</key> |
| 30 | <true/> | 28 | <true/> |
| 29 | + <key>NSCameraUsageDescription</key> | ||
| 30 | + <string>We use the camera to scan barcodes</string> | ||
| 31 | + <key>NSPhotoLibraryUsageDescription</key> | ||
| 32 | + <string>We need access in order to open photos of barcodes</string> | ||
| 31 | <key>UILaunchStoryboardName</key> | 33 | <key>UILaunchStoryboardName</key> |
| 32 | <string>LaunchScreen</string> | 34 | <string>LaunchScreen</string> |
| 33 | <key>UIMainStoryboardFile</key> | 35 | <key>UIMainStoryboardFile</key> |
| @@ -47,7 +49,5 @@ | @@ -47,7 +49,5 @@ | ||
| 47 | </array> | 49 | </array> |
| 48 | <key>UIViewControllerBasedStatusBarAppearance</key> | 50 | <key>UIViewControllerBasedStatusBarAppearance</key> |
| 49 | <false/> | 51 | <false/> |
| 50 | - <key>CADisableMinimumFrameDurationOnPhone</key> | ||
| 51 | - <true/> | ||
| 52 | </dict> | 52 | </dict> |
| 53 | </plist> | 53 | </plist> |
| @@ -133,9 +133,9 @@ class _BarcodeScannerWithControllerState | @@ -133,9 +133,9 @@ class _BarcodeScannerWithControllerState | ||
| 133 | icon: const Icon(Icons.image), | 133 | icon: const Icon(Icons.image), |
| 134 | iconSize: 32.0, | 134 | iconSize: 32.0, |
| 135 | onPressed: () async { | 135 | onPressed: () async { |
| 136 | - final ImagePicker _picker = ImagePicker(); | 136 | + final ImagePicker picker = ImagePicker(); |
| 137 | // Pick an image | 137 | // Pick an image |
| 138 | - final XFile? image = await _picker.pickImage( | 138 | + final XFile? image = await picker.pickImage( |
| 139 | source: ImageSource.gallery, | 139 | source: ImageSource.gallery, |
| 140 | ); | 140 | ); |
| 141 | if (image != null) { | 141 | if (image != null) { |
| 1 | +import 'dart:typed_data'; | ||
| 2 | + | ||
| 3 | +import 'package:flutter/material.dart'; | ||
| 4 | +import 'package:mobile_scanner/mobile_scanner.dart'; | ||
| 5 | + | ||
| 6 | +class BarcodeScannerReturningImage extends StatefulWidget { | ||
| 7 | + const BarcodeScannerReturningImage({Key? key}) : super(key: key); | ||
| 8 | + | ||
| 9 | + @override | ||
| 10 | + _BarcodeScannerReturningImageState createState() => | ||
| 11 | + _BarcodeScannerReturningImageState(); | ||
| 12 | +} | ||
| 13 | + | ||
| 14 | +class _BarcodeScannerReturningImageState | ||
| 15 | + extends State<BarcodeScannerReturningImage> | ||
| 16 | + with SingleTickerProviderStateMixin { | ||
| 17 | + String? barcode; | ||
| 18 | + Uint8List? image; | ||
| 19 | + | ||
| 20 | + MobileScannerController controller = MobileScannerController( | ||
| 21 | + torchEnabled: true, | ||
| 22 | + returnImage: true, | ||
| 23 | + // formats: [BarcodeFormat.qrCode] | ||
| 24 | + // facing: CameraFacing.front, | ||
| 25 | + ); | ||
| 26 | + | ||
| 27 | + bool isStarted = true; | ||
| 28 | + | ||
| 29 | + @override | ||
| 30 | + Widget build(BuildContext context) { | ||
| 31 | + return Scaffold( | ||
| 32 | + backgroundColor: Colors.black, | ||
| 33 | + body: Builder( | ||
| 34 | + builder: (context) { | ||
| 35 | + return Stack( | ||
| 36 | + children: [ | ||
| 37 | + MobileScanner( | ||
| 38 | + controller: controller, | ||
| 39 | + fit: BoxFit.contain, | ||
| 40 | + // allowDuplicates: true, | ||
| 41 | + // controller: MobileScannerController( | ||
| 42 | + // torchEnabled: true, | ||
| 43 | + // facing: CameraFacing.front, | ||
| 44 | + // ), | ||
| 45 | + onDetect: (barcode, args) { | ||
| 46 | + setState(() { | ||
| 47 | + this.barcode = barcode.rawValue; | ||
| 48 | + showDialog( | ||
| 49 | + context: context, | ||
| 50 | + builder: (context) => Image( | ||
| 51 | + image: MemoryImage(image!), | ||
| 52 | + fit: BoxFit.contain, | ||
| 53 | + ), | ||
| 54 | + ); | ||
| 55 | + image = barcode.image; | ||
| 56 | + }); | ||
| 57 | + }, | ||
| 58 | + ), | ||
| 59 | + Align( | ||
| 60 | + alignment: Alignment.bottomCenter, | ||
| 61 | + child: Container( | ||
| 62 | + alignment: Alignment.bottomCenter, | ||
| 63 | + height: 100, | ||
| 64 | + color: Colors.black.withOpacity(0.4), | ||
| 65 | + child: Row( | ||
| 66 | + mainAxisAlignment: MainAxisAlignment.spaceEvenly, | ||
| 67 | + children: [ | ||
| 68 | + IconButton( | ||
| 69 | + color: Colors.white, | ||
| 70 | + icon: ValueListenableBuilder( | ||
| 71 | + valueListenable: controller.torchState, | ||
| 72 | + builder: (context, state, child) { | ||
| 73 | + if (state == null) { | ||
| 74 | + return const Icon( | ||
| 75 | + Icons.flash_off, | ||
| 76 | + color: Colors.grey, | ||
| 77 | + ); | ||
| 78 | + } | ||
| 79 | + switch (state as TorchState) { | ||
| 80 | + case TorchState.off: | ||
| 81 | + return const Icon( | ||
| 82 | + Icons.flash_off, | ||
| 83 | + color: Colors.grey, | ||
| 84 | + ); | ||
| 85 | + case TorchState.on: | ||
| 86 | + return const Icon( | ||
| 87 | + Icons.flash_on, | ||
| 88 | + color: Colors.yellow, | ||
| 89 | + ); | ||
| 90 | + } | ||
| 91 | + }, | ||
| 92 | + ), | ||
| 93 | + iconSize: 32.0, | ||
| 94 | + onPressed: () => controller.toggleTorch(), | ||
| 95 | + ), | ||
| 96 | + IconButton( | ||
| 97 | + color: Colors.white, | ||
| 98 | + icon: isStarted | ||
| 99 | + ? const Icon(Icons.stop) | ||
| 100 | + : const Icon(Icons.play_arrow), | ||
| 101 | + iconSize: 32.0, | ||
| 102 | + onPressed: () => setState(() { | ||
| 103 | + isStarted ? controller.stop() : controller.start(); | ||
| 104 | + isStarted = !isStarted; | ||
| 105 | + }), | ||
| 106 | + ), | ||
| 107 | + Center( | ||
| 108 | + child: SizedBox( | ||
| 109 | + width: MediaQuery.of(context).size.width - 200, | ||
| 110 | + height: 50, | ||
| 111 | + child: FittedBox( | ||
| 112 | + child: Text( | ||
| 113 | + barcode ?? 'Scan something!', | ||
| 114 | + overflow: TextOverflow.fade, | ||
| 115 | + style: Theme.of(context) | ||
| 116 | + .textTheme | ||
| 117 | + .headline4! | ||
| 118 | + .copyWith(color: Colors.white), | ||
| 119 | + ), | ||
| 120 | + ), | ||
| 121 | + ), | ||
| 122 | + ), | ||
| 123 | + IconButton( | ||
| 124 | + color: Colors.white, | ||
| 125 | + icon: ValueListenableBuilder( | ||
| 126 | + valueListenable: controller.cameraFacingState, | ||
| 127 | + builder: (context, state, child) { | ||
| 128 | + if (state == null) { | ||
| 129 | + return const Icon(Icons.camera_front); | ||
| 130 | + } | ||
| 131 | + switch (state as CameraFacing) { | ||
| 132 | + case CameraFacing.front: | ||
| 133 | + return const Icon(Icons.camera_front); | ||
| 134 | + case CameraFacing.back: | ||
| 135 | + return const Icon(Icons.camera_rear); | ||
| 136 | + } | ||
| 137 | + }, | ||
| 138 | + ), | ||
| 139 | + iconSize: 32.0, | ||
| 140 | + onPressed: () => controller.switchCamera(), | ||
| 141 | + ), | ||
| 142 | + SizedBox( | ||
| 143 | + width: 50, | ||
| 144 | + height: 50, | ||
| 145 | + child: image != null | ||
| 146 | + ? Image( | ||
| 147 | + image: MemoryImage(image!), | ||
| 148 | + fit: BoxFit.contain, | ||
| 149 | + ) | ||
| 150 | + : Container(), | ||
| 151 | + ), | ||
| 152 | + ], | ||
| 153 | + ), | ||
| 154 | + ), | ||
| 155 | + ), | ||
| 156 | + ], | ||
| 157 | + ); | ||
| 158 | + }, | ||
| 159 | + ), | ||
| 160 | + ); | ||
| 161 | + } | ||
| 162 | +} |
| 1 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 2 | import 'package:mobile_scanner_example/barcode_scanner_controller.dart'; | 2 | import 'package:mobile_scanner_example/barcode_scanner_controller.dart'; |
| 3 | +import 'package:mobile_scanner_example/barcode_scanner_returning_image.dart'; | ||
| 3 | import 'package:mobile_scanner_example/barcode_scanner_without_controller.dart'; | 4 | import 'package:mobile_scanner_example/barcode_scanner_without_controller.dart'; |
| 4 | 5 | ||
| 5 | void main() => runApp(const MaterialApp(home: MyHome())); | 6 | void main() => runApp(const MaterialApp(home: MyHome())); |
| @@ -31,6 +32,17 @@ class MyHome extends StatelessWidget { | @@ -31,6 +32,17 @@ class MyHome extends StatelessWidget { | ||
| 31 | onPressed: () { | 32 | onPressed: () { |
| 32 | Navigator.of(context).push( | 33 | Navigator.of(context).push( |
| 33 | MaterialPageRoute( | 34 | MaterialPageRoute( |
| 35 | + builder: (context) => const BarcodeScannerReturningImage(), | ||
| 36 | + ), | ||
| 37 | + ); | ||
| 38 | + }, | ||
| 39 | + child: | ||
| 40 | + const Text('MobileScanner with Controller (returning image)'), | ||
| 41 | + ), | ||
| 42 | + ElevatedButton( | ||
| 43 | + onPressed: () { | ||
| 44 | + Navigator.of(context).push( | ||
| 45 | + MaterialPageRoute( | ||
| 34 | builder: (context) => | 46 | builder: (context) => |
| 35 | const BarcodeScannerWithoutController(), | 47 | const BarcodeScannerWithoutController(), |
| 36 | ), | 48 | ), |
| @@ -22,6 +22,9 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | @@ -22,6 +22,9 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | ||
| 22 | // Image to be sent to the texture | 22 | // Image to be sent to the texture |
| 23 | var latestBuffer: CVImageBuffer! | 23 | var latestBuffer: CVImageBuffer! |
| 24 | 24 | ||
| 25 | + // Return image buffer with the Barcode event | ||
| 26 | + var returnImage: Bool = false | ||
| 27 | + | ||
| 25 | // var analyzeMode: Int = 0 | 28 | // var analyzeMode: Int = 0 |
| 26 | var analyzing: Bool = false | 29 | var analyzing: Bool = false |
| 27 | var position = AVCaptureDevice.Position.back | 30 | var position = AVCaptureDevice.Position.back |
| @@ -61,6 +64,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | @@ -61,6 +64,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | ||
| 61 | stop(result) | 64 | stop(result) |
| 62 | case "analyzeImage": | 65 | case "analyzeImage": |
| 63 | analyzeImage(call, result) | 66 | analyzeImage(call, result) |
| 67 | + | ||
| 64 | default: | 68 | default: |
| 65 | result(FlutterMethodNotImplemented) | 69 | result(FlutterMethodNotImplemented) |
| 66 | } | 70 | } |
| @@ -86,6 +90,16 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | @@ -86,6 +90,16 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | ||
| 86 | return Unmanaged<CVPixelBuffer>.passRetained(latestBuffer) | 90 | return Unmanaged<CVPixelBuffer>.passRetained(latestBuffer) |
| 87 | } | 91 | } |
| 88 | 92 | ||
| 93 | + private func ciImageToJpeg(ciImage: CIImage) -> Data { | ||
| 94 | + | ||
| 95 | + // let ciImage = CIImage(cvPixelBuffer: latestBuffer) | ||
| 96 | + let context:CIContext = CIContext.init(options: nil) | ||
| 97 | + let cgImage:CGImage = context.createCGImage(ciImage, from: ciImage.extent)! | ||
| 98 | + let uiImage:UIImage = UIImage(cgImage: cgImage, scale: 1, orientation: UIImage.Orientation.up) | ||
| 99 | + | ||
| 100 | + return uiImage.jpegData(compressionQuality: 0.8)!; | ||
| 101 | + } | ||
| 102 | + | ||
| 89 | // Gets called when a new image is added to the buffer | 103 | // Gets called when a new image is added to the buffer |
| 90 | public func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { | 104 | public func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { |
| 91 | 105 | ||
| @@ -108,7 +122,13 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | @@ -108,7 +122,13 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | ||
| 108 | scanner.process(image) { [self] barcodes, error in | 122 | scanner.process(image) { [self] barcodes, error in |
| 109 | if error == nil && barcodes != nil { | 123 | if error == nil && barcodes != nil { |
| 110 | for barcode in barcodes! { | 124 | for barcode in barcodes! { |
| 111 | - let event: [String: Any?] = ["name": "barcode", "data": barcode.data] | 125 | + |
| 126 | + var event: [String: Any?] = ["name": "barcode", "data": barcode.data] | ||
| 127 | + if (returnImage && latestBuffer != nil) { | ||
| 128 | + let image: CIImage = CIImage(cvPixelBuffer: latestBuffer) | ||
| 129 | + | ||
| 130 | + event["image"] = FlutterStandardTypedData(bytes: ciImageToJpeg(ciImage: image)) | ||
| 131 | + } | ||
| 112 | sink?(event) | 132 | sink?(event) |
| 113 | } | 133 | } |
| 114 | } | 134 | } |
| @@ -168,6 +188,8 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | @@ -168,6 +188,8 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | ||
| 168 | 188 | ||
| 169 | let argReader = MapArgumentReader(call.arguments as? [String: Any]) | 189 | let argReader = MapArgumentReader(call.arguments as? [String: Any]) |
| 170 | 190 | ||
| 191 | + returnImage = argReader.bool(key: "returnImage") ?? false | ||
| 192 | + | ||
| 171 | // let ratio: Int = argReader.int(key: "ratio") | 193 | // let ratio: Int = argReader.int(key: "ratio") |
| 172 | let torch: Bool = argReader.bool(key: "torch") ?? false | 194 | let torch: Bool = argReader.bool(key: "torch") ?? false |
| 173 | let facing: Int = argReader.int(key: "facing") ?? 1 | 195 | let facing: Int = argReader.int(key: "facing") ?? 1 |
| @@ -15,7 +15,7 @@ An universal scanner for Flutter based on MLKit. | @@ -15,7 +15,7 @@ An universal scanner for Flutter based on MLKit. | ||
| 15 | s.source = { :path => '.' } | 15 | s.source = { :path => '.' } |
| 16 | s.source_files = 'Classes/**/*' | 16 | s.source_files = 'Classes/**/*' |
| 17 | s.dependency 'Flutter' | 17 | s.dependency 'Flutter' |
| 18 | - s.dependency 'GoogleMLKit/BarcodeScanning', '~> 2.6.0' | 18 | + s.dependency 'GoogleMLKit/BarcodeScanning', '~> 3.2.0' |
| 19 | s.platform = :ios, '10.0' | 19 | s.platform = :ios, '10.0' |
| 20 | s.static_framework = true | 20 | s.static_framework = true |
| 21 | # Flutter.framework does not contain a i386 slice. | 21 | # Flutter.framework does not contain a i386 slice. |
| @@ -200,7 +200,11 @@ class MobileScannerWebPlugin { | @@ -200,7 +200,11 @@ class MobileScannerWebPlugin { | ||
| 200 | 200 | ||
| 201 | final code = jsQR(imgData.data, canvas.width, canvas.height); | 201 | final code = jsQR(imgData.data, canvas.width, canvas.height); |
| 202 | if (code != null) { | 202 | if (code != null) { |
| 203 | - controller.add({'name': 'barcodeWeb', 'data': code.data}); | 203 | + controller.add({ |
| 204 | + 'name': 'barcodeWeb', | ||
| 205 | + 'data': code.data, | ||
| 206 | + 'binaryData': code.binaryData, | ||
| 207 | + }); | ||
| 204 | } | 208 | } |
| 205 | } | 209 | } |
| 206 | } | 210 | } |
| @@ -32,13 +32,13 @@ class MobileScanner extends StatefulWidget { | @@ -32,13 +32,13 @@ class MobileScanner extends StatefulWidget { | ||
| 32 | 32 | ||
| 33 | /// Create a [MobileScanner] with a [controller], the [controller] must has been initialized. | 33 | /// Create a [MobileScanner] with a [controller], the [controller] must has been initialized. |
| 34 | const MobileScanner({ | 34 | const MobileScanner({ |
| 35 | - Key? key, | 35 | + super.key, |
| 36 | required this.onDetect, | 36 | required this.onDetect, |
| 37 | this.controller, | 37 | this.controller, |
| 38 | this.fit = BoxFit.cover, | 38 | this.fit = BoxFit.cover, |
| 39 | this.allowDuplicates = false, | 39 | this.allowDuplicates = false, |
| 40 | this.onPermissionSet, | 40 | this.onPermissionSet, |
| 41 | - }) : super(key: key); | 41 | + }); |
| 42 | 42 | ||
| 43 | @override | 43 | @override |
| 44 | State<MobileScanner> createState() => _MobileScannerState(); | 44 | State<MobileScanner> createState() => _MobileScannerState(); |
| @@ -53,13 +53,14 @@ class _MobileScannerState extends State<MobileScanner> | @@ -53,13 +53,14 @@ class _MobileScannerState extends State<MobileScanner> | ||
| 53 | super.initState(); | 53 | super.initState(); |
| 54 | WidgetsBinding.instance.addObserver(this); | 54 | WidgetsBinding.instance.addObserver(this); |
| 55 | controller = widget.controller ?? MobileScannerController(onPermissionSet: widget.onPermissionSet); | 55 | controller = widget.controller ?? MobileScannerController(onPermissionSet: widget.onPermissionSet); |
| 56 | + if (!controller.isStarting) controller.start(); | ||
| 56 | } | 57 | } |
| 57 | 58 | ||
| 58 | @override | 59 | @override |
| 59 | void didChangeAppLifecycleState(AppLifecycleState state) { | 60 | void didChangeAppLifecycleState(AppLifecycleState state) { |
| 60 | switch (state) { | 61 | switch (state) { |
| 61 | case AppLifecycleState.resumed: | 62 | case AppLifecycleState.resumed: |
| 62 | - if (!controller.isStarting) controller.start(); | 63 | + if (!controller.isStarting && controller.autoResume) controller.start(); |
| 63 | break; | 64 | break; |
| 64 | case AppLifecycleState.inactive: | 65 | case AppLifecycleState.inactive: |
| 65 | case AppLifecycleState.paused: | 66 | case AppLifecycleState.paused: |
| @@ -73,14 +74,12 @@ class _MobileScannerState extends State<MobileScanner> | @@ -73,14 +74,12 @@ class _MobileScannerState extends State<MobileScanner> | ||
| 73 | 74 | ||
| 74 | @override | 75 | @override |
| 75 | Widget build(BuildContext context) { | 76 | Widget build(BuildContext context) { |
| 76 | - return LayoutBuilder( | ||
| 77 | - builder: (context, BoxConstraints constraints) { | ||
| 78 | return ValueListenableBuilder( | 77 | return ValueListenableBuilder( |
| 79 | valueListenable: controller.args, | 78 | valueListenable: controller.args, |
| 80 | builder: (context, value, child) { | 79 | builder: (context, value, child) { |
| 81 | value = value as MobileScannerArguments?; | 80 | value = value as MobileScannerArguments?; |
| 82 | if (value == null) { | 81 | if (value == null) { |
| 83 | - return Container(color: Colors.black); | 82 | + return const ColoredBox(color: Colors.black); |
| 84 | } else { | 83 | } else { |
| 85 | controller.barcodes.listen((barcode) { | 84 | controller.barcodes.listen((barcode) { |
| 86 | if (!widget.allowDuplicates) { | 85 | if (!widget.allowDuplicates) { |
| @@ -111,8 +110,6 @@ class _MobileScannerState extends State<MobileScanner> | @@ -111,8 +110,6 @@ class _MobileScannerState extends State<MobileScanner> | ||
| 111 | } | 110 | } |
| 112 | }, | 111 | }, |
| 113 | ); | 112 | ); |
| 114 | - }, | ||
| 115 | - ); | ||
| 116 | } | 113 | } |
| 117 | 114 | ||
| 118 | @override | 115 | @override |
| @@ -35,7 +35,8 @@ class MobileScannerController { | @@ -35,7 +35,8 @@ class MobileScannerController { | ||
| 35 | EventChannel eventChannel = | 35 | EventChannel eventChannel = |
| 36 | const EventChannel('dev.steenbakker.mobile_scanner/scanner/event'); | 36 | const EventChannel('dev.steenbakker.mobile_scanner/scanner/event'); |
| 37 | 37 | ||
| 38 | - int? _controllerHashcode; | 38 | + //Must be static to keep the same value on new instances |
| 39 | + static int? _controllerHashcode; | ||
| 39 | StreamSubscription? events; | 40 | StreamSubscription? events; |
| 40 | 41 | ||
| 41 | Function(bool permissionGranted)? onPermissionSet; | 42 | Function(bool permissionGranted)? onPermissionSet; |
| @@ -44,6 +45,8 @@ class MobileScannerController { | @@ -44,6 +45,8 @@ class MobileScannerController { | ||
| 44 | late final ValueNotifier<CameraFacing> cameraFacingState; | 45 | late final ValueNotifier<CameraFacing> cameraFacingState; |
| 45 | final Ratio? ratio; | 46 | final Ratio? ratio; |
| 46 | final bool? torchEnabled; | 47 | final bool? torchEnabled; |
| 48 | + // Whether to return the image buffer with the Barcode event | ||
| 49 | + final bool returnImage; | ||
| 47 | 50 | ||
| 48 | /// If provided, the scanner will only detect those specific formats. | 51 | /// If provided, the scanner will only detect those specific formats. |
| 49 | /// | 52 | /// |
| @@ -54,6 +57,9 @@ class MobileScannerController { | @@ -54,6 +57,9 @@ class MobileScannerController { | ||
| 54 | bool hasTorch = false; | 57 | bool hasTorch = false; |
| 55 | late StreamController<Barcode> barcodesController; | 58 | late StreamController<Barcode> barcodesController; |
| 56 | 59 | ||
| 60 | + /// Whether to automatically resume the camera when the application is resumed | ||
| 61 | + bool autoResume; | ||
| 62 | + | ||
| 57 | Stream<Barcode> get barcodes => barcodesController.stream; | 63 | Stream<Barcode> get barcodes => barcodesController.stream; |
| 58 | 64 | ||
| 59 | MobileScannerController({ | 65 | MobileScannerController({ |
| @@ -62,6 +68,8 @@ class MobileScannerController { | @@ -62,6 +68,8 @@ class MobileScannerController { | ||
| 62 | this.torchEnabled, | 68 | this.torchEnabled, |
| 63 | this.formats, | 69 | this.formats, |
| 64 | this.onPermissionSet, | 70 | this.onPermissionSet, |
| 71 | + this.autoResume = true, | ||
| 72 | + this.returnImage = false, | ||
| 65 | }) { | 73 | }) { |
| 66 | // In case a new instance is created before calling dispose() | 74 | // In case a new instance is created before calling dispose() |
| 67 | if (_controllerHashcode != null) { | 75 | if (_controllerHashcode != null) { |
| @@ -77,8 +85,6 @@ class MobileScannerController { | @@ -77,8 +85,6 @@ class MobileScannerController { | ||
| 77 | // onCancel: () => setAnalyzeMode(AnalyzeMode.none.index), | 85 | // onCancel: () => setAnalyzeMode(AnalyzeMode.none.index), |
| 78 | ); | 86 | ); |
| 79 | 87 | ||
| 80 | - start(); | ||
| 81 | - | ||
| 82 | // Listen to events from the platform specific code | 88 | // Listen to events from the platform specific code |
| 83 | events = eventChannel | 89 | events = eventChannel |
| 84 | .receiveBroadcastStream() | 90 | .receiveBroadcastStream() |
| @@ -88,24 +94,32 @@ class MobileScannerController { | @@ -88,24 +94,32 @@ class MobileScannerController { | ||
| 88 | void handleEvent(Map event) { | 94 | void handleEvent(Map event) { |
| 89 | final name = event['name']; | 95 | final name = event['name']; |
| 90 | final data = event['data']; | 96 | final data = event['data']; |
| 97 | + final binaryData = event['binaryData']; | ||
| 91 | switch (name) { | 98 | switch (name) { |
| 92 | case 'torchState': | 99 | case 'torchState': |
| 93 | - final state = TorchState.values[data as int]; | 100 | + final state = TorchState.values[data as int? ?? 0]; |
| 94 | torchState.value = state; | 101 | torchState.value = state; |
| 95 | break; | 102 | break; |
| 96 | case 'barcode': | 103 | case 'barcode': |
| 97 | - final barcode = Barcode.fromNative(data as Map); | 104 | + final image = returnImage ? event['image'] as Uint8List : null; |
| 105 | + final barcode = Barcode.fromNative(data as Map? ?? {}, image); | ||
| 98 | barcodesController.add(barcode); | 106 | barcodesController.add(barcode); |
| 99 | break; | 107 | break; |
| 100 | case 'barcodeMac': | 108 | case 'barcodeMac': |
| 101 | barcodesController.add( | 109 | barcodesController.add( |
| 102 | Barcode( | 110 | Barcode( |
| 103 | - rawValue: (data as Map)['payload'] as String, | 111 | + rawValue: (data as Map)['payload'] as String?, |
| 104 | ), | 112 | ), |
| 105 | ); | 113 | ); |
| 106 | break; | 114 | break; |
| 107 | case 'barcodeWeb': | 115 | case 'barcodeWeb': |
| 108 | - barcodesController.add(Barcode(rawValue: data as String)); | 116 | + final bytes = (binaryData as List).cast<int>(); |
| 117 | + barcodesController.add( | ||
| 118 | + Barcode( | ||
| 119 | + rawValue: data as String?, | ||
| 120 | + rawBytes: Uint8List.fromList(bytes), | ||
| 121 | + ), | ||
| 122 | + ); | ||
| 109 | break; | 123 | break; |
| 110 | default: | 124 | default: |
| 111 | throw UnimplementedError(); | 125 | throw UnimplementedError(); |
| @@ -136,11 +150,11 @@ class MobileScannerController { | @@ -136,11 +150,11 @@ class MobileScannerController { | ||
| 136 | // Check authorization status | 150 | // Check authorization status |
| 137 | if (!kIsWeb) { | 151 | if (!kIsWeb) { |
| 138 | MobileScannerState state = MobileScannerState | 152 | MobileScannerState state = MobileScannerState |
| 139 | - .values[await methodChannel.invokeMethod('state') as int]; | 153 | + .values[await methodChannel.invokeMethod('state') as int? ?? 0]; |
| 140 | switch (state) { | 154 | switch (state) { |
| 141 | case MobileScannerState.undetermined: | 155 | case MobileScannerState.undetermined: |
| 142 | final bool result = | 156 | final bool result = |
| 143 | - await methodChannel.invokeMethod('request') as bool; | 157 | + await methodChannel.invokeMethod('request') as bool? ?? false; |
| 144 | state = result | 158 | state = result |
| 145 | ? MobileScannerState.authorized | 159 | ? MobileScannerState.authorized |
| 146 | : MobileScannerState.denied; | 160 | : MobileScannerState.denied; |
| @@ -171,6 +185,7 @@ class MobileScannerController { | @@ -171,6 +185,7 @@ class MobileScannerController { | ||
| 171 | arguments['formats'] = formats!.map((e) => e.rawValue).toList(); | 185 | arguments['formats'] = formats!.map((e) => e.rawValue).toList(); |
| 172 | } | 186 | } |
| 173 | } | 187 | } |
| 188 | + arguments['returnImage'] = returnImage; | ||
| 174 | 189 | ||
| 175 | // Start the camera with arguments | 190 | // Start the camera with arguments |
| 176 | Map<String, dynamic>? startResult = {}; | 191 | Map<String, dynamic>? startResult = {}; |
| @@ -194,7 +209,7 @@ class MobileScannerController { | @@ -194,7 +209,7 @@ class MobileScannerController { | ||
| 194 | throw PlatformException(code: 'INITIALIZATION ERROR'); | 209 | throw PlatformException(code: 'INITIALIZATION ERROR'); |
| 195 | } | 210 | } |
| 196 | 211 | ||
| 197 | - hasTorch = startResult['torchable'] as bool; | 212 | + hasTorch = startResult['torchable'] as bool? ?? false; |
| 198 | 213 | ||
| 199 | if (kIsWeb) { | 214 | if (kIsWeb) { |
| 200 | onPermissionSet?.call(true); // If we reach this line, it means camera permission has been granted | 215 | onPermissionSet?.call(true); // If we reach this line, it means camera permission has been granted |
| @@ -202,15 +217,15 @@ class MobileScannerController { | @@ -202,15 +217,15 @@ class MobileScannerController { | ||
| 202 | args.value = MobileScannerArguments( | 217 | args.value = MobileScannerArguments( |
| 203 | webId: startResult['ViewID'] as String?, | 218 | webId: startResult['ViewID'] as String?, |
| 204 | size: Size( | 219 | size: Size( |
| 205 | - startResult['videoWidth'] as double, | ||
| 206 | - startResult['videoHeight'] as double, | 220 | + startResult['videoWidth'] as double? ?? 0, |
| 221 | + startResult['videoHeight'] as double? ?? 0, | ||
| 207 | ), | 222 | ), |
| 208 | hasTorch: hasTorch, | 223 | hasTorch: hasTorch, |
| 209 | ); | 224 | ); |
| 210 | } else { | 225 | } else { |
| 211 | args.value = MobileScannerArguments( | 226 | args.value = MobileScannerArguments( |
| 212 | - textureId: startResult['textureId'] as int, | ||
| 213 | - size: toSize(startResult['size'] as Map), | 227 | + textureId: startResult['textureId'] as int?, |
| 228 | + size: toSize(startResult['size'] as Map? ?? {}), | ||
| 214 | hasTorch: hasTorch, | 229 | hasTorch: hasTorch, |
| 215 | ); | 230 | ); |
| 216 | } | 231 | } |
| @@ -12,6 +12,11 @@ class Barcode { | @@ -12,6 +12,11 @@ class Barcode { | ||
| 12 | /// Returns null if the corner points can not be determined. | 12 | /// Returns null if the corner points can not be determined. |
| 13 | final List<Offset>? corners; | 13 | final List<Offset>? corners; |
| 14 | 14 | ||
| 15 | + /// Returns raw bytes of the image buffer | ||
| 16 | + /// | ||
| 17 | + /// Returns null if the image was not returned | ||
| 18 | + final Uint8List? image; | ||
| 19 | + | ||
| 15 | /// Returns barcode format | 20 | /// Returns barcode format |
| 16 | final BarcodeFormat format; | 21 | final BarcodeFormat format; |
| 17 | 22 | ||
| @@ -74,6 +79,7 @@ class Barcode { | @@ -74,6 +79,7 @@ class Barcode { | ||
| 74 | 79 | ||
| 75 | Barcode({ | 80 | Barcode({ |
| 76 | this.corners, | 81 | this.corners, |
| 82 | + this.image, | ||
| 77 | this.format = BarcodeFormat.ean13, | 83 | this.format = BarcodeFormat.ean13, |
| 78 | this.rawBytes, | 84 | this.rawBytes, |
| 79 | this.type = BarcodeType.text, | 85 | this.type = BarcodeType.text, |
| @@ -91,7 +97,7 @@ class Barcode { | @@ -91,7 +97,7 @@ class Barcode { | ||
| 91 | }); | 97 | }); |
| 92 | 98 | ||
| 93 | /// Create a [Barcode] from native data. | 99 | /// Create a [Barcode] from native data. |
| 94 | - Barcode.fromNative(Map data) | 100 | + Barcode.fromNative(Map data, this.image) |
| 95 | : corners = toCorners(data['corners'] as List?), | 101 | : corners = toCorners(data['corners'] as List?), |
| 96 | format = toFormat(data['format'] as int), | 102 | format = toFormat(data['format'] as int), |
| 97 | rawBytes = data['rawBytes'] as Uint8List?, | 103 | rawBytes = data['rawBytes'] as Uint8List?, |
| 1 | @JS() | 1 | @JS() |
| 2 | library jsqr; | 2 | library jsqr; |
| 3 | 3 | ||
| 4 | +import 'dart:typed_data'; | ||
| 5 | + | ||
| 4 | import 'package:js/js.dart'; | 6 | import 'package:js/js.dart'; |
| 5 | 7 | ||
| 6 | @JS('jsQR') | 8 | @JS('jsQR') |
| @@ -9,4 +11,6 @@ external Code? jsQR(dynamic data, int? width, int? height); | @@ -9,4 +11,6 @@ external Code? jsQR(dynamic data, int? width, int? height); | ||
| 9 | @JS() | 11 | @JS() |
| 10 | class Code { | 12 | class Code { |
| 11 | external String get data; | 13 | external String get data; |
| 14 | + | ||
| 15 | + external Uint8ClampedList get binaryData; | ||
| 12 | } | 16 | } |
-
Please register or login to post a comment