diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..13426b4 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* scanBarcode method that opens a camera views and exits once an item has been scanned or the user disimisses the scanner. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4b97384 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Amol Gangadhare + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/android/.classpath b/android/.classpath new file mode 100644 index 0000000..eb19361 --- /dev/null +++ b/android/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..c6cbe56 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,8 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures diff --git a/android/.project b/android/.project new file mode 100644 index 0000000..61cbfaa --- /dev/null +++ b/android/.project @@ -0,0 +1,23 @@ + + + flutter_scandit + Project flutter_scandit created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000..1571ee1 --- /dev/null +++ b/android/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,13 @@ +arguments= +auto.sync=false +build.scans.enabled=false +connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(6.0-20191016123526+0000)) +connection.project.dir=../example/android +eclipse.preferences.version=1 +gradle.user.home= +java.home= +jvm.arguments= +offline.mode=false +override.workspace.settings=true +show.console.view=true +show.executions.view=true diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..4e19842 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,44 @@ +group 'za.co.palota.flutter_scandit' +version '1.0' + +buildscript { + repositories { + google() + jcenter() + maven { url 'https://scandit.bintray.com/DataCapture' } + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.2.1' + } +} + +rootProject.allprojects { + repositories { + google() + jcenter() + } +} + +apply plugin: 'com.android.library' + +android { + compileSdkVersion 28 + + defaultConfig { + minSdkVersion 19 + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + lintOptions { + disable 'InvalidPackage' + } + dependencies { + implementation "com.scandit.datacapture:core:6.1.0" + implementation "com.scandit.datacapture:barcode:6.1.0" + + implementation "androidx.appcompat:appcompat:1.0.2" + implementation "com.google.android.material:material:1.0.0" + + implementation "androidx.constraintlayout:constraintlayout:1.1.3" + } +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..2bd6f4f --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx1536M + diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..019065d --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..49438ec --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'flutter_scandit' diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000..2bd7b7d --- /dev/null +++ b/android/src/main/AndroidManifest.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/src/main/java/za/co/palota/flutter_scandit/BarcodeScanActivity.java b/android/src/main/java/za/co/palota/flutter_scandit/BarcodeScanActivity.java new file mode 100644 index 0000000..18aa20b --- /dev/null +++ b/android/src/main/java/za/co/palota/flutter_scandit/BarcodeScanActivity.java @@ -0,0 +1,216 @@ +package za.co.palota.flutter_scandit; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import com.scandit.datacapture.barcode.capture.*; +import com.scandit.datacapture.barcode.data.Barcode; +import com.scandit.datacapture.barcode.data.Symbology; +import com.scandit.datacapture.barcode.ui.overlay.BarcodeCaptureOverlay; +import com.scandit.datacapture.core.capture.DataCaptureContext; +import com.scandit.datacapture.core.data.FrameData; +import com.scandit.datacapture.core.source.Camera; +import com.scandit.datacapture.core.source.FrameSourceState; +import com.scandit.datacapture.core.ui.DataCaptureView; +import com.scandit.datacapture.core.ui.viewfinder.RectangularViewfinder; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; + +public class BarcodeScanActivity + extends CameraPermissionActivity implements BarcodeCaptureListener { + public static final String BARCODE_ERROR = "error"; + public static final String BARCODE_DATA = "data"; + public static final String BARCODE_SYMBOLOGY = "symbology"; + + private DataCaptureContext dataCaptureContext; + private BarcodeCapture barcodeCapture; + private Camera camera; + private DataCaptureView dataCaptureView; + + private AlertDialog dialog; + + private String licenseKey; + private HashSet symbologies; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Intent intent = getIntent(); + this.licenseKey = intent.getStringExtra(FlutterScanditPlugin.LICENSE_KEY); + ArrayList passedSymbologies = intent.getStringArrayListExtra(FlutterScanditPlugin.SYMBOLOGIES_KEY); + symbologies = new HashSet<>(); + + for(String symbologyName:passedSymbologies){ + Symbology symbology = FlutterScanditPlugin.convertToSymbology(symbologyName); + if(symbology != null){ + symbologies.add(symbology); + } + } + if(symbologies.isEmpty()){ + symbologies.add(Symbology.EAN13_UPCA); // default + } + + // Initialize and start the barcode recognition. + initializeAndStartBarcodeScanning(); + } + + private void finishWithError(String errorReason) { + Intent data = new Intent(); + data.putExtra(BARCODE_ERROR, errorReason); + setResult(Activity.RESULT_CANCELED, data); + finish(); + } + + private void initializeAndStartBarcodeScanning() { + // Create data capture context using your license key. + dataCaptureContext = DataCaptureContext.forLicenseKey(this.licenseKey); + + // Use the default camera and set it as the frame source of the context. + // The camera is off by default and must be turned on to start streaming frames to the data + // capture context for recognition. + // See resumeFrameSource and pauseFrameSource below. + camera = Camera.getDefaultCamera(); + if (camera != null) { + // Use the recommended camera settings for the BarcodeCapture mode. + camera.applySettings(BarcodeCapture.createRecommendedCameraSettings()); + dataCaptureContext.setFrameSource(camera); + } else { + finishWithError("NO_CAMERA"); + } + + // The barcode capturing process is configured through barcode capture settings + // which are then applied to the barcode capture instance that manages barcode recognition. + BarcodeCaptureSettings barcodeCaptureSettings = new BarcodeCaptureSettings(); + + // The settings instance initially has all types of barcodes (symbologies) disabled. + // For the purpose of this sample we enable a very generous set of symbologies. + // In your own app ensure that you only enable the symbologies that your app requires as + // every additional enabled symbology has an impact on processing times. + + barcodeCaptureSettings.enableSymbologies(this.symbologies); + + // Some linear/1d barcode symbologies allow you to encode variable-length data. + // By default, the Scandit Data Capture SDK only scans barcodes in a certain length range. + // If your application requires scanning of one of these symbologies, and the length is + // falling outside the default range, you may need to adjust the "active symbol counts" + // for this symbology. This is shown in the following few lines of code for one of the + // variable-length symbologies. + SymbologySettings symbologySettings = + barcodeCaptureSettings.getSymbologySettings(Symbology.CODE39); + + HashSet activeSymbolCounts = new HashSet<>( + Arrays.asList(new Short[] { 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 })); + + symbologySettings.setActiveSymbolCounts(activeSymbolCounts); + + // Create new barcode capture mode with the settings from above. + barcodeCapture = BarcodeCapture.forDataCaptureContext(dataCaptureContext, barcodeCaptureSettings); + + // Register self as a listener to get informed whenever a new barcode got recognized. + barcodeCapture.addListener(this); + + // To visualize the on-going barcode capturing process on screen, setup a data capture view + // that renders the camera preview. The view must be connected to the data capture context. + dataCaptureView = DataCaptureView.newInstance(this, dataCaptureContext); + + // Add a barcode capture overlay to the data capture view to render the location of captured + // barcodes on top of the video preview. + // This is optional, but recommended for better visual feedback. + BarcodeCaptureOverlay overlay = BarcodeCaptureOverlay.newInstance(barcodeCapture, dataCaptureView); + overlay.setViewfinder(new RectangularViewfinder()); + + setContentView(dataCaptureView); + } + + @Override + protected void onPause() { + pauseFrameSource(); + super.onPause(); + } + + @Override + protected void onDestroy() { + barcodeCapture.removeListener(this); + dataCaptureContext.removeMode(barcodeCapture); + super.onDestroy(); + } + + private void pauseFrameSource() { + // Switch camera off to stop streaming frames. + // The camera is stopped asynchronously and will take some time to completely turn off. + // Until it is completely stopped, it is still possible to receive further results, hence + // it's a good idea to first disable barcode capture as well. + barcodeCapture.setEnabled(false); + camera.switchToDesiredState(FrameSourceState.OFF, null); + } + + @Override + protected void onResume() { + super.onResume(); + + // Check for camera permission and request it, if it hasn't yet been granted. + // Once we have the permission the onCameraPermissionGranted() method will be called. + requestCameraPermission(); + } + + @Override + public void onCameraPermissionGranted() { + resumeFrameSource(); + } + + @Override + public void onCameraPermissionDenied() { + finishWithError("CAMERA_PERMISSION_DENIED"); + } + + private void resumeFrameSource() { + dismissScannedCodesDialog(); + + // Switch camera on to start streaming frames. + // The camera is started asynchronously and will take some time to completely turn on. + barcodeCapture.setEnabled(true); + camera.switchToDesiredState(FrameSourceState.ON, null); + } + + private void dismissScannedCodesDialog() { + if (dialog != null) { + dialog.dismiss(); + dialog = null; + } + } + + + @Override + public void onBarcodeScanned( + @NonNull BarcodeCapture barcodeCapture, + @NonNull BarcodeCaptureSession session, + @NonNull FrameData frameData + ) { + if (session.getNewlyRecognizedBarcodes().isEmpty()) return; + + Barcode barcode = session.getNewlyRecognizedBarcodes().get(0); + + + Intent data = new Intent(); + data.putExtra(BARCODE_DATA, barcode.getData()); + data.putExtra(BARCODE_SYMBOLOGY, barcode.getSymbology().name()); + setResult(Activity.RESULT_OK, data); + finish(); + } + + + @Override + public void onSessionUpdated(@NonNull BarcodeCapture barcodeCapture, + @NonNull BarcodeCaptureSession session, @NonNull FrameData data) {} + + @Override + public void onObservationStarted(@NonNull BarcodeCapture barcodeCapture) {} + + @Override + public void onObservationStopped(@NonNull BarcodeCapture barcodeCapture) {} +} \ No newline at end of file diff --git a/android/src/main/java/za/co/palota/flutter_scandit/CameraPermissionActivity.java b/android/src/main/java/za/co/palota/flutter_scandit/CameraPermissionActivity.java new file mode 100644 index 0000000..95d71f5 --- /dev/null +++ b/android/src/main/java/za/co/palota/flutter_scandit/CameraPermissionActivity.java @@ -0,0 +1,78 @@ +package za.co.palota.flutter_scandit; + +import android.Manifest; +import android.annotation.TargetApi; +import android.content.pm.PackageManager; +import android.os.Build; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; + +/** + * An activity to request the camera permission. + */ +public abstract class CameraPermissionActivity extends AppCompatActivity { + + private static final String CAMERA_PERMISSION = Manifest.permission.CAMERA; + private static final int CAMERA_PERMISSION_REQUEST = 0; + + private boolean permissionDeniedOnce = false; + private boolean paused = true; + + @Override + protected void onPause() { + super.onPause(); + + paused = true; + } + + @Override + protected void onResume() { + super.onResume(); + + paused = false; + } + + protected boolean hasCameraPermission() { + return (Build.VERSION.SDK_INT < Build.VERSION_CODES.M + || checkSelfPermission(CAMERA_PERMISSION) == PackageManager.PERMISSION_GRANTED); + } + + @TargetApi(Build.VERSION_CODES.M) + protected void requestCameraPermission() { + // For Android M and onwards we need to request the camera permission from the user. + if (!hasCameraPermission()) { + // The user already denied the permission once, we don't ask twice. + if (!permissionDeniedOnce) { + // It's clear why the camera is required. We don't need to give a detailed reason. + requestPermissions(new String[] { CAMERA_PERMISSION }, CAMERA_PERMISSION_REQUEST); + } + + } else { + // We already have the permission or don't need it. + onCameraPermissionGranted(); + } + } + + @Override + public void onRequestPermissionsResult( + int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if (requestCode == CAMERA_PERMISSION_REQUEST) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + permissionDeniedOnce = false; + if (!paused) { + // Only call the function if not paused - camera should not be used otherwise. + onCameraPermissionGranted(); + } + } else { + onCameraPermissionDenied(); + // The user denied the permission - we are not going to ask again. + permissionDeniedOnce = true; + } + } else { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + } + + public abstract void onCameraPermissionGranted(); + public abstract void onCameraPermissionDenied(); +} \ No newline at end of file diff --git a/android/src/main/java/za/co/palota/flutter_scandit/FlutterScanditPlugin.java b/android/src/main/java/za/co/palota/flutter_scandit/FlutterScanditPlugin.java new file mode 100644 index 0000000..420c7b6 --- /dev/null +++ b/android/src/main/java/za/co/palota/flutter_scandit/FlutterScanditPlugin.java @@ -0,0 +1,176 @@ +package za.co.palota.flutter_scandit; + +import android.app.Activity; +import android.content.Intent; +import android.util.Log; + +import com.scandit.datacapture.barcode.data.Symbology; + +import io.flutter.app.FlutterActivity; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.MethodChannel.MethodCallHandler; +import io.flutter.plugin.common.MethodChannel.Result; +import io.flutter.plugin.common.PluginRegistry.ActivityResultListener; +import io.flutter.plugin.common.PluginRegistry.Registrar; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** FlutterScanditPlugin */ +public class FlutterScanditPlugin implements MethodCallHandler, ActivityResultListener { + private static final String TAG = FlutterScanditPlugin.class.getSimpleName(); + private static final String PLUGIN_CHANNEL = "flutter_scandit"; + private static final int BARCODE_CAPTURE_CODE = 1111; + + public static final String LICENSE_KEY = "licenseKey"; + public static final String NO_LICENSE = "MISSING_LICENCE"; + + public static final String SYMBOLOGIES_KEY = "symbologies"; + + private static FlutterScanditPlugin instance; + private static Activity activity; + private static Result pendingResult; + + private final Registrar registrar; + + private FlutterScanditPlugin(FlutterActivity activity, final Registrar registrar) { + FlutterScanditPlugin.activity = activity; + this.registrar = registrar; + } + + /** Plugin registration. */ + public static void registerWith(Registrar registrar) { + final MethodChannel channel = new MethodChannel(registrar.messenger(), PLUGIN_CHANNEL); + instance = new FlutterScanditPlugin((FlutterActivity)registrar.activity(), registrar); + registrar.addActivityResultListener(instance); + channel.setMethodCallHandler(instance); + } + + @Override + public void onMethodCall(MethodCall call, Result result) { + pendingResult = result; + if(call.method.equals("scanBarcode")){ + Map args = (Map) call.arguments; + if(args.containsKey(LICENSE_KEY)) { + ArrayList passedSymbologies = (ArrayList)args.get(SYMBOLOGIES_KEY); + List symbologies = new ArrayList(); + for(String symbologyName:passedSymbologies){ + Symbology symbology = convertToSymbology(symbologyName); + if(symbology != null){ + symbologies.add(symbology); + } + } + if(symbologies.isEmpty()){ + symbologies.add(Symbology.EAN13_UPCA); // default + } + + startBarcodeScanner((String)args.get(LICENSE_KEY),passedSymbologies); + } else { + result.error(NO_LICENSE,null,null); + } + } + else { + result.notImplemented(); + } + } + + @Override + public boolean onActivityResult(int requestCode, int resultCode, Intent data) { + if(requestCode == BARCODE_CAPTURE_CODE) { + if(resultCode == Activity.RESULT_OK){ + try{ + String barcode = data.getStringExtra(BarcodeScanActivity.BARCODE_DATA); + String symbology = data.getStringExtra(BarcodeScanActivity.BARCODE_SYMBOLOGY); + Map result = new HashMap(); + result.put("data",barcode); + result.put("symbology",symbology); + pendingResult.success(result); + } catch(Exception e) { + pendingResult.error(e.toString(),null,null); + } + } else if(resultCode == Activity.RESULT_CANCELED){ + pendingResult.success(new HashMap()); + } + else if(data != null) { + String errorCode = data.getStringExtra(BarcodeScanActivity.BARCODE_ERROR); + pendingResult.error(errorCode,null,null); + } else { + pendingResult.error("UNKNOWN_ERROR",null,null); + } + } + return false; + } + + private void startBarcodeScanner(String licenseKey, ArrayList symbologies) { + try { + Intent intent = new Intent(activity, BarcodeScanActivity.class); + intent.putExtra(LICENSE_KEY,licenseKey); + intent.putStringArrayListExtra(SYMBOLOGIES_KEY,symbologies); + activity.startActivityForResult(intent, BARCODE_CAPTURE_CODE); + } catch (Exception e) { + Log.e(TAG, "startView: " + e.getLocalizedMessage()); + } + } + + public static Symbology convertToSymbology(String name){ + switch (name){ + case "EAN13_UPCA": + return Symbology.EAN13_UPCA; + case "UPCE": + return Symbology.UPCE; + case "EAN8": + return Symbology.EAN8; + case "CODE39": + return Symbology.CODE39; + case "CODE128": + return Symbology.CODE128; + case "CODE11": + return Symbology.CODE11; + case "CODE25": + return Symbology.CODE25; + case "CODABAR": + return Symbology.CODABAR; + case "INTERLEAVED_TWO_OF_FIVE": + return Symbology.INTERLEAVED_TWO_OF_FIVE; + case "MSI_PLESSEY": + return Symbology.MSI_PLESSEY; + case "QR": + return Symbology.QR; + case "DATA_MATRIX": + return Symbology.DATA_MATRIX; + case "AZTEC": + return Symbology.AZTEC; + case "MAXI_CODE": + return Symbology.MAXI_CODE; + case "DOT_CODE": + return Symbology.DOT_CODE; + case "KIX": + return Symbology.KIX; + case "RM4SCC": + return Symbology.RM4SCC; + case "GS1_DATABAR": + return Symbology.GS1_DATABAR; + case "GS1_DATABAR_EXPANDED": + return Symbology.GS1_DATABAR_EXPANDED; + case "GS1_DATABAR_LIMITED": + return Symbology.GS1_DATABAR_LIMITED; + case "PDF417": + return Symbology.PDF417; + case "MICRO_PDF417": + return Symbology.MICRO_PDF417; + case "MICRO_QR": + return Symbology.MICRO_QR; + case "CODE32": + return Symbology.CODE32; + case "LAPA4SC": + return Symbology.LAPA4SC; + default: + return null; + } + } +} diff --git a/assets/close.png b/assets/close.png new file mode 100644 index 0000000..44ea6ae Binary files /dev/null and b/assets/close.png differ diff --git a/example/.gitignore b/example/.gitignore new file mode 100644 index 0000000..2ddde2a --- /dev/null +++ b/example/.gitignore @@ -0,0 +1,73 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.packages +.pub-cache/ +.pub/ +/build/ + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/example/.metadata b/example/.metadata new file mode 100644 index 0000000..fea404f --- /dev/null +++ b/example/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 68587a0916366e9512a78df22c44163d041dd5f3 + channel: stable + +project_type: app diff --git a/example/README.md b/example/README.md new file mode 100644 index 0000000..b4b881b --- /dev/null +++ b/example/README.md @@ -0,0 +1,16 @@ +# flutter_scandit_example + +Demonstrates how to use the flutter_scandit plugin. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/example/android/.project b/example/android/.project new file mode 100644 index 0000000..3964dd3 --- /dev/null +++ b/example/android/.project @@ -0,0 +1,17 @@ + + + android + Project android created by Buildship. + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/example/android/.settings/org.eclipse.buildship.core.prefs b/example/android/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000..e889521 --- /dev/null +++ b/example/android/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir= +eclipse.preferences.version=1 diff --git a/example/android/app/.classpath b/example/android/app/.classpath new file mode 100644 index 0000000..eb19361 --- /dev/null +++ b/example/android/app/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/example/android/app/.project b/example/android/app/.project new file mode 100644 index 0000000..ac485d7 --- /dev/null +++ b/example/android/app/.project @@ -0,0 +1,23 @@ + + + app + Project app created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/example/android/app/.settings/org.eclipse.buildship.core.prefs b/example/android/app/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000..b1886ad --- /dev/null +++ b/example/android/app/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir=.. +eclipse.preferences.version=1 diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle new file mode 100644 index 0000000..0bbc68b --- /dev/null +++ b/example/android/app/build.gradle @@ -0,0 +1,61 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 28 + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "za.co.palota.flutter_scandit" + minSdkVersion 19 + targetSdkVersion 28 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + + 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 + } + } +} + +flutter { + source '../..' +} + +dependencies { + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' +} diff --git a/example/android/app/release/app-release.apk b/example/android/app/release/app-release.apk new file mode 100644 index 0000000..368a137 Binary files /dev/null and b/example/android/app/release/app-release.apk differ diff --git a/example/android/app/release/output.json b/example/android/app/release/output.json new file mode 100644 index 0000000..9f0c959 --- /dev/null +++ b/example/android/app/release/output.json @@ -0,0 +1 @@ +[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] \ No newline at end of file diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..cd821b7 --- /dev/null +++ b/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..d7f39ef --- /dev/null +++ b/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + diff --git a/example/android/app/src/main/java/za/co/palota/flutter_scandit_example/MainActivity.java b/example/android/app/src/main/java/za/co/palota/flutter_scandit_example/MainActivity.java new file mode 100644 index 0000000..232e08b --- /dev/null +++ b/example/android/app/src/main/java/za/co/palota/flutter_scandit_example/MainActivity.java @@ -0,0 +1,13 @@ +package za.co.palota.flutter_scandit_example; + +import android.os.Bundle; +import io.flutter.app.FlutterActivity; +import io.flutter.plugins.GeneratedPluginRegistrant; + +public class MainActivity extends FlutterActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + GeneratedPluginRegistrant.registerWith(this); + } +} diff --git a/example/android/app/src/main/res/drawable/launch_background.xml b/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..db77bb4 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..17987b7 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..09d4391 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..d5f1c8d Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..4d6372e Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..00fa441 --- /dev/null +++ b/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..cd821b7 --- /dev/null +++ b/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/example/android/build.gradle b/example/android/build.gradle new file mode 100644 index 0000000..bb8a303 --- /dev/null +++ b/example/android/build.gradle @@ -0,0 +1,29 @@ +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.2.1' + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/example/android/gradle.properties b/example/android/gradle.properties new file mode 100644 index 0000000..2bd6f4f --- /dev/null +++ b/example/android/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx1536M + diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..2819f02 --- /dev/null +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip diff --git a/example/android/settings.gradle b/example/android/settings.gradle new file mode 100644 index 0000000..5a2f14f --- /dev/null +++ b/example/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..6b4c0f7 --- /dev/null +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..e8efba1 --- /dev/null +++ b/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..399e934 --- /dev/null +++ b/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/example/ios/Podfile b/example/ios/Podfile new file mode 100644 index 0000000..e9286cb --- /dev/null +++ b/example/ios/Podfile @@ -0,0 +1,74 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# 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 []; + 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 +end + +target 'Runner' do + use_frameworks! + + # 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 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 pub 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 + } + + # 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') + } +end + +# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system. +install! 'cocoapods', :disable_input_output_paths => true + +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['ENABLE_BITCODE'] = 'NO' + end + end +end diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock new file mode 100644 index 0000000..6c135d8 --- /dev/null +++ b/example/ios/Podfile.lock @@ -0,0 +1,33 @@ +PODS: + - Flutter (1.0.0) + - flutter_scandit (0.0.1): + - Flutter + - ScanditBarcodeCapture (~> 6.1) + - ScanditBarcodeCapture (6.1.0): + - ScanditCaptureCore (= 6.1.0) + - ScanditCaptureCore (6.1.0) + +DEPENDENCIES: + - Flutter (from `.symlinks/flutter/ios-release`) + - flutter_scandit (from `.symlinks/plugins/flutter_scandit/ios`) + +SPEC REPOS: + trunk: + - ScanditBarcodeCapture + - ScanditCaptureCore + +EXTERNAL SOURCES: + Flutter: + :path: ".symlinks/flutter/ios-release" + flutter_scandit: + :path: ".symlinks/plugins/flutter_scandit/ios" + +SPEC CHECKSUMS: + Flutter: 0e3d915762c693b495b44d77113d4970485de6ec + flutter_scandit: 9506d411cd63c3c804ef34556b47d9372968c09e + ScanditBarcodeCapture: af76f1775b760e99d6ceb4f05336adea50ea91b1 + ScanditCaptureCore: 344dbe643f1074eca1b111c6b06a9bb2a2f1d3a4 + +PODFILE CHECKSUM: b6a0a141693093b304368d08511b46cf3d1d0ac5 + +COCOAPODS: 1.8.4 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..80a029c --- /dev/null +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,599 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* 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, ); }; }; + 6D9529876EA741B8619231FD /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0828CC3349F9C6ABAF8E0BBF /* 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, ); }; }; + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; + 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 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0828CC3349F9C6ABAF8E0BBF /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 862F872BD4CAB6B18B5B39DB /* 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 = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; + 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 = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + C85470D5CFEBBE8755FECB3B /* 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 = ""; }; + E913A334AF2F25B120B4F0D1 /* 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 = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, + 6D9529876EA741B8619231FD /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3F5371A036A61127340F25BE /* Pods */ = { + isa = PBXGroup; + children = ( + 862F872BD4CAB6B18B5B39DB /* Pods-Runner.debug.xcconfig */, + C85470D5CFEBBE8755FECB3B /* Pods-Runner.release.xcconfig */, + E913A334AF2F25B120B4F0D1 /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B80C3931E831B6300D905FE /* App.framework */, + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEBA1CF902C7004384FC /* Flutter.framework */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 3F5371A036A61127340F25BE /* Pods */, + C4A76C4BF3C6626A2F35067C /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + C4A76C4BF3C6626A2F35067C /* Frameworks */ = { + isa = PBXGroup; + children = ( + 0828CC3349F9C6ABAF8E0BBF /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + B6472D5026C1802E6525D296 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 88E1CD86AC8549BF905450C3 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 0910; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + }; + 88E1CD86AC8549BF905450C3 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + B6472D5026C1802E6525D296 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + 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"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = "za.co.palota.flutter-scandit"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 4.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = "za.co.palota.flutter-scandit"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = "za.co.palota.flutter-scandit"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 4.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..c537502 --- /dev/null +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..21a3cc1 --- /dev/null +++ b/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000..dc9ada4 Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000..28c6bf0 Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000..2ccbfd9 Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000..f091b6b Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000..4cde121 Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000..d0ef06e Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000..dcdc230 Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000..2ccbfd9 Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000..c8f9ed8 Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000..a6d6b86 Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000..a6d6b86 Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000..75b2d16 Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000..c4df70d Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000..6a84f41 Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000..d0e1f58 Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..0bedcf2 --- /dev/null +++ b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ios/Runner/Base.lproj/Main.storyboard b/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist new file mode 100644 index 0000000..0fa0037 --- /dev/null +++ b/example/ios/Runner/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + flutter_scandit_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + NSCameraUsageDescription + Camera permission is required. + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/example/ios/Runner/Runner-Bridging-Header.h b/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..7335fdf --- /dev/null +++ b/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" \ No newline at end of file diff --git a/example/lib/main.dart b/example/lib/main.dart new file mode 100644 index 0000000..f10784a --- /dev/null +++ b/example/lib/main.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter_scandit/flutter_scandit.dart'; + +void main() => runApp(MyApp()); + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State { + BarcodeResult barcode; + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Flutter Scandit example app'), + ), + body: Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + RaisedButton( + onPressed: () async { + var result = await FlutterScandit(symbologies: [ + Symbology.EAN13_UPCA, + Symbology.CODE128 + ], licenseKey: "-- ENTER YOUR SCANDIT LICENSE KEY HERE -") + .scanBarcode(); + setState(() { + barcode = result; + }); + }, + child: Text('SCAN'), + ), + SizedBox( + height: 32, + ), + barcode != null + ? Text('${barcode.data} ${barcode.symbology}') + : Text('please scan a barcode...'), + ], + ), + ), + ), + ); + } +} diff --git a/example/pubspec.lock b/example/pubspec.lock new file mode 100644 index 0000000..ee1a83d --- /dev/null +++ b/example/pubspec.lock @@ -0,0 +1,153 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.14.11" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.2" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_scandit: + dependency: "direct dev" + description: + path: ".." + relative: true + source: path + version: "0.0.1" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.5" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.7" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.4" + pedantic: + dependency: transitive + description: + name: pedantic + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0+1" + quiver: + dependency: transitive + description: + name: quiver + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.5" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.9.3" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.5" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.6" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" +sdks: + dart: ">=2.2.2 <3.0.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml new file mode 100644 index 0000000..6b97650 --- /dev/null +++ b/example/pubspec.yaml @@ -0,0 +1,63 @@ +name: flutter_scandit_example +description: Demonstrates how to use the flutter_scandit plugin. +publish_to: 'none' + +environment: + sdk: ">=2.1.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^0.1.2 + +dev_dependencies: + flutter_test: + sdk: flutter + + flutter_scandit: + path: ../ + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart new file mode 100644 index 0000000..ecd69c8 --- /dev/null +++ b/example/test/widget_test.dart @@ -0,0 +1,27 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:flutter_scandit_example/main.dart'; + +void main() { + testWidgets('Verify Platform version', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MyApp()); + + // Verify that platform version is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => widget is Text && + widget.data.startsWith('Running on:'), + ), + findsOneWidget, + ); + }); +} diff --git a/flutter_scandit.iml b/flutter_scandit.iml new file mode 100644 index 0000000..429df7d --- /dev/null +++ b/flutter_scandit.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..aa479fd --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,37 @@ +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +.DS_Store +*.swp +profile + +DerivedData/ +build/ +GeneratedPluginRegistrant.h +GeneratedPluginRegistrant.m + +.generated/ + +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + +xcuserdata + +*.moved-aside + +*.pyc +*sync/ +Icon? +.tags* + +/Flutter/Generated.xcconfig +/Flutter/flutter_export_environment.sh \ No newline at end of file diff --git a/ios/Assets/.gitkeep b/ios/Assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/ios/Classes/BarcodeScannerViewController.swift b/ios/Classes/BarcodeScannerViewController.swift new file mode 100644 index 0000000..f671501 --- /dev/null +++ b/ios/Classes/BarcodeScannerViewController.swift @@ -0,0 +1,176 @@ +// +// BarcodeScannerViewController.swift +// flutter_scandit +// +// Created by Kholofelo Moyaba on 2019/11/23. +// + +import ScanditBarcodeCapture + + +protocol BarcodeScannerDelegate: class { + func didScanBarcodeWithResult(data: String, symbology: String) + func didCancel() + func didFailWithErrorCode(code: String) +} + + +extension DataCaptureContext { + // Get a licensed DataCaptureContext. + static func licensed(licenseKey: String) -> DataCaptureContext { + return DataCaptureContext(licenseKey: licenseKey) + } +} + +class BarcodeScannerViewController: UIViewController { + weak var delegate: BarcodeScannerDelegate? + private var licenseKey: String! + private var symbologies: [Symbology]! + private var context: DataCaptureContext! + private var camera: Camera? + private var barcodeCapture: BarcodeCapture! + private var captureView: DataCaptureView! + private var overlay: BarcodeCaptureOverlay! + + var closeImage: UIImage? + + private var backButton: UIButton = UIButton(type: .custom) + + + init(with licenseKey: String, symbologies: [Symbology]) { + self.licenseKey = licenseKey + self.symbologies = symbologies + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + self.licenseKey = "" + self.symbologies = [] + } + + override func viewDidLoad() { + super.viewDidLoad() + setupRecognition() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + configureNavigationBar() + + // Switch camera on to start streaming frames. The camera is started asynchronously and will take some time to + // completely turn on. + barcodeCapture.isEnabled = true + camera?.switch(toDesiredState: .on) + } + + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + + // Switch camera off to stop streaming frames. The camera is stopped asynchronously and will take some time to + // completely turn off. Until it is completely stopped, it is still possible to receive further results, hence + // it's a good idea to first disable barcode capture as well. + barcodeCapture.isEnabled = false + camera?.switch(toDesiredState: .off) + } + + func configureNavigationBar() { + backButton.setTitle("", for: .normal) + backButton.setTitleColor(.white, for: .normal) + backButton.setImage(closeImage, for: .normal) + backButton.imageEdgeInsets = UIEdgeInsetsMake(4,4,4,4) + backButton.tintColor = .white + backButton.imageView?.contentMode = .scaleAspectFit + backButton.addTarget(self, action: #selector(backAction), for: .touchUpInside) + self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton) + self.navigationController?.navigationBar.barTintColor = UIColor.clear + self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) + self.navigationController?.navigationBar.shadowImage = UIImage() + self.navigationController?.navigationBar.isTranslucent = true + } + + @objc func backAction() -> Void { + delegate?.didCancel() + self.dismiss(animated: true, completion: nil) + } + + func setupRecognition() { + // Create data capture context using your license key. + context = DataCaptureContext.licensed(licenseKey: licenseKey) + + // Use the world-facing (back) camera and set it as the frame source of the context. The camera is off by + // default and must be turned on to start streaming frames to the data capture context for recognition. + // See viewWillAppear and viewDidDisappear above. + camera = Camera.default + context.setFrameSource(camera, completionHandler: nil) + + // Use the recommended camera settings for the BarcodeCapture mode. + let recommenededCameraSettings = BarcodeCapture.recommendedCameraSettings + camera?.apply(recommenededCameraSettings) + + // The barcode capturing process is configured through barcode capture settings + // and are then applied to the barcode capture instance that manages barcode recognition. + let settings = BarcodeCaptureSettings() + + // The settings instance initially has all types of barcodes (symbologies) disabled. For the purpose of this + // sample we enable a very generous set of symbologies. In your own app ensure that you only enable the + // symbologies that your app requires as every additional enabled symbology has an impact on processing times. + for symbology in self.symbologies { + settings.set(symbology: symbology, enabled: true) + } + + // Some linear/1d barcode symbologies allow you to encode variable-length data. By default, the Scandit + // Data Capture SDK only scans barcodes in a certain length range. If your application requires scanning of one + // of these symbologies, and the length is falling outside the default range, you may need to adjust the "active + // symbol counts" for this symbology. This is shown in the following few lines of code for one of the + // variable-length symbologies. + let symbologySettings = settings.settings(for: .code39) + symbologySettings.activeSymbolCounts = Set(7...20) as Set + + // Create new barcode capture mode with the settings from above. + barcodeCapture = BarcodeCapture(context: context, settings: settings) + + // Register self as a listener to get informed whenever a new barcode got recognized. + barcodeCapture.addListener(self) + + // To visualize the on-going barcode capturing process on screen, setup a data capture view that renders the + // camera preview. The view must be connected to the data capture context. + captureView = DataCaptureView(context: context, frame: view.bounds) + captureView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + view.addSubview(captureView) + + // Add a barcode capture overlay to the data capture view to render the location of captured barcodes on top of + // the video preview. This is optional, but recommended for better visual feedback. + overlay = BarcodeCaptureOverlay(barcodeCapture: barcodeCapture) + overlay.viewfinder = RectangularViewfinder() + captureView.addOverlay(overlay) + } +} + +// MARK: - BarcodeCaptureListener +extension BarcodeScannerViewController: BarcodeCaptureListener { + + func barcodeCapture(_ barcodeCapture: BarcodeCapture, + didScanIn session: BarcodeCaptureSession, + frameData: FrameData) { + guard let barcode = session.newlyRecognizedBarcodes.first else { + return + } + + // Stop recognizing barcodes for as long as we are displaying the result. There won't be any new results until + // the capture mode is enabled again. Note that disabling the capture mode does not stop the camera, the camera + // continues to stream frames until it is turned off. + barcodeCapture.isEnabled = false + + // If you are not disabling barcode capture here and want to continue scanning, consider setting the + // codeDuplicateFilter when creating the barcode capture settings to around 500 or even -1 if you do not want + // codes to be scanned more than once. + // Get the human readable name of the symbology and assemble the result to be shown. + guard let barcodeData = barcode.data else {return} + let symbology = SymbologyDescription(symbology: barcode.symbology).identifier + + delegate?.didScanBarcodeWithResult(data: barcodeData, symbology: symbology) + self.dismiss(animated: true, completion: nil) + } + +} diff --git a/ios/Classes/FlutterScanditPlugin.h b/ios/Classes/FlutterScanditPlugin.h new file mode 100644 index 0000000..40505f6 --- /dev/null +++ b/ios/Classes/FlutterScanditPlugin.h @@ -0,0 +1,4 @@ +#import + +@interface FlutterScanditPlugin : NSObject +@end diff --git a/ios/Classes/FlutterScanditPlugin.m b/ios/Classes/FlutterScanditPlugin.m new file mode 100644 index 0000000..61b9b18 --- /dev/null +++ b/ios/Classes/FlutterScanditPlugin.m @@ -0,0 +1,8 @@ +#import "FlutterScanditPlugin.h" +#import + +@implementation FlutterScanditPlugin ++ (void)registerWithRegistrar:(NSObject*)registrar { + [SwiftFlutterScanditPlugin registerWithRegistrar:registrar]; +} +@end diff --git a/ios/Classes/SwiftFlutterScanditPlugin.swift b/ios/Classes/SwiftFlutterScanditPlugin.swift new file mode 100644 index 0000000..8325a23 --- /dev/null +++ b/ios/Classes/SwiftFlutterScanditPlugin.swift @@ -0,0 +1,142 @@ +import Flutter +import UIKit +import ScanditCaptureCore +import ScanditBarcodeCapture + +public class SwiftFlutterScanditPlugin: NSObject, FlutterPlugin { + private static var LICENSE_KEY = "licenseKey" + private static var NO_LICENSE = "MISSING_LICENCE" + + private static var SYMBOLOGIES_KEY = "symbologies" + + var registrar: FlutterPluginRegistrar! + + var result: FlutterResult? + var hostViewController: UIViewController! + + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "flutter_scandit", binaryMessenger: registrar.messenger()) + let instance = SwiftFlutterScanditPlugin() + registrar.addMethodCallDelegate(instance, channel: channel) + if let delegate = UIApplication.shared.delegate , let window = delegate.window, let root = window?.rootViewController { + instance.hostViewController = root + instance.registrar = registrar + } + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + if (call.method == "scanBarcode") { + if let args = call.arguments as? NSDictionary { + if(args[SwiftFlutterScanditPlugin.LICENSE_KEY] != nil){ + var symbologies = [Symbology]() + if let passedSymbologies = args[SwiftFlutterScanditPlugin.SYMBOLOGIES_KEY] as? [String] { + symbologies = passedSymbologies.map {convertToSymbology(name: $0)}.filter{$0 != nil}.map{$0!} + } else { + symbologies = [.ean13UPCA] // default + } + + self.result = result + let viewController: BarcodeScannerViewController = BarcodeScannerViewController(with: (args[SwiftFlutterScanditPlugin.LICENSE_KEY]! as? String)!,symbologies: symbologies) + viewController.delegate = self + let navigationController = UINavigationController(rootViewController: viewController) + if hostViewController != nil { + let closeIconKey = registrar.lookupKey(forAsset: "assets/close.png", fromPackage: "flutter_scandit") + if let closeIconPath = Bundle.main.path(forResource: closeIconKey, ofType: nil) { + viewController.closeImage = UIImage(contentsOfFile: closeIconPath) + } + hostViewController.present(navigationController, animated: true, completion: nil) + } + } else { + result(SwiftFlutterScanditPlugin.NO_LICENSE) + } + } else { + result(SwiftFlutterScanditPlugin.NO_LICENSE) + } + + } + else { + result(FlutterMethodNotImplemented) + } + + } + + private func convertToSymbology(name: String) -> Symbology? { + switch name { + case "EAN13_UPCA": + return .ean13UPCA + case "UPCE": + return .upce + case "EAN8": + return .ean8 + case "CODE39": + return .code39 + case "CODE128": + return .code128 + case "CODE11": + return .code11 + case "CODE25": + return .code25 + case "CODABAR": + return .codabar + case "INTERLEAVED_TWO_OF_FIVE": + return .interleavedTwoOfFive + case "MSI_PLESSEY": + return .msiPlessey + case "QR": + return .qr + case "DATA_MATRIX": + return .dataMatrix + case "AZTEC": + return .aztec + case "MAXI_CODE": + return .maxiCode + case "DOT_CODE": + return .dotCode + case "KIX": + return .kix + case "RM4SCC": + return .rm4scc + case "GS1_DATABAR": + return .gs1Databar + case "GS1_DATABAR_EXPANDED": + return .gs1DatabarExpanded + case "GS1_DATABAR_LIMITED": + return .gs1DatabarLimited + case "PDF417": + return .pdf417 + case "MICRO_PDF417": + return .microPDF417 + case "MICRO_QR": + return .microQR + case "CODE32": + return .code32 + case "LAPA4SC": + return .lapa4SC + default: + return nil + } + } + +} + + + +extension SwiftFlutterScanditPlugin: BarcodeScannerDelegate { + func didScanBarcodeWithResult(data: String, symbology: String) { + if let channelResult = result { + channelResult(["data": data,"symbology": symbology]) + } + } + + func didCancel() { + if let channelResult = result { + channelResult([String: String]()) + } + } + + func didFailWithErrorCode(code: String) { + if let channelResult = result { + channelResult(code as NSString) + } + } +} diff --git a/ios/flutter_scandit.podspec b/ios/flutter_scandit.podspec new file mode 100644 index 0000000..9651231 --- /dev/null +++ b/ios/flutter_scandit.podspec @@ -0,0 +1,22 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'flutter_scandit' + s.version = '0.0.1' + s.summary = 'Flutter Scandit plugin.' + s.description = <<-DESC +A new flutter plugin project. + DESC + s.homepage = 'http://example.com' + s.license = { :file => '../LICENSE' } + s.author = { 'Your Company' => 'email@example.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.public_header_files = 'Classes/**/*.h' + s.dependency 'Flutter' + s.dependency 'ScanditBarcodeCapture', '~> 6.1' + + s.ios.deployment_target = '9.0' +end + diff --git a/lib/flutter_scandit.dart b/lib/flutter_scandit.dart new file mode 100644 index 0000000..8e0cf75 --- /dev/null +++ b/lib/flutter_scandit.dart @@ -0,0 +1,124 @@ +import 'dart:async'; +import 'package:meta/meta.dart'; + +import 'package:flutter/services.dart'; + +class FlutterScandit { + static const MethodChannel _channel = const MethodChannel('flutter_scandit'); + + final String licenseKey; + final List symbologies; + + static const List defaultSymbologoes = [Symbology.EAN13_UPCA]; + + FlutterScandit({@required this.licenseKey, this.symbologies = defaultSymbologoes}); + + Future scanBarcode() async { + Map arguments = { + "licenseKey": licenseKey, + "symbologies": symbologies.map(_getSymbologyString).toList() + }; + + var result = await _channel.invokeMethod('scanBarcode',arguments); + print(result); + final Map barcode = Map.from(result); + + return BarcodeResult( + data: barcode["data"], symbology: barcode["symbology"]); + } + + static String _getSymbologyString(Symbology symbology) { + switch (symbology) { + case Symbology.EAN13_UPCA: + return "EAN13_UPCA"; + case Symbology.UPCE: + return "UPCE"; + case Symbology.EAN8: + return "EAN8"; + case Symbology.CODE39: + return "CODE39"; + case Symbology.CODE93: + return "CODE93"; + case Symbology.CODE128: + return "CODE128"; + case Symbology.CODE11: + return "CODE11"; + case Symbology.CODE25: + return "CODE25"; + case Symbology.CODABAR: + return "CODABAR"; + case Symbology.INTERLEAVED_TWO_OF_FIVE: + return "INTERLEAVED_TWO_OF_FIVE"; + case Symbology.MSI_PLESSEY: + return "MSI_PLESSEY"; + case Symbology.QR: + return "QR"; + case Symbology.DATA_MATRIX: + return "DATA_MATRIX"; + case Symbology.AZTEC: + return "AZTEC"; + case Symbology.MAXI_CODE: + return "MAXI_CODE"; + case Symbology.DOT_CODE: + return "DOT_CODE"; + case Symbology.KIX: + return "KIX"; + case Symbology.RM4SCC: + return "RM4SCC"; + case Symbology.GS1_DATABAR: + return "GS1_DATABAR"; + case Symbology.GS1_DATABAR_EXPANDED: + return "GS1_DATABAR_EXPANDED"; + case Symbology.GS1_DATABAR_LIMITED: + return "GS1_DATABAR_LIMITED"; + case Symbology.PDF417: + return "PDF417"; + case Symbology.MICRO_PDF417: + return "MICRO_PDF417"; + case Symbology.MICRO_QR: + return "MICRO_QR"; + case Symbology.CODE32: + return "CODE32"; + case Symbology.LAPA4SC: + return "LAPA4SC"; + default: + return symbology.toString(); + } + } +} + +class BarcodeResult { + final String data; + final String symbology; + + BarcodeResult({this.data, this.symbology}); +} + +enum Symbology { + EAN13_UPCA, + UPCE, + EAN8, + CODE39, + CODE93, + CODE128, + CODE11, + CODE25, + CODABAR, + INTERLEAVED_TWO_OF_FIVE, + MSI_PLESSEY, + QR, + DATA_MATRIX, + AZTEC, + MAXI_CODE, + DOT_CODE, + KIX, + RM4SCC, + GS1_DATABAR, + GS1_DATABAR_EXPANDED, + GS1_DATABAR_LIMITED, + PDF417, + MICRO_PDF417, + MICRO_QR, + CODE32, + LAPA4SC, +} diff --git a/test/flutter_scandit_test.dart b/test/flutter_scandit_test.dart new file mode 100644 index 0000000..239bd6f --- /dev/null +++ b/test/flutter_scandit_test.dart @@ -0,0 +1,23 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_scandit/flutter_scandit.dart'; + +void main() { + const MethodChannel channel = MethodChannel('flutter_scandit'); + final FlutterScandit plugin = FlutterScandit(licenseKey: "123", symbologies: [Symbology.EAN13_UPCA]); + + setUp(() { + + channel.setMockMethodCallHandler((MethodCall methodCall) async { + return '42'; + }); + }); + + tearDown(() { + channel.setMockMethodCallHandler(null); + }); + + test('scanBarcode', () async { + expect(await plugin.scanBarcode(), '42'); + }); +}