I've code an app to scan barcodes. I've tried to use ZXing and all works fine, but I would use directly camera without external App (like Anobii), there is any way to do this whit ZXing?
CaptureActivity has the method:
public void handleDecode(Result rawResult, Bitmap barcode)
This method decides if will call to an external or internal app, you should comment the following code into switch(source){...} to avoid exit to external apps.:
case NATIVE_APP_INTENT:
case PRODUCT_SEARCH_LINK:
handleDecodeExternally(rawResult, resultHandler, barcode);
break;
case ZXING_LINK:
if (returnUrlTemplate == null) {
handleDecodeInternally(rawResult, resultHandler, barcode);
} else {
handleDecodeExternally(rawResult, resultHandler, barcode);
}
break;
In the next method you can call to your activity, you should comment all and add the next code:
private void handleDecodeInternally(Result rawResult,
ResultHandler resultHandler, Bitmap barcode) {
String resultString = resultHandler.getDisplayContents().toString();
if (resultString.startsWith("some"))//define a regular expression in the qr code{
//do something as call a new activity
}else{
//show error message
}
}
Expanding Flavio's answer you need to look at com.google.zxing.client.android.camera package which contains classes for working with android camera
Related
I have had a problem for weeks and still can not solve, did a lot of research and tested many codes, but nothing solved. I will explain my problem in detail.
I am making an application where in a layout there would be three or more clickable photos, I am using the “ArthurHub / Android-Image-Cropper” image cropping library, the steps are:
Click on the image, which gives the option to open the image gallery to select a photo or take a new photo, after that I can crop
the selected image.
Select the second photo, do the same as the previous one, thereafter.
Upload the photos to the server.
Steps 1 is working correctly, the problem arises when I try to select from the second image.
What I'm using: I'm using two classes: the one that requests the images and the one that returns:
1. would be the main window with ImageButton.
2. and the other class that returns the selected images to the first class. (Contains the function that calls the gallery or camera, cuts the image, the other “onActivityResult” function that returns the image address, who asked for the picture).
So far everything works correctly.
Problem Description: The problem arises from the second image selected. when the second class returns everything to the first, it is as if the second image is stored in the same memory space as the first (erasing everything previously), and if I select the third image, it deletes the second and only remains the third and henceforth. What I want to do is select the images and have them all seen at the same time (usable) to send to a server.
Solutions I tried:
After days of searching, the suggestion was to make several returns on “onActivityResult” so that it returned the result of selecting
images separately, I couldn't find anything that worked, the
explanations I found were only halfway (including the official
documentation does not detail the steps to control the various returns
of the function, is very superficial), could not control the separate
pointing of the images.
switch (requestCode){
case (1000):
Intent intent1 = new Intent(TirarFoto1.this, RegistrarAutomovelDuasRodas.class);
intent1.putExtra("class", classname);
intent1.putExtra("imageview", imageview);
intent1.putExtra("pathimage", pathimage);
startActivity(intent1);
break;
case (2000):
Intent intent2 = new Intent(TirarFoto1.this, RegistrarAutomovelDuasRodas.class);
intent2.putExtra("class", classname);
intent2.putExtra("imageview", imageview);
intent2.putExtra("pathimage", pathimage);
startActivity(intent2);
case (3000):
Intent intent3 = new Intent(TirarFoto1.this, RegistrarAutomovelDuasRodas.class);
intent3.putExtra("class", classname);
intent3.putExtra("imageview", imageview);
intent3.putExtra("pathimage", pathimage);
startActivity(intent3);
break;
default: break;
}
I decided to save each image separately outside the “temporary cache” folder (where they are located), even with the “manifest”
permissions, nothing happens, permission is denied, so I couldn't even
create the new folder to save the images in it, as a result does not
save the selected images.
if (ContextCompat.checkSelfPermission(TirarFoto1.this,Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED){
File file = new File(Environment.getExternalStoragePublicDirectory(String.valueOf(imageUri))+"folderName");
if (!file.exists()){
Toast.makeText(this, "exists", Toast.LENGTH_SHORT).show();
}
if (success){
Toast.makeText(this, "creaty", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(this, "Erro!!!", Toast.LENGTH_SHORT).show();
}
}else {
requestStoragePermisson();
}
Result: The first solution did not work and the second did not work.
What I want: a model, a concrete way to help me, can anyone please help me with this? I have been stuck in this problem for a long time.
me to use ArthurHub-Android-Image-Cropper for cropped image, you can learn from this link
https://github.com/ArthurHub/Android-Image-Cropper/wiki
hope this help
Edit:
i have a class using ArthurHub-Android-Image-Cropper but from kotlin and i try to convert to java
like this
//for identify image
private Int imageNo;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//......
//set button image 1
final Button button1 = findViewById(R.id.button_image1);
button1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// set image count to 1
imageNo=1
getImageClick()
}
});
//set button image 2
final Button button1 = findViewById(R.id.button_image1);
button1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// set image count to 2
imageNo=2
getImageClick()
}
});
//set button image 3
final Button button1 = findViewById(R.id.button_image1);
button1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// set image count to 3
imageNo=3
getImageClick()
}
});
}
//select image form camera or galery
public void getImageClick() {
CropImage.startPickImageActivity(this);
}
//this for Crope Image
private void startCropImageActivity(Uri imageUri) {
CropImage.activity(imageUri)
.start(this);
}
#Override
#SuppressLint("NewApi")
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//handle result from onGetimageClick(button for select image from camera or galery)
if (requestCode == CropImage.PICK_IMAGE_CHOOSER_REQUEST_CODE && resultCode == AppCompatActivity.RESULT_OK) {
Uri imageUri = CropImage.getPickImageResultUri(this, data);
//start Crope image
startCropImageActivity(imageUri);
}
// handle result of CropImageActivity
else if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
CropImage.ActivityResult result = CropImage.getActivityResult(data);
Uri resultUri = result.getUri();
switch (imageNo){
case (1):
//here you have resultUri for save image or preview as image1
break;
case (2):
//here you have resultUri for save image or preview as image1
case (3):
//here you have resultUri for save image or preview as image1
}
}
}
don't forget to add manifest
<activity android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
android:theme="#style/Theme.AppCompat"/>
Hope this help
When the Zxing finds a QR code it deliver it to handleResult function and it stops the camera. I need to restart the camera if the decoded QR code was already saved in my app. How to restart the camera again?
If you're using ZXing's ZXingScannerView you can use stopCameraPreview() in combination with stopCamera() when you're processing the QR Code and/or showing the result to your users. When your app/user is ready to scan again you just call setResultHandler() with startCamera() and resumeCameraPreview().
Example:
public void startScan() { //use this when you want to resume the camera
if (scannerView != null) {
scannerView.setResultHandler(this);
scannerView.startCamera();
rescan();
}
}
public void stopScan() { //use this when you want to stop scanning
// it is very important to do that,
// because the camera will keep scanning codes in background
if (scannerView != null) {
scannerView.stopCameraPreview();
scannerView.stopCamera();
}
}
public void rescan() {
if (scannerView != null) {
scannerView.resumeCameraPreview(this);
}
}
Hope this helps :)
I am developing an Android application, I need to embed the Zxing scanner. The application should allow the user to scan a QR Code and then store the QR code ID of the product and parse it from an XML file. As yet, I have used the simple code:
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.setPackage(getPackageName());
intent.putExtra("com.google.zxing.client.android.SCAN.SCAN_MODE", "QR_CODE_MODE");
startActivityForResult(intent, 0);
What this code does is, scans the product and bring me back to the previous screen of my app. I haven't included the entire library from Zxing as I wanted the Barcode scanner to handle it, but it seems I have to do more than I already have done.
You need to make an onActivityResult method that will get the callback once barcode scanner is done. Inside there you will handle the code string and do whatever you like with it.
/*Here is where we come back after the Barcode Scanner is done*/
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == 0) {
if (resultCode == RESULT_OK) {
// contents contains whatever the code was
String contents = intent.getStringExtra("SCAN_RESULT");
// Format contains the type of code i.e. UPC, EAN, QRCode etc...
String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
// Handle successful scan
Log.i("TAG",format + "\t" + contents);
} else if (resultCode == RESULT_CANCELED) {
// Handle cancel. If the user presses 'back' before a code is scanned.
Log.i("TAG","Canceled");
}
}
}
This example just logs the results, you'll need to expand upon it to do whatever you want with the info you get back from the scanner.
Better still, use the IntentIntegrator class supplied with the project. It wraps up all the details listed here and its documentation already tells you exactly how to integrate it into your app. It deals with things for you like getting the app installed if not already.
In my onCreate method Im creating an webView and then loading an HTML file thats saved in my assets folder. This is all working fine. When a button is pressed it sends a call using javascript to this method to open the qr code scanner.
webView.setWebViewClient(new WebViewClient()
{
/* On Android 1.1 shouldOverrideUrlLoading() will be called every time the user clicks a link,
* but on Android 1.5 it will be called for every page load, even if it was caused by calling loadUrl()! */
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
System.out.println(url);
if (url.equals("fake://qr_scan"))
{
launchQRScanner(view);
}
return false;
}
});
Here is the method launchQRScanner()
public void launchQRScanner(View v) {
if (isCameraAvailable()) {
Intent intent = new Intent(this, ZBarScannerActivity.class);
intent.putExtra(ZBarConstants.SCAN_MODES, new int[]{Symbol.QRCODE});
startActivityForResult(intent, ZBAR_SCANNER_REQUEST);
} else {
Toast.makeText(this, "Rear Facing Camera Unavailable", Toast.LENGTH_SHORT).show();
}
}
So this works for the first time the button is pressed. The qr code reader open as an intent, it scans, disappears and returns the value correctly. But for every time after the method shouldOverrideUrlLoading() doesn't get called when the button is pressed. Possibly has something to do with leaving the app and coming back? Can't seem to figure it out.
BTW this is the project that I used to implement the qr code reader
https://github.com/DushyanthMaguluru/ZBarScanner
Fixed, Just had to reload the webView after the barcode is scanned. Simple fix.
var camera = {
settings : {
quality : 50,
targetWidth : 1024,
targetHeight : 1024,
correctOrientation : true
}
};
var error = function(message) {
alert("Error happened while trying to get a picture", message);
};
document.addEventListener("deviceready", function() {
camera.toFile = function() {
this.settings.destinationType = navigator.camera.DestinationType.FILE_URI;
return this;
},
camera.toBase64 = function() {
this.settings.destinationType = navigator.camera.DestinationType.DATA_URL;
return this;
},
camera.fromCamera = function() {
this.settings.sourceType = navigator.camera.PictureSourceType.CAMERA;
return this;
};
camera.fromLibrary = function() {
this.settings.sourceType = navigator.camera.PictureSourceType.PHOTOLIBRARY;
return this;
};
camera.fromPhotoAlbum = function() {
this.settings.sourceType = navigator.camera.PictureSourceType.SAVEDPHOTOALBUM;
return this;
}
camera.get = function(callback) {
navigator.camera.getPicture(function(data) {
alert("taking a picture successful");
callback(data);
}, error, camera.settings);
};
}, false);
This is my small wrapper for the camera. And I call it like this:
camera.fromPhotoAlbum().toBase64().get(function(base64){});
About 20% of the time, the "alert("taking a picture successful");" is not called, while no error is shown. If I cancel taking a picture, an alert with the message "Error happened while trying to get a picture" is shown, so the error callback works.
Basically nothing happens. I've tested it on a Samsung Galaxy S2 on CM9 and a brand new HTC One X.
There was another question recently about this same problem that I answered. We ran into this at my company and solved it. It has more to do with the Android system than Phonegap.
What's happening is when you start the camera, your app goes into onStop(). While there, the Android system has the right to kill your app if it needs memory. It just so happens that memory usually gets low when the camera takes a picture and dumps it into memory, so there's a good chance your app will get killed while your user takes a picture.
Now that your app is dead, when the camera finishes, it restarts your app. That's why it's acting so weird; the camera comes back into your app, but not the same instance that it had before, so your callback never gets called, since it doesn't exist anymore.
You can reduce the frequency at which this occurs by reducing the quality of the picture and passing it by URI instead of data to your app, but the problem won't go away completely.
To work around the callback never happening, we made a Java callback that starts the camera and saves the picture to the same location every time it takes one. Then, when the app starts back up from getting killed, it looks in that location for the picture.
It's a weird solution to a stupid problem, but if your app gets killed, that camera callback simply won't happen. If you need more information on how to make the Java callback to do this, let me know and I'll put our code up here. Otherwise, take a look at this SO answer for more info.
EDIT: Here's the code we use in our main DroidGap activity:
private static final String folderPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/appName";
private static final String filePath = "phonegapImage.jpg";
#Override
public void onCreate(Bundle savedState) {
//...The rest of onCreate, this makes the Java available in JavaScript
appView.addJavascriptInterface(this, "Camera");
}
public void takePhoto(final String callback) {
Log.v("Camera Plugin", "Starting takePhoto callback");
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(folderPath, filePath)));
startActivityForResult(intent, TAKE_PICTURE);
}
public String getPhotoUri() {
return Uri.fromFile(new File(folderPath, filePath)).toString();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case TAKE_PICTURE:
if (resultCode == Activity.RESULT_OK) {
//Do whatever you need to do when the camera returns
//This is after the picture is already saved, we return to the page
}
break;
default:
Log.v("Camera", "Something strange happened...");
break;
}
}
Then, in your JavaScript, you can invoke the camera with:
Camera.takePhoto("onPhotoURISuccess");
//Then, to get the location of the photo after you take it and load the page again
var imgPath = Camera.getPhotoUri();
So, that's about it. Just make sure to change all of the path/file/page/etc names to what you want to use in your app. This will overwrite that image every time a picture is taken, but you can probably figure something out to dynamically name them if you don't want that. You can use that URI just as you would any other path in your JavaScript.