From d42c4229fd57d11ba3436762f9413c470f729208 Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Sat, 22 Nov 2014 09:47:02 -0800 Subject: [PATCH] Update to latest zxing QR code scanner. Closes #2078 // FREEBIE --- build.gradle | 2 + .../zxing/integration/IntentIntegrator.java | 285 ------------------ .../zxing/integration/IntentResult.java | 48 --- .../securesms/KeyScanningActivity.java | 14 +- 4 files changed, 10 insertions(+), 339 deletions(-) delete mode 100644 libtextsecure/src/main/java/org/whispersystems/textsecure/zxing/integration/IntentIntegrator.java delete mode 100644 libtextsecure/src/main/java/org/whispersystems/textsecure/zxing/integration/IntentResult.java diff --git a/build.gradle b/build.gradle index 97ea38aec4..1736def16d 100644 --- a/build.gradle +++ b/build.gradle @@ -38,6 +38,7 @@ dependencies { compile 'com.github.chrisbanes.photoview:library:1.2.3' compile 'com.android.support:appcompat-v7:21.0.2' compile 'com.madgag.spongycastle:prov:1.51.0.0' + compile 'com.google.zxing:android-integration:3.1.0' compile ('com.android.support:support-v4-preferencefragment:1.0.0@aar'){ exclude module: 'support-v4' } @@ -62,6 +63,7 @@ dependencyVerification { 'com.github.chrisbanes.photoview:library:8b5344e206f125e7ba9d684008f36c4992d03853c57e5814125f88496126e3cc', 'com.android.support:appcompat-v7:b760fd3d0b0b0547a1bcef9031b40939f31049ba955f04c8fdc5aa09a25d19e9', 'com.madgag.spongycastle:prov:b8c3fec3a59aac1aa04ccf4dad7179351e54ef7672f53f508151b614c131398a', + 'com.google.zxing:android-integration:89e56aadf1164bd71e57949163c53abf90af368b51669c0d4a47a163335f95c4', 'com.android.support:support-v4-preferencefragment:5470f5872514a6226fa1fc6f4e000991f38805691c534cf0bd2778911fc773ad', 'com.squareup.dagger:dagger:789aca24537022e49f91fc6444078d9de8f1dd99e1bfb090f18491b186967883', 'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f', diff --git a/libtextsecure/src/main/java/org/whispersystems/textsecure/zxing/integration/IntentIntegrator.java b/libtextsecure/src/main/java/org/whispersystems/textsecure/zxing/integration/IntentIntegrator.java deleted file mode 100644 index b4a6116e4d..0000000000 --- a/libtextsecure/src/main/java/org/whispersystems/textsecure/zxing/integration/IntentIntegrator.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.whispersystems.textsecure.zxing.integration; - -import android.app.AlertDialog; -import android.app.Activity; -import android.content.ActivityNotFoundException; -import android.content.DialogInterface; -import android.content.Intent; -import android.net.Uri; - -/** - *

A utility class which helps ease integration with Barcode Scanner via {@link Intent}s. This is a simple - * way to invoke barcode scanning and receive the result, without any need to integrate, modify, or learn the - * project's source code.

- * - *

Initiating a barcode scan

- * - *

