nativescript-barcodescanner
Advanced tools
Comparing version 1.4.1 to 2.0.0
@@ -1,183 +0,182 @@ | ||
var barcodescanner = require("./barcodescanner-common"); | ||
"use strict"; | ||
var appModule = require("application"); | ||
var camModule = require("camera"); | ||
var camera = require("camera"); | ||
var utils = require("utils/utils"); | ||
var SCANNER_REQUEST_CODE = 444; | ||
var CAMERA_PERMISSION_REQUEST_CODE = 555; | ||
var broadcastManager; | ||
barcodescanner.rememberedContext = null; | ||
barcodescanner._cameraPermissionGranted = function () { | ||
var hasPermission = android.os.Build.VERSION.SDK_INT < 23; // Android M. (6.0) | ||
if (!hasPermission) { | ||
hasPermission = android.content.pm.PackageManager.PERMISSION_GRANTED == | ||
android.support.v4.content.ContextCompat.checkSelfPermission(appModule.android.currentContext, android.Manifest.permission.CAMERA); | ||
} | ||
return hasPermission; | ||
}; | ||
barcodescanner.available = function () { | ||
return new Promise(function (resolve, reject) { | ||
try { | ||
resolve(camModule.isAvailable()); | ||
} catch (ex) { | ||
console.log("Error in barcodescanner.available: " + ex); | ||
// let's just assume it's ok | ||
resolve(true); | ||
var BarcodeScanner = (function () { | ||
function BarcodeScanner() { | ||
this.broadcastManager = null; | ||
this.rememberedContext = null; | ||
this._cameraPermissionGranted = function () { | ||
var hasPermission = android.os.Build.VERSION.SDK_INT < 23; | ||
if (!hasPermission) { | ||
hasPermission = android.content.pm.PackageManager.PERMISSION_GRANTED === | ||
android.support.v4.content.ContextCompat.checkSelfPermission(utils.ad.getApplicationContext(), android.Manifest.permission.CAMERA); | ||
} | ||
return hasPermission; | ||
}; | ||
this._requestCameraPermission = function (onPermissionGranted, reject) { | ||
this._onPermissionGranted = onPermissionGranted; | ||
this._reject = reject; | ||
android.support.v4.app.ActivityCompat.requestPermissions(appModule.android.currentContext, [android.Manifest.permission.CAMERA], 234); | ||
}; | ||
var self = this; | ||
appModule.android.on(appModule.AndroidApplication.activityRequestPermissionsEvent, function (args) { | ||
for (var i = 0; i < args.permissions.length; i++) { | ||
if (args.grantResults[i] === android.content.pm.PackageManager.PERMISSION_DENIED) { | ||
self._reject("Please allow access to the Camera and try again."); | ||
return; | ||
} | ||
} | ||
if (self._onPermissionGranted) { | ||
self._onPermissionGranted(); | ||
} | ||
else { | ||
console.log("No after-permission callback function specified for requestCode " + args.requestCode + ". That's a bug in the nativescript-barcodescanner plugin, please report it!"); | ||
} | ||
}); | ||
} | ||
}); | ||
}; | ||
barcodescanner.hasCameraPermission = function () { | ||
return new Promise(function (resolve) { | ||
resolve(barcodescanner._cameraPermissionGranted()); | ||
}); | ||
}; | ||
barcodescanner.requestCameraPermission = function () { | ||
return new Promise(function (resolve) { | ||
if (!barcodescanner._cameraPermissionGranted()) { | ||
// in a future version we could hook up the callback and change this flow a bit | ||
android.support.v4.app.ActivityCompat.requestPermissions( | ||
appModule.android.currentContext, | ||
[android.Manifest.permission.CAMERA], | ||
CAMERA_PERMISSION_REQUEST_CODE); | ||
// this is not the nicest solution as the user needs to initiate scanning again after granting permission, | ||
// so enhance this in a future version, but it's ok for now | ||
resolve(); | ||
} | ||
}); | ||
}; | ||
barcodescanner.scan = function(arg) { | ||
return new Promise(function (resolve, reject) { | ||
try { | ||
if (!barcodescanner._cameraPermissionGranted()) { | ||
barcodescanner.requestCameraPermission(); | ||
reject("Permission needed"); | ||
return; | ||
} | ||
// the intent name should match the filter name in AndroidManifest.xml, don't change it | ||
var intent = new android.content.Intent("com.google.zxing.client.android.SCAN"); | ||
// limit searching for a valid Intent to this package only | ||
intent.setPackage(appModule.android.context.getPackageName()); | ||
arg = arg || {}; | ||
// shown at the bottom of the scan UI, default is: "Place a barcode inside the viewfinder rectangle to scan it." | ||
if (arg.message) { | ||
intent.putExtra("PROMPT_MESSAGE", arg.message); | ||
} | ||
if (arg.preferFrontCamera === true) { | ||
// if no front cam is found this will fall back to the back camera | ||
intent.putExtra(com.google.zxing.client.android.Intents.Scan.CAMERA_ID, 1); | ||
} | ||
if (arg.showFlipCameraButton === true) { | ||
intent.putExtra(com.google.zxing.client.android.Intents.Scan.SHOW_FLIP_CAMERA_BUTTON, true); | ||
} | ||
if (arg.orientation) { | ||
// if not set, sensor orientation is used (rotates with the device) | ||
intent.putExtra(com.google.zxing.client.android.Intents.Scan.ORIENTATION_LOCK, arg.orientation); | ||
} | ||
if (arg.formats) { | ||
intent.putExtra(com.google.zxing.client.android.Intents.Scan.FORMATS, arg.formats); | ||
// intent.putExtra(com.google.zxing.client.android.Intents.Scan.MODE, com.google.zxing.client.android.Intents.Scan.QR_CODE_MODE); | ||
} | ||
// rectangle size can be controlled as well (but don't bother as of yet) | ||
// intent.putExtra(com.google.zxing.client.android.Intents.Scan.WIDTH, 200); | ||
// intent.putExtra(com.google.zxing.client.android.Intents.Scan.HEIGHT, 200); | ||
var isContinuous = typeof arg.continuousScanCallback === "function"; | ||
if (isContinuous) { | ||
if (!broadcastManager) { | ||
broadcastManager = android.support.v4.content.LocalBroadcastManager.getInstance(com.tns.NativeScriptApplication.getInstance()); | ||
} | ||
barcodescanner._continuousScanCallback = arg.continuousScanCallback; | ||
intent.putExtra(com.google.zxing.client.android.Intents.Scan.BULK_SCAN, true); | ||
barcodescanner._scannedArray = []; | ||
var CallbackReceiver = android.content.BroadcastReceiver.extend({ | ||
onReceive: function (context, data) { | ||
var format = data.getStringExtra(com.google.zxing.client.android.Intents.Scan.RESULT_FORMAT); | ||
var text = data.getStringExtra(com.google.zxing.client.android.Intents.Scan.RESULT); | ||
// don't report duplicates | ||
if (barcodescanner._scannedArray.indexOf("[" + text + "][" + format + "]") == -1) { | ||
barcodescanner._scannedArray.push("[" + text + "][" + format + "]"); | ||
barcodescanner._continuousScanCallback({ | ||
format : format, | ||
text : text | ||
}); | ||
BarcodeScanner.prototype.available = function () { | ||
return new Promise(function (resolve, reject) { | ||
try { | ||
resolve(camera.isAvailable()); | ||
} | ||
} | ||
catch (ex) { | ||
console.log("Error in barcodescanner.available: " + ex); | ||
resolve(true); | ||
} | ||
}); | ||
barcodescanner._onReceiveCallback = new CallbackReceiver(); | ||
broadcastManager.registerReceiver(barcodescanner._onReceiveCallback, new android.content.IntentFilter("bulk-barcode-result")); | ||
} | ||
if (intent.resolveActivity(com.tns.NativeScriptApplication.getInstance().getPackageManager()) !== null) { | ||
var previousResult = appModule.android.onActivityResult; | ||
appModule.android.onActivityResult = function (requestCode, resultCode, data) { | ||
if (barcodescanner.rememberedContext !== null) { | ||
appModule.android.currentContext = barcodescanner.rememberedContext; | ||
barcodescanner.rememberedContext = null; | ||
} | ||
appModule.android.onActivityResult = previousResult; | ||
if (requestCode === SCANNER_REQUEST_CODE) { | ||
if (isContinuous) { | ||
broadcastManager.unregisterReceiver(barcodescanner._onReceiveCallback); | ||
barcodescanner._onReceiveCallback = undefined; | ||
} else { | ||
if (resultCode === android.app.Activity.RESULT_OK) { | ||
var format = data.getStringExtra(com.google.zxing.client.android.Intents.Scan.RESULT_FORMAT); | ||
var text = data.getStringExtra(com.google.zxing.client.android.Intents.Scan.RESULT); | ||
resolve({ | ||
format : format, | ||
text : text | ||
}); | ||
} else { | ||
reject("Scan aborted"); | ||
} | ||
}; | ||
; | ||
BarcodeScanner.prototype.hasCameraPermission = function () { | ||
var self = this; | ||
return new Promise(function (resolve) { | ||
var granted = self._cameraPermissionGranted(); | ||
resolve(granted); | ||
}); | ||
}; | ||
; | ||
BarcodeScanner.prototype.requestCameraPermission = function () { | ||
var self = this; | ||
return new Promise(function (resolve, reject) { | ||
try { | ||
self._requestCameraPermission(resolve, reject); | ||
} | ||
} | ||
}; | ||
// we need to cache and restore the context, otherwise the dialogs module will be broken (and possibly other things as well) | ||
barcodescanner.rememberedContext = appModule.android.currentContext; | ||
appModule.android.currentContext.startActivityForResult(intent, SCANNER_REQUEST_CODE); | ||
if (isContinuous) { | ||
resolve(); | ||
} | ||
} else { | ||
// this is next to impossible | ||
reject("Configuration error"); | ||
} | ||
} catch (ex) { | ||
console.log("Error in barcodescanner.scan: " + ex); | ||
reject(ex); | ||
} | ||
}); | ||
}; | ||
barcodescanner.stop = function (arg) { | ||
return new Promise(function (resolve, reject) { | ||
try { | ||
var stopIntent = new android.content.Intent("barcode-scanner-stop"); | ||
broadcastManager.sendBroadcast(stopIntent); | ||
broadcastManager.unregisterReceiver(barcodescanner._onReceiveCallback); | ||
barcodescanner._onReceiveCallback = undefined; | ||
resolve(); | ||
} catch (ex) { | ||
reject(ex); | ||
} | ||
}); | ||
}; | ||
module.exports = barcodescanner; | ||
catch (ex) { | ||
console.log("Error in barcodescanner.requestCameraPermission: " + ex); | ||
reject(ex); | ||
} | ||
}); | ||
}; | ||
; | ||
BarcodeScanner.prototype.stop = function () { | ||
var self = this; | ||
return new Promise(function (resolve, reject) { | ||
try { | ||
var stopIntent = new android.content.Intent("barcode-scanner-stop"); | ||
self.broadcastManager.sendBroadcast(stopIntent); | ||
self.broadcastManager.unregisterReceiver(self._onReceiveCallback); | ||
self._onReceiveCallback = undefined; | ||
resolve(); | ||
} | ||
catch (ex) { | ||
reject(ex); | ||
} | ||
}); | ||
}; | ||
; | ||
BarcodeScanner.prototype.scan = function (arg) { | ||
var self = this; | ||
return new Promise(function (resolve, reject) { | ||
var onPermissionGranted = function () { | ||
var intent = new android.content.Intent("com.google.zxing.client.android.SCAN"); | ||
intent.setPackage(appModule.android.context.getPackageName()); | ||
arg = arg || {}; | ||
if (arg.message) { | ||
intent.putExtra("PROMPT_MESSAGE", arg.message); | ||
} | ||
if (arg.preferFrontCamera === true) { | ||
intent.putExtra(com.google.zxing.client.android.Intents.Scan.CAMERA_ID, 1); | ||
} | ||
if (arg.showFlipCameraButton === true) { | ||
intent.putExtra(com.google.zxing.client.android.Intents.Scan.SHOW_FLIP_CAMERA_BUTTON, true); | ||
} | ||
if (arg.orientation) { | ||
intent.putExtra(com.google.zxing.client.android.Intents.Scan.ORIENTATION_LOCK, arg.orientation); | ||
} | ||
if (arg.formats) { | ||
intent.putExtra(com.google.zxing.client.android.Intents.Scan.FORMATS, arg.formats); | ||
} | ||
var isContinuous = typeof arg.continuousScanCallback === "function"; | ||
if (isContinuous) { | ||
if (!self.broadcastManager) { | ||
self.broadcastManager = android.support.v4.content.LocalBroadcastManager.getInstance(com.tns.NativeScriptApplication.getInstance()); | ||
} | ||
self._continuousScanCallback = arg.continuousScanCallback; | ||
intent.putExtra(com.google.zxing.client.android.Intents.Scan.BULK_SCAN, true); | ||
self._scannedArray = []; | ||
var CallbackReceiver = android.content.BroadcastReceiver.extend({ | ||
onReceive: function (context, data) { | ||
var format = data.getStringExtra(com.google.zxing.client.android.Intents.Scan.RESULT_FORMAT); | ||
var text = data.getStringExtra(com.google.zxing.client.android.Intents.Scan.RESULT); | ||
if (self._scannedArray.indexOf("[" + text + "][" + format + "]") == -1) { | ||
self._scannedArray.push("[" + text + "][" + format + "]"); | ||
self._continuousScanCallback({ | ||
format: format, | ||
text: text | ||
}); | ||
} | ||
} | ||
}); | ||
self._onReceiveCallback = new CallbackReceiver(); | ||
self.broadcastManager.registerReceiver(self._onReceiveCallback, new android.content.IntentFilter("bulk-barcode-result")); | ||
} | ||
if (intent.resolveActivity(com.tns.NativeScriptApplication.getInstance().getPackageManager()) !== null) { | ||
var previousResult_1 = appModule.android.onActivityResult; | ||
appModule.android.onActivityResult = function (requestCode, resultCode, data) { | ||
if (self.rememberedContext !== null) { | ||
appModule.android.currentContext = self.rememberedContext; | ||
self.rememberedContext = null; | ||
} | ||
appModule.android.onActivityResult = previousResult_1; | ||
if (requestCode === SCANNER_REQUEST_CODE) { | ||
if (isContinuous) { | ||
self.broadcastManager.unregisterReceiver(self._onReceiveCallback); | ||
self._onReceiveCallback = undefined; | ||
} | ||
else { | ||
if (resultCode === android.app.Activity.RESULT_OK) { | ||
var format = data.getStringExtra(com.google.zxing.client.android.Intents.Scan.RESULT_FORMAT); | ||
var text = data.getStringExtra(com.google.zxing.client.android.Intents.Scan.RESULT); | ||
resolve({ | ||
format: format, | ||
text: text | ||
}); | ||
} | ||
else { | ||
reject("Scan aborted"); | ||
} | ||
} | ||
} | ||
}; | ||
self.rememberedContext = appModule.android.currentContext; | ||
appModule.android.currentContext.startActivityForResult(intent, SCANNER_REQUEST_CODE); | ||
if (isContinuous) { | ||
resolve(); | ||
} | ||
} | ||
else { | ||
reject("Configuration error"); | ||
} | ||
}; | ||
if (!self._cameraPermissionGranted()) { | ||
self._requestCameraPermission(onPermissionGranted, reject); | ||
return; | ||
} | ||
onPermissionGranted(); | ||
}); | ||
}; | ||
; | ||
return BarcodeScanner; | ||
}()); | ||
exports.BarcodeScanner = BarcodeScanner; |
@@ -1,137 +0,228 @@ | ||
var barcodescanner = require("./barcodescanner-common"); | ||
"use strict"; | ||
var utils = require("utils/utils"); | ||
var frame = require("ui/frame"); | ||
var utils = require("utils/utils"); | ||
barcodescanner.available = function () { | ||
return new Promise(function (resolve) { | ||
// since this would also request permission... | ||
// resolve(QRCodeReader.isAvailable()); | ||
// ... and it's extremely likely to be 'true' anyway, I decided to hardcode this: | ||
resolve(true); | ||
}); | ||
}; | ||
// TODO consider asking camera PERMISSION beforehand: https://github.com/yannickl/QRCodeReaderViewController/issues/4, | ||
// would fit well with the Android 6 implementation. | ||
barcodescanner.scan = function (arg) { | ||
return new Promise(function (resolve, reject) { | ||
try { | ||
arg = arg || {}; | ||
var closeButtonLabel = arg.cancelLabel || "Close"; | ||
var isContinuous = typeof arg.continuousScanCallback === "function"; | ||
var types = []; | ||
if (arg.formats) { | ||
var formats = arg.formats.split(","); | ||
for (var f in formats) { | ||
var format = formats[f].trim(); | ||
if (format === "QR_CODE") types.push(AVMetadataObjectTypeQRCode); | ||
else if (format === "PDF_417") types.push(AVMetadataObjectTypePDF417Code); | ||
else if (format === "AZTEC") types.push(AVMetadataObjectTypeAztecCode); | ||
else if (format === "UPC_E") types.push(AVMetadataObjectTypeUPCECode); | ||
else if (format === "CODE_39") types.push(AVMetadataObjectTypeCode39Code); | ||
else if (format === "CODE_39_MOD_43") types.push(AVMetadataObjectTypeCode39Mod43Code); | ||
else if (format === "CODE_93") types.push(AVMetadataObjectTypeCode93Code); | ||
else if (format === "CODE_128") types.push(AVMetadataObjectTypeCode128Code); | ||
else if (format === "EAN_8") types.push(AVMetadataObjectTypeEAN8Code); | ||
else if (format === "EAN_13") types.push(AVMetadataObjectTypeEAN13Code); | ||
var BarcodeScanner = (function () { | ||
function BarcodeScanner() { | ||
this._hasCameraPermission = function () { | ||
var authStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo); | ||
return authStatus === 3; | ||
}; | ||
this._hasDeniedCameraPermission = function () { | ||
var authStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo); | ||
return authStatus === 2 || authStatus === 1; | ||
}; | ||
this._addVolumeObserver = function () { | ||
this._audioSession = utils.ios.getter(AVAudioSession, AVAudioSession.sharedInstance); | ||
this._audioSession.setActiveError(true, null); | ||
this._currentVolume = this._audioSession.outputVolume; | ||
this._audioSession.addObserverForKeyPathOptionsContext(this._observer, "outputVolume", 0, null); | ||
}; | ||
this._removeVolumeObserver = function () { | ||
try { | ||
this._audioSession.removeObserverForKeyPath(this._observer, "outputVolume"); | ||
} | ||
catch (ignore) { | ||
} | ||
}; | ||
this._enableTorch = function () { | ||
var device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo); | ||
device.lockForConfiguration(); | ||
device.setTorchModeOnWithLevelError(AVCaptureMaxAvailableTorchLevel); | ||
device.flashMode = 1; | ||
device.unlockForConfiguration(); | ||
}; | ||
this._disableTorch = function () { | ||
var device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo); | ||
device.lockForConfiguration(); | ||
device.torchMode = 0; | ||
device.flashMode = 0; | ||
device.unlockForConfiguration(); | ||
}; | ||
this._observer = VolumeObserverClass.alloc(); | ||
this._observer["_owner"] = this; | ||
} | ||
BarcodeScanner.prototype.available = function () { | ||
return new Promise(function (resolve, reject) { | ||
resolve(true); | ||
}); | ||
}; | ||
; | ||
BarcodeScanner.prototype.hasCameraPermission = function () { | ||
var self = this; | ||
return new Promise(function (resolve) { | ||
resolve(self._hasCameraPermission()); | ||
}); | ||
}; | ||
; | ||
BarcodeScanner.prototype.requestCameraPermission = function () { | ||
return new Promise(function (resolve) { | ||
QRCodeReader.isAvailable(); | ||
resolve(); | ||
}); | ||
}; | ||
; | ||
BarcodeScanner.prototype.stop = function () { | ||
var self = this; | ||
return new Promise(function (resolve, reject) { | ||
try { | ||
var app = utils.ios.getter(UIApplication, UIApplication.sharedApplication); | ||
app.keyWindow.rootViewController.dismissViewControllerAnimatedCompletion(true, null); | ||
self._removeVolumeObserver(); | ||
resolve(); | ||
} | ||
catch (ex) { | ||
reject(ex); | ||
} | ||
}); | ||
}; | ||
; | ||
BarcodeScanner.prototype.scan = function (arg) { | ||
var self = this; | ||
return new Promise(function (resolve, reject) { | ||
try { | ||
if (self._hasDeniedCameraPermission()) { | ||
if (arg.openSettingsIfPermissionWasPreviouslyDenied) { | ||
utils.ios.getter(UIApplication, UIApplication.sharedApplication).openURL(NSURL.URLWithString(UIApplicationOpenSettingsURLString)); | ||
} | ||
reject("The user previously denied permission to access the camera."); | ||
return; | ||
} | ||
self._addVolumeObserver(); | ||
arg = arg || {}; | ||
var closeButtonLabel = arg.cancelLabel || "Close"; | ||
var isContinuous_1 = typeof arg.continuousScanCallback === "function"; | ||
var types = []; | ||
if (arg.formats) { | ||
var formats = arg.formats.split(","); | ||
for (var _i = 0, formats_1 = formats; _i < formats_1.length; _i++) { | ||
var format = formats_1[_i]; | ||
format = format.trim(); | ||
if (format === "QR_CODE") | ||
types.push(AVMetadataObjectTypeQRCode); | ||
else if (format === "PDF_417") | ||
types.push(AVMetadataObjectTypePDF417Code); | ||
else if (format === "AZTEC") | ||
types.push(AVMetadataObjectTypeAztecCode); | ||
else if (format === "UPC_E") | ||
types.push(AVMetadataObjectTypeUPCECode); | ||
else if (format === "CODE_39") | ||
types.push(AVMetadataObjectTypeCode39Code); | ||
else if (format === "CODE_39_MOD_43") | ||
types.push(AVMetadataObjectTypeCode39Mod43Code); | ||
else if (format === "CODE_93") | ||
types.push(AVMetadataObjectTypeCode93Code); | ||
else if (format === "CODE_128") | ||
types.push(AVMetadataObjectTypeCode128Code); | ||
else if (format === "EAN_8") | ||
types.push(AVMetadataObjectTypeEAN8Code); | ||
else if (format === "EAN_13") | ||
types.push(AVMetadataObjectTypeEAN13Code); | ||
} | ||
} | ||
else { | ||
types = [AVMetadataObjectTypeUPCECode, AVMetadataObjectTypeCode39Code, AVMetadataObjectTypeCode39Mod43Code, | ||
AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode93Code, AVMetadataObjectTypeCode128Code, | ||
AVMetadataObjectTypePDF417Code, AVMetadataObjectTypeQRCode, AVMetadataObjectTypeAztecCode]; | ||
} | ||
var bs = QRCodeReaderViewController.readerWithCancelButtonTitleMetadataObjectTypes(closeButtonLabel, types); | ||
bs.modalPresentationStyle = 2; | ||
var delegate_1 = QRCodeReaderDelegateImpl.new().initWithCallback(isContinuous_1, function (reader, text, format) { | ||
if (text === undefined) { | ||
self._removeVolumeObserver(); | ||
reject("Scan aborted"); | ||
} | ||
else { | ||
var result = { | ||
format: format, | ||
text: text | ||
}; | ||
if (isContinuous_1) { | ||
arg.continuousScanCallback(result); | ||
} | ||
else { | ||
self._removeVolumeObserver(); | ||
resolve(result); | ||
} | ||
} | ||
delegate_1 = undefined; | ||
}); | ||
bs.delegate = delegate_1; | ||
var topMostFrame = frame.topmost(); | ||
if (topMostFrame) { | ||
var vc = topMostFrame.currentPage && topMostFrame.currentPage.ios; | ||
if (vc) { | ||
vc.presentViewControllerAnimatedCompletion(bs, true, null); | ||
} | ||
} | ||
if (isContinuous_1) { | ||
resolve(); | ||
} | ||
} | ||
catch (ex) { | ||
console.log("Error in barcodescanner.scan: " + ex); | ||
reject(ex); | ||
} | ||
}); | ||
}; | ||
; | ||
return BarcodeScanner; | ||
}()); | ||
exports.BarcodeScanner = BarcodeScanner; | ||
var QRCodeReaderDelegateImpl = (function (_super) { | ||
__extends(QRCodeReaderDelegateImpl, _super); | ||
function QRCodeReaderDelegateImpl() { | ||
_super.apply(this, arguments); | ||
} | ||
QRCodeReaderDelegateImpl.new = function () { | ||
return _super.new.call(this); | ||
}; | ||
QRCodeReaderDelegateImpl.prototype.initWithCallback = function (isContinuous, callback) { | ||
this._isContinuous = isContinuous; | ||
this._callback = callback; | ||
return this; | ||
}; | ||
QRCodeReaderDelegateImpl.prototype.readerDidCancel = function (reader) { | ||
var app = utils.ios.getter(UIApplication, UIApplication.sharedApplication); | ||
app.keyWindow.rootViewController.dismissViewControllerAnimatedCompletion(true, null); | ||
this._callback(reader); | ||
}; | ||
; | ||
QRCodeReaderDelegateImpl.prototype.readerDidScanResultForType = function (reader, text, type) { | ||
if (this._isContinuous) { | ||
if (!this._scannedArray) { | ||
this._scannedArray = Array(); | ||
} | ||
if (this._scannedArray.indexOf("[" + text + "][" + type + "]") === -1) { | ||
this._scannedArray.push("[" + text + "][" + type + "]"); | ||
this._callback(reader, text, type); | ||
} | ||
} | ||
} else { | ||
types = [AVMetadataObjectTypeUPCECode, AVMetadataObjectTypeCode39Code, AVMetadataObjectTypeCode39Mod43Code, | ||
AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode93Code, AVMetadataObjectTypeCode128Code, | ||
AVMetadataObjectTypePDF417Code, AVMetadataObjectTypeQRCode, AVMetadataObjectTypeAztecCode]; | ||
} | ||
var bs = QRCodeReaderViewController.readerWithCancelButtonTitleMetadataObjectTypes(closeButtonLabel, types); | ||
bs.modalPresentationStyle = UIModalPresentationFormSheet; | ||
// Assign first to local variable, otherwise it will be garbage collected since delegate is weak reference. | ||
var delegate = QRCodeReaderDelegateImpl.new().initWithCallback(isContinuous, function (reader, text, format) { | ||
// invoke the callback / promise | ||
if (text === undefined) { | ||
reject("Scan aborted"); | ||
} else { | ||
var result = { | ||
format : format, | ||
text : text | ||
}; | ||
if (isContinuous) { | ||
arg.continuousScanCallback(result); | ||
} else { | ||
resolve(result); | ||
} | ||
else { | ||
var app = utils.ios.getter(UIApplication, UIApplication.sharedApplication); | ||
app.keyWindow.rootViewController.dismissViewControllerAnimatedCompletion(true, null); | ||
this._callback(reader, text, type); | ||
} | ||
// Remove the local variable for the delegate. | ||
delegate = undefined; | ||
}); | ||
bs.delegate = delegate; | ||
var topMostFrame = frame.topmost(); | ||
if (topMostFrame) { | ||
var vc = topMostFrame.currentPage && topMostFrame.currentPage.ios; | ||
if (vc) { | ||
vc.presentViewControllerAnimatedCompletion(bs, true, null); | ||
}; | ||
; | ||
QRCodeReaderDelegateImpl.ObjCProtocols = [QRCodeReaderDelegate]; | ||
return QRCodeReaderDelegateImpl; | ||
}(NSObject)); | ||
var VolumeObserverClass = (function (_super) { | ||
__extends(VolumeObserverClass, _super); | ||
function VolumeObserverClass() { | ||
_super.apply(this, arguments); | ||
} | ||
VolumeObserverClass.prototype.observeValueForKeyPathOfObjectChangeContext = function (path, obj, change, context) { | ||
if (path === "outputVolume") { | ||
var volumeLevel = utils.ios.getter(MPMusicPlayerController, MPMusicPlayerController.applicationMusicPlayer).volume; | ||
if (volumeLevel > this["_owner"]._currentVolume) { | ||
this["_owner"]._enableTorch(); | ||
} | ||
else { | ||
this["_owner"]._disableTorch(); | ||
} | ||
this["_owner"]._currentVolume = volumeLevel; | ||
} | ||
} | ||
if (isContinuous) { | ||
resolve(); | ||
} | ||
} catch (ex) { | ||
console.log("Error in barcodescanner.scan: " + ex); | ||
reject(ex); | ||
} | ||
}); | ||
}; | ||
barcodescanner.stop = function (arg) { | ||
return new Promise(function (resolve, reject) { | ||
try { | ||
var app = utils.ios.getter(UIApplication, UIApplication.sharedApplication); | ||
app.keyWindow.rootViewController.dismissViewControllerAnimatedCompletion(true, null); | ||
resolve(); | ||
} catch (ex) { | ||
reject(ex); | ||
} | ||
}); | ||
}; | ||
var QRCodeReaderDelegateImpl = (function (_super) { | ||
__extends(QRCodeReaderDelegateImpl, _super); | ||
function QRCodeReaderDelegateImpl() { | ||
_super.apply(this, arguments); | ||
} | ||
QRCodeReaderDelegateImpl.new = function () { | ||
return _super.new.call(this); | ||
}; | ||
QRCodeReaderDelegateImpl.prototype.initWithCallback = function (isContinuous, callback) { | ||
this._isContinuous = isContinuous; | ||
this._callback = callback; | ||
return this; | ||
}; | ||
QRCodeReaderDelegateImpl.prototype.readerDidCancel = function (reader) { | ||
var app = utils.ios.getter(UIApplication, UIApplication.sharedApplication); | ||
app.keyWindow.rootViewController.dismissViewControllerAnimatedCompletion(true, null); | ||
this._callback(reader); | ||
}; | ||
QRCodeReaderDelegateImpl.prototype.readerDidScanResultForType = function (reader, text, type) { | ||
if (this._isContinuous) { | ||
if (!this._scannedArray) { | ||
this._scannedArray = []; | ||
} | ||
// don't report duplicates | ||
if (this._scannedArray.indexOf("[" + text + "][" + type + "]") == -1) { | ||
this._scannedArray.push("[" + text + "][" + type + "]"); | ||
this._callback(reader, text, type); | ||
} | ||
} else { | ||
var app = utils.ios.getter(UIApplication, UIApplication.sharedApplication); | ||
app.keyWindow.rootViewController.dismissViewControllerAnimatedCompletion(true, null); | ||
this._callback(reader, text, type); | ||
} | ||
}; | ||
QRCodeReaderDelegateImpl.ObjCProtocols = [QRCodeReaderDelegate]; | ||
return QRCodeReaderDelegateImpl; | ||
})(NSObject); | ||
module.exports = barcodescanner; | ||
}; | ||
return VolumeObserverClass; | ||
}(NSObject)); |
{ | ||
"name": "nativescript-barcodescanner", | ||
"version": "1.4.1", | ||
"version": "2.0.0", | ||
"description": "Scan QR/barcodes with a {N} app.", | ||
"main": "barcodescanner.js", | ||
"typings": "barcodescanner.d.ts", | ||
"nativescript": { | ||
@@ -12,2 +13,10 @@ "platforms": { | ||
}, | ||
"scripts": { | ||
"build": "tsc", | ||
"demo.ios": "npm run preparedemo && cd demo && tns emulate ios --device \"iPhone 7\"", | ||
"demo.ios.device": "npm run preparedemo && cd demo && tns run ios", | ||
"demo.android": "npm run preparedemo && cd demo && tns run android", | ||
"preparedemo": "npm run build && cd demo && tns plugin remove nativescript-barcodescanner && tns plugin add .. && tns install", | ||
"setup": "npm i && cd demo && npm i && cd .. && npm run build && cd demo && tns plugin add .. && cd .." | ||
}, | ||
"repository": { | ||
@@ -18,2 +27,3 @@ "type": "git", | ||
"keywords": [ | ||
"ecosystem:nativescript", | ||
"NativeScript", | ||
@@ -25,2 +35,4 @@ "Barcode", | ||
"Continuous", | ||
"Flashlight", | ||
"Torch", | ||
"Aztec", | ||
@@ -49,3 +61,12 @@ "Codabar", | ||
}, | ||
"homepage": "https://github.com/eddyverbruggen/nativescript-barcodescanner" | ||
"homepage": "https://github.com/eddyverbruggen/nativescript-barcodescanner", | ||
"devDependencies": { | ||
"nativescript-dev-typescript": "^0.3.2", | ||
"tns-core-modules": "^2.3.0", | ||
"tns-platform-declarations": "^2.3.0", | ||
"typescript": "^1.8.0" | ||
}, | ||
"dependencies": { | ||
"nativescript-theme-core": "^0.1.2" | ||
} | ||
} |
127
README.md
# NativeScript BarcodeScanner | ||
Scan a barcode (or a QR code, or a lot of other formats really) | ||
#### Want a quick demo? | ||
* git clone https://github.com/EddyVerbruggen/nativescript-barcodescanner barcodedemo | ||
* cd barcodedemo | ||
* npm run setup | ||
* npm run demo.android (or demo.ios / demo.ios.device) | ||
> Looking for a demo? [Look no further!](https://github.com/EddyVerbruggen/nativescript-barcodescanner-demo) | ||
## Supported barcode types | ||
@@ -53,14 +55,45 @@ | ||
## Usage | ||
Tip: during a scan you can use the volume up/down buttons to toggle the torch. | ||
### function: scan (single mode) | ||
#### TypeScript | ||
```js | ||
var barcodescanner = require("nativescript-barcodescanner"); | ||
import {BarcodeScanner} from "nativescript-barcodescanner"; | ||
let barcodescanner = new BarcodeScanner(); | ||
barcodescanner.scan({ | ||
formats: "QR_CODE, EAN_13", | ||
cancelLabel: "EXIT. Also, try the volume buttons!", // iOS only, default 'Close' | ||
message: "Use the volume buttons for extra light", // Android only, default is 'Place a barcode inside the viewfinder rectangle to scan it.' | ||
preferFrontCamera: front, // Android only, default false | ||
showFlipCameraButton: flip, // Android only, default false (on iOS it's always available) | ||
orientation: orientation, // Android only, default undefined (sensor-driven orientation), other options: portrait|landscape | ||
openSettingsIfPermissionWasPreviouslyDenied: true // On iOS you can send the user to the settings app if access was previously denied | ||
}).then((result) => { | ||
// Note that this Promise is never invoked when a 'continuousScanCallback' function is provided | ||
alert({ | ||
title: "Scan result", | ||
message: "Format: " + result.format + ",\nValue: " + result.text, | ||
okButtonText: "OK" | ||
}); | ||
}, (errorMessage) => { | ||
console.log("No scan. " + errorMessage); | ||
} | ||
); | ||
``` | ||
#### JavaScript | ||
```js | ||
var BarcodeScanner = require("nativescript-barcodescanner").BarcodeScanner; | ||
var barcodescanner = new BarcodeScanner(); | ||
barcodescanner.scan({ | ||
formats: "QR_CODE,PDF_417", // Pass in of you want to restrict scanning to certain types | ||
cancelLabel: "Stop scanning", // iOS only, default 'Close' | ||
message: "Go scan something", // Android only, default is 'Place a barcode inside the viewfinder rectangle to scan it.' | ||
cancelLabel: "EXIT. Also, try the volume buttons!", // iOS only, default 'Close' | ||
message: "Use the volume buttons for extra light", // Android only, default is 'Place a barcode inside the viewfinder rectangle to scan it.' | ||
preferFrontCamera: false, // Android only, default false | ||
showFlipCameraButton: true, // Android only, default false (on iOS it's always available) | ||
orientation: "landscape" // Android only, optionally lock the orientation to either "portrait" or "landscape" | ||
orientation: "landscape", // Android only, optionally lock the orientation to either "portrait" or "landscape" | ||
openSettingsIfPermissionWasPreviouslyDenied: true // On iOS you can send the user to the settings app if access was previously denied | ||
}).then( | ||
@@ -78,4 +111,3 @@ function(result) { | ||
### function: scan (bulk / continuous mode) | ||
By popular demand version 1.4.0 added bulk mode. | ||
The scanner will continuously report scanned codes back to your code, | ||
In this mode the scanner will continuously report scanned codes back to your code, | ||
but it will only be dismissed if the user tells it to, or you call `stop` programmatically. | ||
@@ -88,2 +120,4 @@ | ||
You'll notice that the Promise will no longer receive the result as there may be many results: | ||
#### JavaScript | ||
```js | ||
@@ -115,2 +149,3 @@ var count = 0; | ||
#### JavaScript | ||
```js | ||
@@ -127,11 +162,12 @@ var barcodescanner = require("nativescript-barcodescanner"); | ||
### function: hasCameraPermission / requestCameraPermission | ||
On Android 6 you need to request permission to use the camera at runtime when targeting API level 23+. | ||
On Android 6+ you need to request permission to use the camera at runtime when targeting API level 23+. | ||
Even if the `uses-permission` tag for the Camera is present in `AndroidManifest.xml`. | ||
Note that `hasCameraPermission` will return true when: | ||
* You're running this on iOS, or | ||
* You're targeting an API level lower than 23, or | ||
* You're using Android < 6, or | ||
* You've already granted permission. | ||
On iOS 10+ there's something similar going on. | ||
Since version 1.5.0 you can let the plugin handle this for you | ||
(if need be a prompt will be shown to the user when the scanner launches), | ||
but if for some reason you want to handle permissions yourself you can use these functions. | ||
#### JavaScript | ||
```js | ||
@@ -153,4 +189,59 @@ barcodescanner.hasCameraPermission().then( | ||
Note that the `scan` function will also check for permission and ask for it if it wasn't previously granted. | ||
If you're relying on that, then you should know that since we're not catching the consent result | ||
the user will then need to allow camera access and launch the scanner again. | ||
### Usage with `nativescript-angular` | ||
When using Angular 2, it is best to inject dependencies into your classes. Here is an example of how you | ||
can set up `nativescript-barcodescanner` in an Angular 2 app with dependency injection. | ||
1. Set up an [opaque token](https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#dependency-injection-tokens) | ||
```ts | ||
//barcodescanner.ts | ||
import { OpaqueToken } from '@angular/core'; | ||
import * as scanner from 'nativescript-barcodescanner'; | ||
export const BARCODE_SCANNER = new OpaqueToken('barcodescanner'); | ||
//These are re-exported for convenience (so you don't have to import from two places) | ||
export const barcodescanner = scanner; | ||
export type BarcodeScanner = scanner.BarcodeScanner; | ||
export type ScanOptions = scanner.ScanOptions; | ||
export type IosScanOptions = scanner.ScanOptions.IOS; | ||
export type AndroidScanOptions = scanner.ScanOptions.Android; | ||
``` | ||
1. Register the provider with your module | ||
```ts | ||
//app.module.ts | ||
import { NgModule, ValueProvider } from '@angular/core'; | ||
import { BARCODE_SCANNER, barcodescanner } from './barcodescanner'; | ||
//other imports | ||
@NgModule({ | ||
//bootstrap, declarations, imports, etc. | ||
providers: [ | ||
<ValueProvider>{ provide: BARCODE_SCANNER, useValue: barcodescanner } | ||
] | ||
}) | ||
export class AppModule {} | ||
``` | ||
1. Inject it into your component | ||
```ts | ||
//my-component.ts | ||
import { Component, Inject } from '@angular/core'; | ||
import { BARCODE_SCANNER, BarcodeScanner } from './barcodescanner'; | ||
//other imports | ||
@Component({ ... }) | ||
export class MyComponent { | ||
constructor(@Inject(BARCODE_SCANNER) private barcodeScanner: BarcodeScanner) { | ||
} | ||
//use the barcodescanner wherever you need it. See general usage above. | ||
scanBarcode() { | ||
this.barcodeScanner.scan({ ... }); | ||
} | ||
} | ||
``` | ||
## Changelog | ||
* __2.0.0__ Conversion to TypeScript (note that the JS require syntax is now slightly different!). | ||
* __1.5.0__ Auto-permission handling. Use the volume up/down buttons to toggle the torch. | ||
* __1.4.0__ Bulk scanning. |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1444713
34
982
241
1
4
1
+ Addednativescript-theme-core@0.1.5(transitive)