Skip to content

Commit

Permalink
Updated to lates ZXing integration code.
Browse files Browse the repository at this point in the history
  • Loading branch information
phw committed Sep 2, 2013
1 parent 877d789 commit be3580f
Showing 1 changed file with 106 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.app.AlertDialog;
Expand All @@ -29,6 +31,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;

/**
Expand Down Expand Up @@ -75,9 +78,13 @@
* <p>You can use {@link #setTitle(String)} to customize the title of this download prompt dialog (or, use
* {@link #setTitleByID(int)} to set the title by string resource ID.) Likewise, the prompt message, and
* yes/no button labels can be changed.</p>
*
* <p>Finally, you can use {@link #addExtra(String, Object)} to add more parameters to the Intent used
* to invoke the scanner. This can be used to set additional options not directly exposed by this
* simplified API.</p>
*
* <p>By default, this will only allow applications that are known to respond to this intent correctly
* do so. The apps that are allowed to response can be set with {@link #setTargetApplications(Collection)}.
* do so. The apps that are allowed to response can be set with {@link #setTargetApplications(List)}.
* For example, set to {@link #TARGET_BARCODE_SCANNER_ONLY} to only target the Barcode Scanner app itself.</p>
*
* <h2>Sharing text via barcode</h2>
Expand All @@ -86,6 +93,13 @@
*
* <p>Some code, particularly download integration, was contributed from the Anobiit application.</p>
*
* <h2>Enabling experimental barcode formats</h2>
*
* <p>Some formats are not enabled by default even when scanning with {@link #ALL_CODE_TYPES}, such as
* PDF417. Use {@link #initiateScan(java.util.Collection)} with
* a collection containing the names of formats to scan for explicitly, like "PDF_417", to use such
* formats.</p>
*
* @author Sean Owen
* @author Fred Lin
* @author Isaac Potoczny-Jones
Expand All @@ -104,6 +118,7 @@ public class IntentIntegrator {
public static final String DEFAULT_NO = "No";

private static final String BS_PACKAGE = "com.google.zxing.client.android";
private static final String BSPLUS_PACKAGE = "com.srowen.bs.android";

// supported barcode formats
public static final Collection<String> PRODUCT_CODE_TYPES = list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "RSS_14");
Expand All @@ -115,20 +130,21 @@ public class IntentIntegrator {

public static final Collection<String> ALL_CODE_TYPES = null;

public static final Collection<String> TARGET_BARCODE_SCANNER_ONLY = Collections.singleton(BS_PACKAGE);
public static final Collection<String> TARGET_ALL_KNOWN = list(
BS_PACKAGE, // Barcode Scanner
"com.srowen.bs.android", // Barcode Scanner+
"com.srowen.bs.android.simple" // Barcode Scanner+ Simple
// TODO add more -- what else supports this intent?
public static final List<String> TARGET_BARCODE_SCANNER_ONLY = Collections.singletonList(BS_PACKAGE);
public static final List<String> TARGET_ALL_KNOWN = list(
BSPLUS_PACKAGE, // Barcode Scanner+
BSPLUS_PACKAGE + ".simple", // Barcode Scanner+ Simple
BS_PACKAGE // Barcode Scanner
// What else supports this intent?
);

private final Activity activity;
private String title;
private String message;
private String buttonYes;
private String buttonNo;
private Collection<String> targetApplications;
private List<String> targetApplications;
private final Map<String,Object> moreExtras;

public IntentIntegrator(Activity activity) {
this.activity = activity;
Expand All @@ -137,6 +153,7 @@ public IntentIntegrator(Activity activity) {
buttonYes = DEFAULT_YES;
buttonNo = DEFAULT_NO;
targetApplications = TARGET_ALL_KNOWN;
moreExtras = new HashMap<String,Object>(3);
}

public String getTitle() {
Expand Down Expand Up @@ -191,27 +208,41 @@ public Collection<String> getTargetApplications() {
return targetApplications;
}

public void setTargetApplications(Collection<String> targetApplications) {
public final void setTargetApplications(List<String> targetApplications) {
if (targetApplications.isEmpty()) {
throw new IllegalArgumentException("No target applications");
}
this.targetApplications = targetApplications;
}

public void setSingleTargetApplication(String targetApplication) {
this.targetApplications = Collections.singleton(targetApplication);
this.targetApplications = Collections.singletonList(targetApplication);
}

public Map<String,?> getMoreExtras() {
return moreExtras;
}

public final void addExtra(String key, Object value) {
moreExtras.put(key, value);
}

/**
* Initiates a scan for all known barcode types.
*/
public AlertDialog initiateScan() {
public final AlertDialog initiateScan() {
return initiateScan(ALL_CODE_TYPES);
}

/**
* Initiates a scan only for a certain set of barcode types, given as strings corresponding
* to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants
* like {@link #PRODUCT_CODE_TYPES} for example.
*
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise
*/
public AlertDialog initiateScan(Collection<String> desiredBarcodeFormats) {
public final AlertDialog initiateScan(Collection<String> desiredBarcodeFormats) {
Intent intentScan = new Intent(BS_PACKAGE + ".SCAN");
intentScan.addCategory(Intent.CATEGORY_DEFAULT);

Expand All @@ -235,13 +266,13 @@ public AlertDialog initiateScan(Collection<String> desiredBarcodeFormats) {
intentScan.setPackage(targetAppPackage);
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
attachMoreExtras(intentScan);
startActivityForResult(intentScan, REQUEST_CODE);
return null;
}

/**
* Start an activity.<br>
* This method is defined to allow different methods of activity starting for
* Start an activity. This method is defined to allow different methods of activity starting for
* newer versions of Android and for compatibility library.
*
* @param intent Intent to start.
Expand All @@ -257,15 +288,24 @@ private String findTargetAppPackage(Intent intent) {
PackageManager pm = activity.getPackageManager();
List<ResolveInfo> availableApps = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (availableApps != null) {
for (ResolveInfo availableApp : availableApps) {
String packageName = availableApp.activityInfo.packageName;
if (targetApplications.contains(packageName)) {
return packageName;
for (String targetApp : targetApplications) {
if (contains(availableApps, targetApp)) {
return targetApp;
}
}
}
return null;
}

private static boolean contains(Iterable<ResolveInfo> availableApps, String targetApp) {
for (ResolveInfo availableApp : availableApps) {
String packageName = availableApp.activityInfo.packageName;
if (targetApp.equals(packageName)) {
return true;
}
}
return false;
}

private AlertDialog showDownloadDialog() {
AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity);
Expand All @@ -274,13 +314,14 @@ private AlertDialog showDownloadDialog() {
downloadDialog.setPositiveButton(buttonYes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Uri uri = Uri.parse("market://details?id=" + BS_PACKAGE);
String packageName = targetApplications.get(0);
Uri uri = Uri.parse("market://details?id=" + packageName);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
try {
activity.startActivity(intent);
} catch (ActivityNotFoundException anfe) {
// Hmm, market is not installed
Log.w(TAG, "Android Market is not installed; cannot install Barcode Scanner");
Log.w(TAG, "Google Play is not installed; cannot install " + packageName);
}
}
});
Expand Down Expand Up @@ -321,31 +362,66 @@ public static IntentResult parseActivityResult(int requestCode, int resultCode,
}


/**
* Defaults to type "TEXT_TYPE".
* @see #shareText(CharSequence, CharSequence)
*/
public final AlertDialog shareText(CharSequence text) {
return shareText(text, "TEXT_TYPE");
}

/**
* Shares the given text by encoding it as a barcode, such that another user can
* scan the text off the screen of the device.
*
* @param text the text string to encode as a barcode
* @param type type of data to encode. See {@code com.google.zxing.client.android.Contents.Type} constants.
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise
*/
public void shareText(CharSequence text) {
public final AlertDialog shareText(CharSequence text, CharSequence type) {
Intent intent = new Intent();
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setAction(BS_PACKAGE + ".ENCODE");
intent.putExtra("ENCODE_TYPE", "TEXT_TYPE");
intent.putExtra("ENCODE_TYPE", type);
intent.putExtra("ENCODE_DATA", text);
String targetAppPackage = findTargetAppPackage(intent);
if (targetAppPackage == null) {
showDownloadDialog();
} else {
intent.setPackage(targetAppPackage);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
activity.startActivity(intent);
return showDownloadDialog();
}
intent.setPackage(targetAppPackage);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
attachMoreExtras(intent);
activity.startActivity(intent);
return null;
}

private static Collection<String> list(String... values) {
return Collections.unmodifiableCollection(Arrays.asList(values));
private static List<String> list(String... values) {
return Collections.unmodifiableList(Arrays.asList(values));
}

private void attachMoreExtras(Intent intent) {
for (Map.Entry<String,Object> entry : moreExtras.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// Kind of hacky
if (value instanceof Integer) {
intent.putExtra(key, (Integer) value);
} else if (value instanceof Long) {
intent.putExtra(key, (Long) value);
} else if (value instanceof Boolean) {
intent.putExtra(key, (Boolean) value);
} else if (value instanceof Double) {
intent.putExtra(key, (Double) value);
} else if (value instanceof Float) {
intent.putExtra(key, (Float) value);
} else if (value instanceof Bundle) {
intent.putExtra(key, (Bundle) value);
} else {
intent.putExtra(key, value.toString());
}
}
}

}

0 comments on commit be3580f

Please sign in to comment.