Integration is essentially as easy as calling {@link #initiateScan(Activity)} and waiting - * for the result in your app.

- * - *

It does require that the Barcode Scanner application is installed. The - * {@link #initiateScan(Activity)} method will prompt the user to download the application, if needed.

- * - *

There are a few steps to using this integration. First, your {@link Activity} must implement - * the method {@link Activity#onActivityResult(int, int, Intent)} and include a line of code like this:

- * - *

{@code - * public void onActivityResult(int requestCode, int resultCode, Intent intent) { - * IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent); - * if (scanResult != null) { - * // handle scan result - * } - * // else continue with any other code you need in the method - * ... - * } - * }

- * - *

This is where you will handle a scan result. - * Second, just call this in response to a user action somewhere to begin the scan process:

- * - *

{@code IntentIntegrator.initiateScan(yourActivity);}

- * - *

You can use {@link #initiateScan(Activity, CharSequence, CharSequence, CharSequence, CharSequence)} or - * {@link #initiateScan(Activity, int, int, int, int)} to customize the download prompt with - * different text labels.

- * - *

Note that {@link #initiateScan(Activity)} returns an {@link AlertDialog} which is non-null if the - * user was prompted to download the application. This lets the calling app potentially manage the dialog. - * In particular, ideally, the app dismisses the dialog if it's still active in its {@link Activity#onPause()} - * method.

- * - *

Sharing text via barcode

- * - *

To share text, encoded as a QR Code on-screen, similarly, see {@link #shareText(Activity, CharSequence)}.

- * - *

Some code, particularly download integration, was contributed from the Anobiit application.

- * - * @author Sean Owen - * @author Fred Lin - * @author Isaac Potoczny-Jones - * @author Brad Drehmer - */ -public final class IntentIntegrator { - - public static final int REQUEST_CODE = 0x0ba7c0de; // get it? - - public static final String DEFAULT_TITLE = "Install Barcode Scanner?"; - public static final String DEFAULT_MESSAGE = - "This application requires Barcode Scanner. Would you like to install it?"; - public static final String DEFAULT_YES = "Yes"; - public static final String DEFAULT_NO = "No"; - - // supported barcode formats - public static final String PRODUCT_CODE_TYPES = "UPC_A,UPC_E,EAN_8,EAN_13"; - public static final String ONE_D_CODE_TYPES = PRODUCT_CODE_TYPES + ",CODE_39,CODE_93,CODE_128"; - public static final String QR_CODE_TYPES = "QR_CODE"; - public static final String ALL_CODE_TYPES = null; - - private IntentIntegrator() { - } - - /** - * See {@link #initiateScan(Activity, CharSequence, CharSequence, CharSequence, CharSequence)} -- - * same, but uses default English labels. - */ - public static AlertDialog initiateScan(Activity activity) { - return initiateScan(activity, DEFAULT_TITLE, DEFAULT_MESSAGE, DEFAULT_YES, DEFAULT_NO); - } - - /** - * See {@link #initiateScan(Activity, CharSequence, CharSequence, CharSequence, CharSequence)} -- - * same, but takes string IDs which refer - * to the {@link Activity}'s resource bundle entries. - */ - public static AlertDialog initiateScan(Activity activity, - int stringTitle, - int stringMessage, - int stringButtonYes, - int stringButtonNo) { - return initiateScan(activity, - activity.getString(stringTitle), - activity.getString(stringMessage), - activity.getString(stringButtonYes), - activity.getString(stringButtonNo)); - } - - /** - * See {@link #initiateScan(Activity, CharSequence, CharSequence, CharSequence, CharSequence, CharSequence)} -- - * same, but scans for all supported barcode types. - * @param stringTitle title of dialog prompting user to download Barcode Scanner - * @param stringMessage text of dialog prompting user to download Barcode Scanner - * @param stringButtonYes text of button user clicks when agreeing to download - * Barcode Scanner (e.g. "Yes") - * @param stringButtonNo text of button user clicks when declining to download - * Barcode Scanner (e.g. "No") - * @return an {@link AlertDialog} if the user was prompted to download the app, - * null otherwise - */ - public static AlertDialog initiateScan(Activity activity, - CharSequence stringTitle, - CharSequence stringMessage, - CharSequence stringButtonYes, - CharSequence stringButtonNo) { - - return initiateScan(activity, - stringTitle, - stringMessage, - stringButtonYes, - stringButtonNo, - ALL_CODE_TYPES); - } - - /** - * Invokes scanning. - * - * @param stringTitle title of dialog prompting user to download Barcode Scanner - * @param stringMessage text of dialog prompting user to download Barcode Scanner - * @param stringButtonYes text of button user clicks when agreeing to download - * Barcode Scanner (e.g. "Yes") - * @param stringButtonNo text of button user clicks when declining to download - * Barcode Scanner (e.g. "No") - * @param stringDesiredBarcodeFormats a comma separated list of codes you would - * like to scan for. - * @return an {@link AlertDialog} if the user was prompted to download the app, - * null otherwise - * @throws InterruptedException if timeout expires before a scan completes - */ - public static AlertDialog initiateScan(Activity activity, - CharSequence stringTitle, - CharSequence stringMessage, - CharSequence stringButtonYes, - CharSequence stringButtonNo, - CharSequence stringDesiredBarcodeFormats) { - Intent intentScan = new Intent("com.google.zxing.client.android.SCAN"); - intentScan.addCategory(Intent.CATEGORY_DEFAULT); - - // check which types of codes to scan for - if (stringDesiredBarcodeFormats != null) { - // set the desired barcode types - intentScan.putExtra("SCAN_FORMATS", stringDesiredBarcodeFormats); - } - - try { - activity.startActivityForResult(intentScan, REQUEST_CODE); - return null; - } catch (ActivityNotFoundException e) { - return showDownloadDialog(activity, stringTitle, stringMessage, stringButtonYes, stringButtonNo); - } - } - - private static AlertDialog showDownloadDialog(final Activity activity, - CharSequence stringTitle, - CharSequence stringMessage, - CharSequence stringButtonYes, - CharSequence stringButtonNo) { - AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity); - downloadDialog.setTitle(stringTitle); - downloadDialog.setMessage(stringMessage); - downloadDialog.setPositiveButton(stringButtonYes, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialogInterface, int i) { - Uri uri = Uri.parse("market://search?q=pname:com.google.zxing.client.android"); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - activity.startActivity(intent); - } - }); - downloadDialog.setNegativeButton(stringButtonNo, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialogInterface, int i) {} - }); - return downloadDialog.show(); - } - - - /** - *

Call this from your {@link Activity}'s - * {@link Activity#onActivityResult(int, int, Intent)} method.

- * - * @return null if the event handled here was not related to {@link IntentIntegrator}, or - * else an {@link IntentResult} containing the result of the scan. If the user cancelled scanning, - * the fields will be null. - */ - public static IntentResult parseActivityResult(int requestCode, int resultCode, Intent intent) { - if (requestCode == REQUEST_CODE) { - if (resultCode == Activity.RESULT_OK) { - String contents = intent.getStringExtra("SCAN_RESULT"); - String formatName = intent.getStringExtra("SCAN_RESULT_FORMAT"); - return new IntentResult(contents, formatName); - } else { - return new IntentResult(null, null); - } - } - return null; - } - - /** - * See {@link #shareText(Activity, CharSequence, CharSequence, CharSequence, CharSequence, CharSequence)} -- - * same, but uses default English labels. - */ - public static void shareText(Activity activity, CharSequence text) { - shareText(activity, text, DEFAULT_TITLE, DEFAULT_MESSAGE, DEFAULT_YES, DEFAULT_NO); - } - - /** - * See {@link #shareText(Activity, CharSequence, CharSequence, CharSequence, CharSequence, CharSequence)} -- - * same, but takes string IDs which refer to the {@link Activity}'s resource bundle entries. - */ - public static void shareText(Activity activity, - CharSequence text, - int stringTitle, - int stringMessage, - int stringButtonYes, - int stringButtonNo) { - shareText(activity, - text, - activity.getString(stringTitle), - activity.getString(stringMessage), - activity.getString(stringButtonYes), - activity.getString(stringButtonNo)); - } - - /** - * 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 stringTitle title of dialog prompting user to download Barcode Scanner - * @param stringMessage text of dialog prompting user to download Barcode Scanner - * @param stringButtonYes text of button user clicks when agreeing to download - * Barcode Scanner (e.g. "Yes") - * @param stringButtonNo text of button user clicks when declining to download - * Barcode Scanner (e.g. "No") - */ - public static void shareText(Activity activity, - CharSequence text, - CharSequence stringTitle, - CharSequence stringMessage, - CharSequence stringButtonYes, - CharSequence stringButtonNo) { - - Intent intent = new Intent(); - intent.setAction("com.google.zxing.client.android.ENCODE"); - intent.putExtra("ENCODE_TYPE", "TEXT_TYPE"); - intent.putExtra("ENCODE_DATA", text); - try { - activity.startActivity(intent); - } catch (ActivityNotFoundException e) { - showDownloadDialog(activity, stringTitle, stringMessage, stringButtonYes, stringButtonNo); - } - } - -} diff --git a/libtextsecure/src/main/java/org/whispersystems/textsecure/zxing/integration/IntentResult.java b/libtextsecure/src/main/java/org/whispersystems/textsecure/zxing/integration/IntentResult.java deleted file mode 100644 index aed21cad1d..0000000000 --- a/libtextsecure/src/main/java/org/whispersystems/textsecure/zxing/integration/IntentResult.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2009 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.whispersystems.textsecure.zxing.integration; - -/** - *

Encapsulates the result of a barcode scan invoked through {@link IntentIntegrator}.

- * - * @author Sean Owen - */ -public final class IntentResult { - - private final String contents; - private final String formatName; - - IntentResult(String contents, String formatName) { - this.contents = contents; - this.formatName = formatName; - } - - /** - * @return raw content of barcode - */ - public String getContents() { - return contents; - } - - /** - * @return name of format, like "QR_CODE", "UPC_A". See BarcodeFormat for more format names. - */ - public String getFormatName() { - return formatName; - } - -} diff --git a/src/org/thoughtcrime/securesms/KeyScanningActivity.java b/src/org/thoughtcrime/securesms/KeyScanningActivity.java index dce93a2dfb..e892dd979c 100644 --- a/src/org/thoughtcrime/securesms/KeyScanningActivity.java +++ b/src/org/thoughtcrime/securesms/KeyScanningActivity.java @@ -23,13 +23,13 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.widget.Toast; +import com.google.zxing.integration.android.IntentIntegrator; +import com.google.zxing.integration.android.IntentResult; + import org.thoughtcrime.securesms.util.Base64; -import org.whispersystems.libaxolotl.IdentityKey; import org.thoughtcrime.securesms.util.Dialogs; import org.thoughtcrime.securesms.util.DynamicTheme; - -import org.whispersystems.textsecure.zxing.integration.IntentIntegrator; -import org.whispersystems.textsecure.zxing.integration.IntentResult; +import org.whispersystems.libaxolotl.IdentityKey; /** * Activity for initiating/receiving key QR code scans. @@ -99,11 +99,13 @@ public abstract class KeyScanningActivity extends PassphraseRequiredActionBarAct } protected void initiateScan() { - IntentIntegrator.initiateScan(this); + IntentIntegrator intentIntegrator = new IntentIntegrator(this); + intentIntegrator.initiateScan(); } protected void initiateDisplay() { - IntentIntegrator.shareText(this, Base64.encodeBytes(getIdentityKeyToDisplay().serialize())); + IntentIntegrator intentIntegrator = new IntentIntegrator(this); + intentIntegrator.shareText(Base64.encodeBytes(getIdentityKeyToDisplay().serialize())); } protected abstract String getScanString();