Added small android-integration module
[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  * <p>Integration is essentially as easy as calling {@link #initiateScan(Activity)} and waiting
32  * for the result in your app.</p>
33  *
34  * <p>It does require that the Barcode Scanner application is installed. The
35  * {@link #initiateScan(Activity)} method will prompt the user to download the application, if needed.</p>
36  *
37  * <p>There are a few steps to using this integration. First, your {@link Activity} must implement
38  * the method {@link Activity#onActivityResult(int, int, Intent)} and include a line of code like this:</p>
39  *
40  * <p>{@code
41  * public void onActivityResult(int requestCode, int resultCode, Intent intent) {
42  *   IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
43  *   if (scanResult != null) {
44  *     // handle scan result
45  *   }
46  *   // else continue with any other code you need in the method
47  *   ...
48  * }
49  * }</p>
50  *
51  * <p>This is where you will handle a scan result.
52  * Second, just call this in response to a user action somewhere to begin the scan process:</p>
53  *
54  * <p>{@code integrator.initiateScan();}</p>
55  *
56  * <p>You can use {@link #initiateScan(Activity, String, String, String, String)} or
57  * {@link #initiateScan(Activity, int, int, int, int)} to customize the download prompt with
58  * different text labels.</p>
59  *
60  * <p>Some code, particularly download integration, was contributed from the Anobiit application.</p>
61  *
62  * @author Sean Owen
63  * @author Fred Lin
64  */
65 public final class IntentIntegrator {
66
67   public static final int REQUEST_CODE = 0x0ba7c0de; // get it?
68
69   private IntentIntegrator() {
70   }
71
72   /**
73    * See {@link #initiateScan(Activity, String, String, String, String)} -- same, but uses default English labels.
74    */
75   public static void initiateScan(Activity activity) {
76     initiateScan(activity,
77                  "Install Barcode Scanner?",
78                  "This application requires Barcode Scanner. Would you like to install it?",
79                  "Yes",
80                  "No");
81   }
82
83   /**
84    * See {@link #initiateScan(Activity, String, String, String, String)} -- same, but takes string IDs which refer
85    * to the {@link Activity}'s resource bundle entries.
86    */
87   public static void initiateScan(Activity activity,
88                                   int stringTitle,
89                                   int stringMessage,
90                                   int stringButtonYes,
91                                   int stringButtonNo) {
92     initiateScan(activity,
93                  activity.getString(stringTitle),
94                  activity.getString(stringMessage),
95                  activity.getString(stringButtonYes),
96                  activity.getString(stringButtonNo));
97   }
98
99   /**
100    * Invokes scanning.
101    *
102    * @param stringTitle title of dialog prompting user to download Barcode Scanner
103    * @param stringMessage text of dialog prompting user to download Barcode Scanner
104    * @param stringButtonYes text of button user clicks when agreeing to download Barcode Scanner (e.g. "Yes")
105    * @param stringButtonNo text of button user clicks when declining to download Barcode Scanner (e.g. "No")
106    * @return the contents of the barcode that was scanned, or null if none was found
107    * @throws InterruptedException if timeout expires before a scan completes
108    */
109   public static void initiateScan(Activity activity,
110                                   String stringTitle,
111                                   String stringMessage,
112                                   String stringButtonYes,
113                                   String stringButtonNo) {
114     Intent intentScan = new Intent("com.google.zxing.client.android.SCAN");
115     intentScan.addCategory(Intent.CATEGORY_DEFAULT);
116     try {
117       activity.startActivityForResult(intentScan, REQUEST_CODE);
118     } catch (ActivityNotFoundException e) {
119       showDownloadDialog(activity, stringTitle, stringMessage, stringButtonYes, stringButtonNo);
120     }
121   }
122
123   private static void showDownloadDialog(final Activity activity,
124                                          String stringTitle,
125                                          String stringMessage,
126                                          String stringButtonYes,
127                                          String stringButtonNo) {
128     AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity);
129     downloadDialog.setTitle(stringTitle);
130     downloadDialog.setMessage(stringMessage);
131     downloadDialog.setPositiveButton(stringButtonYes, new DialogInterface.OnClickListener() {
132       public void onClick(DialogInterface dialogInterface, int i) {
133         Uri uri = Uri.parse("market://search?q=pname:com.google.zxing.client.android");
134         Intent intent = new Intent(Intent.ACTION_VIEW, uri);
135         activity.startActivity(intent);
136       }
137     });
138     downloadDialog.setNegativeButton(stringButtonNo, new DialogInterface.OnClickListener() {
139       public void onClick(DialogInterface dialogInterface, int i) {}
140     });
141     downloadDialog.show();
142   }
143
144
145   /**
146    * <p>Call this from your {@link Activity}'s {@link Activity#onActivityResult(int, int, Intent)} method.</p>
147    *
148    * @return null if the event handled here was not related to {@link IntentIntegrator}, or
149    *  else an {@link IntentResult} containing the result of the scan. If the user cancelled scanning,
150    *  the fields will be null.
151    */
152   public static IntentResult parseActivityResult(int requestCode, int resultCode, Intent intent) {
153     if (requestCode == REQUEST_CODE) {
154       if (resultCode == Activity.RESULT_OK) {
155         String contents = intent.getStringExtra("SCAN_RESULT");
156         String formatName = intent.getStringExtra("SCAN_RESULT_FORMAT");
157         return new IntentResult(contents, formatName);
158       } else {
159         return new IntentResult(null, null);
160       }
161     }
162     return null;
163   }
164
165 }