030af26a8b41386d4b7b2c245df39789d8ca94fd
[zxing.git] / android-integration / src / com / google / zxing / integration / android / IntentIntegrator.java
1 /*
2  * Copyright 2009 ZXing authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.google.zxing.integration.android;
18
19 import android.app.AlertDialog;
20 import android.app.Activity;
21 import android.content.ActivityNotFoundException;
22 import android.content.DialogInterface;
23 import android.content.Intent;
24 import android.net.Uri;
25
26 /**
27  * <p>A utility class which helps ease integration with Barcode Scanner via {@link Intent}s. This is a simple
28  * way to invoke barcode scanning and receive the result, without any need to integrate, modify, or learn the
29  * project's source code.</p>
30  *
31  * <h2>Initiating a barcode scan</h2>
32  *
33  * <p>Integration is essentially as easy as calling {@link #initiateScan(Activity)} and waiting
34  * for the result in your app.</p>
35  *
36  * <p>It does require that the Barcode Scanner application is installed. The
37  * {@link #initiateScan(Activity)} method will prompt the user to download the application, if needed.</p>
38  *
39  * <p>There are a few steps to using this integration. First, your {@link Activity} must implement
40  * the method {@link Activity#onActivityResult(int, int, Intent)} and include a line of code like this:</p>
41  *
42  * <p>{@code
43  * public void onActivityResult(int requestCode, int resultCode, Intent intent) {
44  *   IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
45  *   if (scanResult != null) {
46  *     // handle scan result
47  *   }
48  *   // else continue with any other code you need in the method
49  *   ...
50  * }
51  * }</p>
52  *
53  * <p>This is where you will handle a scan result.
54  * Second, just call this in response to a user action somewhere to begin the scan process:</p>
55  *
56  * <p>{@code IntentIntegrator.initiateScan(yourActivity);}</p>
57  *
58  * <p>You can use {@link #initiateScan(Activity, String, String, String, String)} or
59  * {@link #initiateScan(Activity, int, int, int, int)} to customize the download prompt with
60  * different text labels.</p>
61  *
62  * <h2>Sharing text via barcode</h2>
63  *
64  * <p>To share text, encoded as a QR Code on-screen, similarly, see {@link #shareText(Activity, String)}.</p>
65  *
66  * <p>Some code, particularly download integration, was contributed from the Anobiit application.</p>
67  *
68  * @author Sean Owen
69  * @author Fred Lin
70  * @author Isaac Potoczny-Jones
71  * @author Brad Drehmer
72  */
73 public final class IntentIntegrator {
74
75   public static final int REQUEST_CODE = 0x0ba7c0de; // get it?
76
77   public static final String DEFAULT_TITLE = "Install Barcode Scanner?";
78   public static final String DEFAULT_MESSAGE =
79       "This application requires Barcode Scanner. Would you like to install it?";
80   public static final String DEFAULT_YES = "Yes";
81   public static final String DEFAULT_NO = "No";
82
83   // supported barcode formats
84   public static final String PRODUCT_CODE_TYPES = "UPC_A,UPC_E,EAN_8,EAN_13";
85   public static final String ONE_D_CODE_TYPES = PRODUCT_CODE_TYPES + ",CODE_39,CODE_128";
86   public static final String QR_CODE_TYPES = "QR_CODE";
87   public static final String ALL_CODE_TYPES = null;
88
89   private IntentIntegrator() {
90   }
91
92   /**
93    * See {@link #initiateScan(Activity, String, String, String, String)} --
94    * same, but uses default English labels.
95    */
96   public static void initiateScan(Activity activity) {
97     initiateScan(activity, DEFAULT_TITLE, DEFAULT_MESSAGE, DEFAULT_YES, DEFAULT_NO);
98   }
99
100   /**
101    * See {@link #initiateScan(Activity, String, String, String, String)} --
102    * same, but takes string IDs which refer
103    * to the {@link Activity}'s resource bundle entries.
104    */
105   public static void initiateScan(Activity activity,
106                                   int stringTitle,
107                                   int stringMessage,
108                                   int stringButtonYes,
109                                   int stringButtonNo) {
110     initiateScan(activity,
111                  activity.getString(stringTitle),
112                  activity.getString(stringMessage),
113                  activity.getString(stringButtonYes),
114                  activity.getString(stringButtonNo));
115   }
116
117   /**
118    * See {@link #initiateScan(Activity, String, String, String, String, String)} --
119    * same, but scans for all supported barcode types.
120    * @param stringTitle title of dialog prompting user to download Barcode Scanner
121    * @param stringMessage text of dialog prompting user to download Barcode Scanner
122    * @param stringButtonYes text of button user clicks when agreeing to download
123    *  Barcode Scanner (e.g. "Yes")
124    * @param stringButtonNo text of button user clicks when declining to download
125    *  Barcode Scanner (e.g. "No")
126    */
127   public static void initiateScan(Activity activity,
128                                   String stringTitle,
129                                   String stringMessage,
130                                   String stringButtonYes,
131                                   String stringButtonNo) {
132
133           initiateScan(activity,
134                  stringTitle,
135                  stringMessage,
136                  stringButtonYes,
137                  stringButtonNo,
138                  ALL_CODE_TYPES);
139   }
140
141   /**
142    * Invokes scanning.
143    *
144    * @param stringTitle title of dialog prompting user to download Barcode Scanner
145    * @param stringMessage text of dialog prompting user to download Barcode Scanner
146    * @param stringButtonYes text of button user clicks when agreeing to download
147    *  Barcode Scanner (e.g. "Yes")
148    * @param stringButtonNo text of button user clicks when declining to download
149    *  Barcode Scanner (e.g. "No")
150    * @param stringDesiredBarcodeFormats a comma separated list of codes you would
151    *  like to scan for.
152    * @return the contents of the barcode that was scanned, or null if none was found
153    * @throws InterruptedException if timeout expires before a scan completes
154    */
155   public static void initiateScan(Activity activity,
156                                   String stringTitle,
157                                   String stringMessage,
158                                   String stringButtonYes,
159                                   String stringButtonNo,
160                                   String stringDesiredBarcodeFormats) {
161     Intent intentScan = new Intent("com.google.zxing.client.android.SCAN");
162     intentScan.addCategory(Intent.CATEGORY_DEFAULT);
163
164     // check which types of codes to scan for
165     if (stringDesiredBarcodeFormats != null) {
166         // set the desired barcode types
167         intentScan.putExtra("SCAN_FORMATS", stringDesiredBarcodeFormats);
168     }
169
170     try {
171       activity.startActivityForResult(intentScan, REQUEST_CODE);
172     } catch (ActivityNotFoundException e) {
173       showDownloadDialog(activity, stringTitle, stringMessage, stringButtonYes, stringButtonNo);
174     }
175   }
176
177   private static void showDownloadDialog(final Activity activity,
178                                          String stringTitle,
179                                          String stringMessage,
180                                          String stringButtonYes,
181                                          String stringButtonNo) {
182     AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity);
183     downloadDialog.setTitle(stringTitle);
184     downloadDialog.setMessage(stringMessage);
185     downloadDialog.setPositiveButton(stringButtonYes, new DialogInterface.OnClickListener() {
186       public void onClick(DialogInterface dialogInterface, int i) {
187         Uri uri = Uri.parse("market://search?q=pname:com.google.zxing.client.android");
188         Intent intent = new Intent(Intent.ACTION_VIEW, uri);
189         activity.startActivity(intent);
190       }
191     });
192     downloadDialog.setNegativeButton(stringButtonNo, new DialogInterface.OnClickListener() {
193       public void onClick(DialogInterface dialogInterface, int i) {}
194     });
195     downloadDialog.show();
196   }
197
198
199   /**
200    * <p>Call this from your {@link Activity}'s
201    * {@link Activity#onActivityResult(int, int, Intent)} method.</p>
202    *
203    * @return null if the event handled here was not related to {@link IntentIntegrator}, or
204    *  else an {@link IntentResult} containing the result of the scan. If the user cancelled scanning,
205    *  the fields will be null.
206    */
207   public static IntentResult parseActivityResult(int requestCode, int resultCode, Intent intent) {
208     if (requestCode == REQUEST_CODE) {
209       if (resultCode == Activity.RESULT_OK) {
210         String contents = intent.getStringExtra("SCAN_RESULT");
211         String formatName = intent.getStringExtra("SCAN_RESULT_FORMAT");
212         return new IntentResult(contents, formatName);
213       } else {
214         return new IntentResult(null, null);
215       }
216     }
217     return null;
218   }
219
220   /**
221    * See {@link #shareText(Activity, String, String, String, String, String)} --
222    * same, but uses default English labels.
223    */
224   public static void shareText(Activity activity, String text) {
225     shareText(activity, text, DEFAULT_TITLE, DEFAULT_MESSAGE, DEFAULT_YES, DEFAULT_NO);
226   }
227
228   /**
229    * See {@link #shareText(Activity, String, String, String, String, String)} --
230    * same, but takes string IDs which refer to the {@link Activity}'s resource bundle entries.
231    */
232   public static void shareText(Activity activity,
233                                String text,
234                                int stringTitle,
235                                int stringMessage,
236                                int stringButtonYes,
237                                int stringButtonNo) {
238     shareText(activity,
239               text,
240               activity.getString(stringTitle),
241               activity.getString(stringMessage),
242               activity.getString(stringButtonYes),
243               activity.getString(stringButtonNo));
244   }
245
246   /**
247    * Shares the given text by encoding it as a barcode, such that another user can
248    * scan the text off the screen of the device.
249    *
250    * @param text the text string to encode as a barcode
251    * @param stringTitle title of dialog prompting user to download Barcode Scanner
252    * @param stringMessage text of dialog prompting user to download Barcode Scanner
253    * @param stringButtonYes text of button user clicks when agreeing to download
254    *  Barcode Scanner (e.g. "Yes")
255    * @param stringButtonNo text of button user clicks when declining to download
256    *  Barcode Scanner (e.g. "No")
257    */
258   public static void shareText(Activity activity,
259                                String text,
260                                String stringTitle,
261                                String stringMessage,
262                                String stringButtonYes,
263                                String stringButtonNo) {
264
265     Intent intent = new Intent();
266     intent.setAction("com.google.zxing.client.android.ENCODE");
267     intent.putExtra("ENCODE_TYPE", "TEXT_TYPE");
268     intent.putExtra("ENCODE_DATA", text);
269     try {
270       activity.startActivity(intent);
271     } catch (ActivityNotFoundException e) {
272       showDownloadDialog(activity, stringTitle, stringMessage, stringButtonYes, stringButtonNo);
273     }
274   }
275
276 }