I am currently using the Zxing library in my app. After scanning the bar code of a book for example, how do I get things like the image, description, etc. from the scan result.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
switch(requestCode) {
case IntentIntegrator.REQUEST_CODE:
if (resultCode == RESULT_OK) {
IntentResult scanResult =
IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
} else if (resultCode == RESULT_CANCELED) {
showDialog("failed", "You messed up");
}
}
}
Thanks for your help
Zxing scans a variety of barcodes/QR codes, so the first thing you need to do is figure out if its a product UPC or a QR code:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (data != null) {
String response = data.getAction();
if(Pattern.matches("[0-9]{1,13}", response)) {
// response is a UPC code, fetch product meta data
// using Google Products API, Best Buy Remix, etc.
} else {
// QR code - phone #, url, location, email, etc.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(response));
startActivity(intent);
}
}
}
There are a number of web services available that will return product meta data given a UPC code. A fairly comprehensive one would be Google's Search API for Shopping. For example, you can get a json representations of the product with UPC = 037988482481 with an URL that looks like this:
https://www.googleapis.com/shopping/search/v1/public/products?country=US&key=your_key_here&restrictBy=gtin:037988482481
You'll need to replace "your_key_here" with your Google API key.
Best Buy also offers a RESTful products API for all of the products they carry which is searchable by UPC code.
You'll want to use an AsyncTask to fetch the product metadata once you have the UPC.
You dont need the 'IntentResult' or 'IntentIntegrator' for that.
You can do this:
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.putExtra("SCAN_MODE", "PRODUCT_MODE");
startActivityForResult(intent, 0);
And then in onActivityResult:
if (requestCode == 0) {
if ((resultCode == RESULT_CANCELED) || (resultCode == -1000)) {
Toast.makeText(WebViewActivity.this, "Nothing captured",
Toast.LENGTH_SHORT).show();
} else {
String capturedQrValue = data.getStringExtra("barcode_data");
}
}
With this you scan the barcode, now there is in the Zxing code another library that uses Google API for looking up that ISBN.
In the class Intents.java you have the info of what extras the intent needs and the class ISBNResultHandler shows what is the result.
Hope it helps someone in the future.
You can check what the Android ZXing app does. The source for the Android client is in: ZXing Android client source code. For ISBN numbers, the source code for handling that is: Android ZXing app's ISBN Result Handler code
For product and book search, the Android code invokes these two functions from ResultHandler.java:
// Uses the mobile-specific version of Product Search, which is formatted for small screens.
final void openProductSearch(String upc) {
Uri uri = Uri.parse("http://www.google." + LocaleManager.getProductSearchCountryTLD() +
"/m/products?q=" + upc + "&source=zxing");
launchIntent(new Intent(Intent.ACTION_VIEW, uri));
}
final void openBookSearch(String isbn) {
Uri uri = Uri.parse("http://books.google." + LocaleManager.getBookSearchCountryTLD() +
"/books?vid=isbn" + isbn);
launchIntent(new Intent(Intent.ACTION_VIEW, uri));
}
In your onActivityResult do like following code
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if(result != null) {
if(result.getContents() == null) {
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
} else {
String qrCode=result.getContents();
}
} else {
// This is important, otherwise the result will not be passed to the fragment
super.onActivityResult(requestCode, resultCode, data);
}
You haven't called result.getContents().
I just want to add that if you want to be able to press back without a RuntimeException surround your if statement with a try catch block. so:
try{
/// get scanned code here
} catch(RuntimeException e) {
e.getStackTrace();
{
Hope that helped the inevitable crash you would face without it.
Related
Is there a way to send a string to google now and get a response?
Example:
send "What time is it?" and get a string or audio response from google that says "It is 4:32pm."
String question = "What time is it?";
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(question);
startActivityForResult(intent, REQ_CODE_SPEECH_INPUT);
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQ_CODE_SPEECH_INPUT: {
if (resultCode == RESULT_OK && null != data) {
ArrayList<String> result = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
String converted_text = result.get(0);
}
break;
}
}
}
You should analyze the question by your self and get the answer and send it back using the TextToSpeech. For your example : You analyzed the string you find "Time" and you get the time from Android system and you send back the time as string to TextToSpeech.
I am integrating card.io in my app for reading information of debit/credit card. I have integrated it successfully but it is always getting card number but not expiry, CVV and display.It sometimes get expiry date but it never gets card holder name and cvv. And further more if I want to change theme I mean text fields and button backgrounds are those possible as library classes not editable. Below is the code I am using for intent i.e,
private void readCardInfo() {
Intent scanIntent = new Intent(getActivity(), CardIOActivity.class);
scanIntent.putExtra(CardIOActivity.EXTRA_REQUIRE_EXPIRY, true);
scanIntent.putExtra(CardIOActivity.EXTRA_REQUIRE_CVV, true);
scanIntent.putExtra(CardIOActivity.EXTRA_REQUIRE_CARDHOLDER_NAME, true);
startActivityForResult(scanIntent, MY_SCAN_REQUEST_CODE);
}
and below is the code I am using for getting data on onActivityResult();
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == MY_SCAN_REQUEST_CODE ){
if (data != null && data.hasExtra(CardIOActivity.EXTRA_SCAN_RESULT)) {
CreditCard scanResult = data.getParcelableExtra(CardIOActivity.EXTRA_SCAN_RESULT);
cardNumber = scanResult.getFormattedCardNumber();
if (scanResult.isExpiryValid()) {
expiryDate = scanResult.expiryMonth + "/" + scanResult.expiryYear;
LogHelper.debugLog("expiry date is " + expiryDate);
setExpiryDate(expiryDate);
}
if (scanResult.cvv != null) {
codeCVV = scanResult.cvv;
tvCVV.setText(codeCVV);
}
if (scanResult.cardholderName != null) {
cardHolderName = scanResult.cardholderName;
etNameOnCard.setText(cardHolderName);
}
setCardNumber(cardNumber);
}
}
}
Am I doing wrong something or missing any step?
Sorry for late replied But if someone face same problem then it will helpful
EXTRA_KEEP_APPLICATION_THEME
public static final String EXTRA_KEEP_APPLICATION_THEME
Boolean extra. Optional. If this value is set to true, and the application has a theme, the theme for the card.io Activitys will be set to the theme of the application.
pass EXTRA_KEEP_APPLICATION_THEME constant in intent extra and set boolean value to true.
I am trying to use the Google Places API and I would like to filter my search to only gym types.
I am using the code given at https://developers.google.com/places/
public void onPickButtonClick(View v) {
// Construct an intent for the place picker
try {
PlacePicker.IntentBuilder intentBuilder =
new PlacePicker.IntentBuilder();
Intent intent = intentBuilder.build(this);
// Start the intent by requesting a result,
// identified by a request code.
startActivityForResult(intent, REQUEST_PLACE_PICKER);
} catch (GooglePlayServicesRepairableException e) {
// ...
} catch (GooglePlayServicesNotAvailableException e) {
// ...
}
}
#Override
protected void onActivityResult(int requestCode,
int resultCode, Intent data) {
if (requestCode == REQUEST_PLACE_PICKER
&& resultCode == Activity.RESULT_OK) {
// The user has selected a place. Extract the name and address.
final Place place = PlacePicker.getPlace(data, this);
final CharSequence name = place.getName();
final CharSequence address = place.getAddress();
String attributions = PlacePicker.getAttributions(data);
if (attributions == null) {
attributions = "";
}
mViewName.setText(name);
mViewAddress.setText(address);
mViewAttributions.setText(Html.fromHtml(attributions));
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
What I was trying to do was to create a filter like below and somehow add that (placeFilter) to the intent.
PlacePicker.IntentBuilder intentBuilder = new PlacePicker.IntentBuilder();
PlaceFilter placeFilter;
ArrayList<String> restictToGyms = new ArrayList<>();
restictToGyms.add("44");
placeFilter = new PlaceFilter(false, restictToGyms);
intent.SOMEHOWADD(placeFilter);
Intent intent = intentBuilder.build(this);
But I am not sure how to add this filter to the intent. In fact I am not sure if this is the right way of doing it. Any pointers will be appreciated. Thanks!
I've been looking to do the same thing. Unfortunately it doesn't seem possible- the PlaceFilter takes place ids, not types. The class PlaceFilter is final so it cannot be extended (I hate it when API writers make classes final, there's almost never a reason to do it). You need to actually make the call and do the filtering via a loop after the result returns.
Refer to this https://developer.android.com/reference/com/google/android/gms/location/places/Place.html
Gym is Place.TYPE_GYM
I am developing an application in cordova but my barcode scanner from Zxing opens and closes Automatically after scanning the product in need to add a scan/exit button and a close button the scanner shouldnt open and close automatically. I also need to check if the scanned product exist in the database (SQL SERVER) and return product infomation i have tried to google but to no avail please help.the following is my code in Eclipse. I need to know how i can modify The UI and add my own control of my ZXING barcode scanner plugin i am developing in Eclipse and have a web api service hosted in IIS which i can access on my android App.Please ASAP or show me how i can modify this barcode UI to ADD my controls.
public void scan() {
Intent intentScan = new Intent(SCAN_INTENT);
intentScan.addCategory(Intent.CATEGORY_DEFAULT);
this.cordova.startActivityForResult((CordovaPlugin) this, intentScan, REQUEST_CODE);
}
My OnStartActivity code is here is the code but it seems like it is the same as yours.
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
JSONObject obj = new JSONObject();
try {
obj.put(TEXT, intent.getStringExtra("SCAN_RESULT"));
obj.put(FORMAT, intent.getStringExtra("SCAN_RESULT_FORMAT"));
obj.put(CANCELLED, false);
} catch (JSONException e) {
Log.d(LOG_TAG, "This should never happen");
}
//this.success(new PluginResult(PluginResult.Status.OK, obj), this.callback);
this.callbackContext.success(obj);
} else if (resultCode == Activity.RESULT_CANCELED) {
JSONObject obj = new JSONObject();
try {
obj.put(TEXT, "");
obj.put(FORMAT, "");
obj.put(CANCELLED, true);
} catch (JSONException e) {
Log.d(LOG_TAG, "This should never happen");
}
//this.success(new PluginResult(PluginResult.Status.OK, obj), this.callback);
this.callbackContext.success(obj);
} else {
//this.error(new PluginResult(PluginResult.Status.ERROR), this.callback);
this.callbackContext.error("Unexpected error");
}
}
}
Good Afternoon I have an app that do what you are looking for... first of all I create an intent so i can use any QR scanner I use an external app in order to get the value of the QR code here.
public void scanNow(View view) {
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.putExtra("com.google.zxing.client.android.SCAN.SCAN_MODE", "QR_CODE_MODE");
startActivityForResult(intent, 0);
}
so in my onStartActivity for result send that info to the server side and I wait for the answer...
public void onActivityResult(int requestCode, int resultCode, Intent intent){
if(requestCode == 0){
if(resultCode == RESULT_OK){
contents = intent.getStringExtra("SCAN_RESULT");// here is the content of the qr scanner
String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
String messLoc = "Visita Guardada Con Exito";
Log.i("xZing", "contents: " + contents + " format: " + format);// Handle successful scan
Toast.makeText(this, messLoc, Toast.LENGTH_LONG).show();
new Thread(new Task()).start(); // here I start the thread for the connection
return;
}
else if(resultCode == RESULT_CANCELED);{// Handle cancel
Log.i("xZing", "Cancelled");
}
}
}
Please let me know if this help you
UPDATE:
I just started using Zbar instead Zxing. It's a whole lot easier to work with. Extremely easy to embed (no 3rd party app for the scanner). It has a lot let file to load into the project. Also, it has an included example that you can pretty much copy and paste into your code. The example is perfect for what you are trying to do and would only require a few edits to gain the functions you are looking for. So try using the zbar library.
Zbar - https://github.com/dm77/ZBarScanner
A tutorial - http://community.magicsoftware.com/en/library?book=en/Magicxpa/&page=Android_Barcode_Scanning_(Using_ZBar_SDK)_Sample.htm
The tutorial isn't that good but it helps with setting it up. NOTE: the links they have don't work if you click them..you have to copy and paste the text into your browser.
The database stuff I explained below still is relevant but ignore the parts about zxing.
Best of luck to you!
Original answer
I may be able to help somewhat for you SQL issues. Do you have any database helper set up?
First off I would google around and find a simply database example to set up the database. There are a number of good ones out there that show you how to set up a database in SQLite for android. The one I used to learn some of the basics:http://hmkcode.com/android-simple-sqlite-database-tutorial/ . You can use the example of Book to create a product class with all the values for columns that match your needs. Then you simply create automatic getters and setters with eclipse click "Source -> generate getters and setters". Onces you've done that you can use the tutorial below to set up your qr scanner. As for keeping the window open, I don't think you need to do that. Just create an activity that the scanner closes into. In that acticity you can have the output and have the scan results compared to the database.
I was able to use the tutorial http://%20http://code.tutsplus.com/tutorials/android-sdk-create-a-barcode-reader--mobile-17162 to integrate zxing into my app. Once I did that
An example of parsing the data from the qr code:
First you call the scan:
public void onClick(View v){
//respond to clicks
if(v.getId()==R.id.scanQRButton){
//scan
IntentIntegrator scanIntegrator = new IntentIntegrator(this);
scanIntegrator.initiateScan();
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
startActivityForResult(intent, 0);
The scan results code then looks like this:
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
//retrieve scan result
IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (scanningResult != null) {
//we have a result
scanContent = scanningResult.getContents();
}
else{
Toast toast = Toast.makeText(getApplicationContext(),
"No scan data received!", Toast.LENGTH_SHORT);
toast.show();
}
}
Now the finishing method for the scan button:
public void onClick(View v){
//respond to clicks
if(v.getId()==R.id.scanQRButton){
//scan
IntentIntegrator scanIntegrator = new IntentIntegrator(this);
scanIntegrator.initiateScan();
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
startActivityForResult(intent, 0);
formatTxt.setText( "Scan Initiated");
contentTxt.setText(" Scan Results: " + scanContent);
if(scanContent != null){
String userid,medname,tabstaken,dob;
// Here I am breaking apart the scan results and
//saving them into variables.
//Do this then call the database for your product and compare
StringTokenizer st = new StringTokenizer(scanContent, ",");
// token 0
dob = st.nextToken();
//token 1
medname = st.nextToken();
//token 2
tabstaken = st.nextToken();
//token 3
//rxnumber
// So here you setup the db so you can access it
DatabaseHandler db = new DatabaseHandler(getApplicationContext());
//This is used to call the results
HashMap<String,String> user = new HashMap<String, String>();
//Use a method such as getProductResults() for your case
user = db.getUserDetails();
enter code here
//An example of me storing the user
userid = user.get("uid");
//debug.setText("Userid: "+ userid+ " medname: " + medname + " tabs: " +tabstaken);
UserLogEntry userlog = new UserLogEntry(getApplicationContext(),userid,medname,tabstaken);
userlog.addUserLog();
}
}
}
If you need to see my database class let me know. Obviously this isn't the exact code you need, but it shows you how to use the results from the QR and call the DB results to do comparisons. Hopefully its helpful
I hope I'll be clear enough.
In my app, I have set it so that pressing the back button activates google's voice recognition service. In the onActivityResult, it checks whether the first word is "call" or "text" and proceed accordingly with the rest of the spoken sentence. For text specifically, it goes like "text [contact name] message [message content]" and then sends it using an smsManager. But since it might get the name or the message wrong, I want it to read out the message and the person's name first for confirmation which I did just fine.
The problem is, to confirm or cancel, I want to also use voice recognition. If after the message is read out, the user says something like send and only then it should proceed to send the message. So, what I need to know is how/if can I implement this (newVoiceCommand) in the code below:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case RESULT_SPEECH: {
if (resultCode == RESULT_OK && null != data) {
s="";
text = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
decide = text.get(0).split("\\s");
for (int i=1; i<decide.length;i++) s= s+decide[i] + " ";
if (decide [0].equals("text")){
if (!s.equals("")){
msg = s.split(" message");
char[] stringArray = msg[0].toCharArray();
stringArray[0] = Character.toUpperCase(stringArray[0]);
msg[0] = new String(stringArray);
contact = get_Number (test(msg[0]));
Intent intent = getIntent();
finish();
startActivity(intent);
String temp = "Are you sure you want to send " + msg[1] + " to " + test(msg[0]);
speakOut (temp);
if (newVoiceCommand.equals("send")){
try {
SmsManager smsManager = SmsManager.getDefault();
out.append(contact);
smsManager.sendTextMessage(contact, null, msg[1], null, null);
Toast.makeText(getApplicationContext(), "SMS Sent! to "+msg[0] + " at " +contact,
Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(getApplicationContext(),
"SMS faild, please try again later!",
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
else if (newVoiceCommand.equals("no")) out.append("Not sending");
}
}
else if (decide[0].equals("call")){
out.append (s);
if (!s.equals("")) {
call (s);
}
}
}
break;
}
}
}
My current attempt:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case RESULT_SPEECH: {
if (resultCode == RESULT_OK && null != data) {
s="";
//Grab the speech results and save them in an arraylist
text = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
//Split each word into an array item
decide = text.get(0).split("\\s");
//Re-concatenate the words starting with the second word together
for (int i=1; i<decide.length;i++) s= s+decide[i] + " ";
//If the first word is "text", then send an SMS using the rest of the information spoken
if (decide [0].equals("text")){
if (!s.equals("")){
check (s);
Intent spIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
spIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "en_US");
try {
startActivityForResult(spIntent, RESULT_SPEECH2);
} catch (ActivityNotFoundException a) {
Toast t = Toast.makeText(getApplicationContext(),
"Opps! Your device doesn't support Speech to Text",
Toast.LENGTH_SHORT);
t.show();
}
switch (requestCode) {
case RESULT_SPEECH2: {
if (resultCode == RESULT_OK && null != data) {
text2 = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
s2 = "";
if (text2.get(0).equals("send")){
smsText (s);
}
else if (text2.get(0).equals("cancel")) return;
}
}
In short, all of the voice recognition results are going to come to you through an asynchronous call to onActivityResult. You don't block and wait for the result, so you need a way to determine whether the recognition is in response to a command or a confirmation at the time you receive the result.
This is what the requestCode parameter of Activity.startActivityForResult() is for:
Sometimes you want to get a result back from an activity when it ends.
For example, you may start an activity that lets the user pick a
person in a list of contacts; when it ends, it returns the person that
was selected. To do this, you call the startActivityForResult(Intent,
int) version with a second integer parameter identifying the call. The
result will come back through your onActivityResult(int, int, Intent)
method.
If you use two different values for requestCode (e.g., define private final static int REQUEST_SPEECH_COMMAND = 1, REQUEST_SPEECH_CONFIRMATION = 2) when you start the voice recognition activity, you can respond differently in onActivityResult. Note that you'll need to store the results of the first voice recognition (the action, message, and recipient) so this information will be available the second time around.