ti.barcode
ti.barcode copied to clipboard
Android CAMERA permission issue on Android SDK23+ (Ti SDK 5+)
From https://developer.android.com/training/permissions/requesting.html#perm-check
If the device is running Android 6.0 or higher, and your app's target SDK is 23 or higher: The app has to list the permissions in the manifest, and it must request each dangerous permission it needs while the app is running.
CAMERA is a "dangerous" permission. I am uncertain, but my impression is that the intent, the bundled version of zxing should be making that requestPermissions() to prompt the user to allow access. Since this not happening the only way you can use this module appears to go into "Settings" and give the app explicit access to the camera.
I haven't used Java in a long time, but if somebody can point me in the right direction I'd be happy to attempt to fix this. Thanks!
You can already ask for the permissions using normal Ti-SDK methods. Use these before you open ti.barcode
In modified example below look out for function cameraPermission used in scanCode.addEventListener
/**
* In this example, we'll use the Barcode module to display some information about
* the scanned barcode.
*/
var Barcode = require('ti.barcode');
Barcode.allowRotation = true;
Barcode.displayedMessage = ' ';
Barcode.allowMenu = false;
Barcode.allowInstructions = false;
Barcode.useLED = true;
var window = Ti.UI.createWindow({
backgroundColor: 'white'
});
var scrollView = Ti.UI.createScrollView({
contentWidth: 'auto',
contentHeight: 'auto',
top: 0,
showVerticalScrollIndicator: true,
layout: 'vertical'
});
/**
* Create a chrome for the barcode scanner.
*/
var overlay = Ti.UI.createView({
backgroundColor: 'transparent',
top: 0, right: 0, bottom: 0, left: 0
});
var switchButton = Ti.UI.createButton({
title: Barcode.useFrontCamera ? 'Back Camera' : 'Front Camera',
textAlign: 'center',
color: '#000', backgroundColor: '#fff', style: 0,
font: { fontWeight: 'bold', fontSize: 16 },
borderColor: '#000', borderRadius: 10, borderWidth: 1,
opacity: 0.5,
width: 220, height: 30,
bottom: 10
});
switchButton.addEventListener('click', function () {
Barcode.useFrontCamera = !Barcode.useFrontCamera;
switchButton.title = Barcode.useFrontCamera ? 'Back Camera' : 'Front Camera';
});
overlay.add(switchButton);
var cancelButton = Ti.UI.createButton({
title: 'Cancel', textAlign: 'center',
color: '#000', backgroundColor: '#fff', style: 0,
font: { fontWeight: 'bold', fontSize: 16 },
borderColor: '#000', borderRadius: 10, borderWidth: 1,
opacity: 0.5,
width: 220, height: 30,
top: 20
});
cancelButton.addEventListener('click', function () {
Barcode.cancel();
});
overlay.add(cancelButton);
/**
* Create a button that will trigger the barcode scanner.
*/
var scanCode = Ti.UI.createButton({
title: 'Scan the Code',
width: 150,
height: 60,
top: 20
});
/** undersirable
function writeFile(){
var filenameBase = new Date().getTime();
var file = Ti.Filesystem.getFile(Ti.Filesystem.externalStorageDirectory + filenameBase);
file.write("a");
return file.exists();
}
*/
var cameraPermission = function(callback){
if(OS_ANDROID){
if (Ti.Media.hasCameraPermissions()) {
if(callback){callback(true);}
} else {
Ti.Media.requestCameraPermissions(function(e) {
if (e.success) {
if(callback){callback(true);}
} else {
if(callback){callback(false);}
alert('No camera permission');
}
});
}
}
if(OS_IOS){
if(callback){callback(true);}
}
};
var mediaPermission = function(callback){
if(OS_ANDROID){
if (Ti.Filesystem.hasStoragePermissions()) {
if(callback){callback(true);}
} else {
Ti.Filesystem.requestStoragePermissions(function(e) {
if (e.success) {
if(callback){callback(true);}
} else {
if(callback){callback(false);}
alert('No storage permission');
}
});
}
}
if(OS_IOS){
if(callback){callback(true);}
}
};
scanCode.addEventListener('click', function () {
cameraPermission(function(re) {
reset();
// Note: while the simulator will NOT show a camera stream in the simulator, you may still call "Barcode.capture"
// to test your barcode scanning overlay.
Barcode.capture({
animate: true,
overlay: overlay,
showCancel: false,
showRectangle: false,
keepOpen: true/*,
acceptedFormats: [
Barcode.FORMAT_QR_CODE
]*/
});
});
});
scrollView.add(scanCode);
/**
* Create a button that will show the gallery picker.
*/
var scanImage = Ti.UI.createButton({
title: 'Scan Image from Gallery',
width: 150, height: 60, top: 20
});
scanImage.addEventListener('click', function () {
reset();
Ti.Media.openPhotoGallery({
success: function (evt) {
Barcode.parse({
image: evt.media/*,
acceptedFormats: [
Barcode.FORMAT_QR_CODE
]*/
});
}
});
});
scrollView.add(scanImage);
/**
* Now listen for various events from the Barcode module. This is the module's way of communicating with us.
*/
var scannedBarcodes = {}, scannedBarcodesCount = 0;
function reset() {
scannedBarcodes = {};
scannedBarcodesCount = 0;
cancelButton.title = 'Cancel';
scanResult.text = ' ';
scanContentType.text = ' ';
scanFormat.text = ' ';
scanParsed.text = ' ';
}
Barcode.addEventListener('error', function (e) {
scanContentType.text = ' ';
scanFormat.text = ' ';
scanParsed.text = ' ';
scanResult.text = e.message;
console.log(e);
});
Barcode.addEventListener('cancel', function (e) {
Ti.API.info('Cancel received');
});
Barcode.addEventListener('success', function (e) {
Ti.API.info('Success called with barcode: ' + e.result);
if (!scannedBarcodes['' + e.result]) {
scannedBarcodes[e.result] = true;
scannedBarcodesCount += 1;
cancelButton.title = 'Finished (' + scannedBarcodesCount + ' Scanned)';
scanResult.text += e.result + ' ';
scanContentType.text += parseContentType(e.contentType) + ' ';
scanFormat.text += e.format + ' ';
scanParsed.text += parseResult(e) + ' ';
}
});
/**
* Finally, we'll add a couple labels to the window. When the user scans a barcode, we'll stick information about it in
* to these labels.
*/
scrollView.add(Ti.UI.createLabel({
text: 'You may need to rotate the device',
top: 10,
height: Ti.UI.SIZE || 'auto', width: Ti.UI.SIZE || 'auto'
}));
scrollView.add(Ti.UI.createLabel({
text: 'Result: ', textAlign: 'left',
top: 10, left: 10,
color: 'black',
height: Ti.UI.SIZE || 'auto'
}));
var scanResult = Ti.UI.createLabel({
text: ' ', textAlign: 'left',
top: 10, left: 10,
color: 'black',
height: Ti.UI.SIZE || 'auto'
});
scrollView.add(scanResult);
scrollView.add(Ti.UI.createLabel({
text: 'Content Type: ',
top: 10, left: 10,
textAlign: 'left',
color: 'black',
height: Ti.UI.SIZE || 'auto'
}));
var scanContentType = Ti.UI.createLabel({
text: ' ', textAlign: 'left',
top: 10, left: 10,
color: 'black',
height: Ti.UI.SIZE || 'auto'
});
scrollView.add(scanContentType);
scrollView.add(Ti.UI.createLabel({
text: 'Format: ', textAlign: 'left',
top: 10, left: 10,
color: 'black',
height: Ti.UI.SIZE || 'auto'
}));
var scanFormat = Ti.UI.createLabel({
text: ' ', textAlign: 'left',
top: 10, left: 10,
color: 'black',
height: Ti.UI.SIZE || 'auto'
});
scrollView.add(scanFormat);
scrollView.add(Ti.UI.createLabel({
text: 'Parsed: ', textAlign: 'left',
top: 10, left: 10,
color: 'black',
height: Ti.UI.SIZE || 'auto'
}));
var scanParsed = Ti.UI.createLabel({
text: ' ', textAlign: 'left',
top: 10, left: 10,
color: 'black',
height: Ti.UI.SIZE || 'auto'
});
scrollView.add(scanParsed);
function parseContentType(contentType) {
switch (contentType) {
case Barcode.URL:
return 'URL';
case Barcode.SMS:
return 'SMS';
case Barcode.TELEPHONE:
return 'TELEPHONE';
case Barcode.TEXT:
return 'TEXT';
case Barcode.CALENDAR:
return 'CALENDAR';
case Barcode.GEOLOCATION:
return 'GEOLOCATION';
case Barcode.EMAIL:
return 'EMAIL';
case Barcode.CONTACT:
return 'CONTACT';
case Barcode.BOOKMARK:
return 'BOOKMARK';
case Barcode.WIFI:
return 'WIFI';
default:
return 'UNKNOWN';
}
}
function parseResult(event) {
var msg = '';
switch (event.contentType) {
case Barcode.URL:
msg = 'URL = ' + event.result;
break;
case Barcode.SMS:
msg = 'SMS = ' + JSON.stringify(event.data);
break;
case Barcode.TELEPHONE:
msg = 'Telephone = ' + event.data.phonenumber;
break;
case Barcode.TEXT:
msg = 'Text = ' + event.result;
break;
case Barcode.CALENDAR:
msg = 'Calendar = ' + JSON.stringify(event.data);
break;
case Barcode.GEOLOCATION:
msg = 'Geo = ' + JSON.stringify(event.data);
break;
case Barcode.EMAIL:
msg = 'Email = ' + event.data.email + '\nSubject = ' + event.data.subject + '\nMessage = ' + event.data.message;
break;
case Barcode.CONTACT:
msg = 'Contact = ' + JSON.stringify(event.data);
break;
case Barcode.BOOKMARK:
msg = 'Bookmark = ' + JSON.stringify(event.data);
break;
case Barcode.WIFI:
return 'WIFI = ' + JSON.stringify(event.data);
default:
msg = 'unknown content type';
break;
}
return msg;
}
window.add(scrollView);
window.open();