summaryrefslogtreecommitdiff
path: root/src/com/google/zxing/integration/android/IntentIntegrator.java
blob: 41b6dc5adbc538cf43f91c327072ec430fb531e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package com.google.zxing.integration.android;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import android.view.Display;
import com.google.zxing.client.android.Intents;

import java.lang.CharSequence;import java.lang.Math;import java.lang.String;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * TODO: update these docs - a lot of it is not relevant anymore.
 *
 * <p>A utility class which helps ease integration with Barcode Scanner via {@link android.content.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.</p>
 * <p/>
 * <h2>Initiating a barcode scan</h2>
 * <p/>
 * <p>Integration is essentially as easy as calling {@link #initiateScan(android.app.Activity)} and waiting
 * for the result in your app.</p>
 * <p/>
 * <p>It does require that the Barcode Scanner application is installed. The
 * {@link #initiateScan(android.app.Activity)} method will prompt the user to download the application, if needed.</p>
 * <p/>
 * <p>There are a few steps to using this integration. First, your {@link android.app.Activity} must implement
 * the method {@link android.app.Activity#onActivityResult(int, int, android.content.Intent)} and include a line of code like this:</p>
 * <p/>
 * <pre>{@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
 *   ...
 * }
 * }</pre>
 * <p/>
 * <p>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:</p>
 * <p/>
 * <pre>{@code IntentIntegrator.initiateScan(yourActivity);}</pre>
 * <p/>
 * <h2>Sharing text via barcode</h2>
 * <p/>
 * <p>To share text, encoded as a QR Code on-screen, similarly, see {@link #shareText(android.app.Activity, CharSequence)}.</p>
 * <p/>
 * <p>Some code, particularly download integration, was contributed from the Anobiit application.</p>
 *
 * @author Sean Owen
 * @author Fred Lin
 * @author Isaac Potoczny-Jones
 * @author Brad Drehmer
 * @author gcstang
 */
public final class IntentIntegrator {

    public static final int REQUEST_CODE = 0x0000c0de; // Only use bottom 16 bits
    private static final String TAG = IntentIntegrator.class.getSimpleName();

    private static final String PACKAGE = "com.google.zxing.client.android";

    // 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() {
    }

    public static void initiateScan(Activity activity) {
        initiateScan(activity, null);
    }


    public static void initiateScan(Activity activity, CharSequence stringDesiredBarcodeFormats) {
        initiateScan(activity, stringDesiredBarcodeFormats, null);
    }


    /**
     * Invokes scanning.
     *
     * @param stringDesiredBarcodeFormats a comma separated list of codes you would
     *                                    like to scan for.
     */
    public static void initiateScan(Activity activity, CharSequence stringDesiredBarcodeFormats, String prompt) {
        Intent intentScan = createScanIntent(activity);

        // check which types of codes to scan for
        if (stringDesiredBarcodeFormats != null) {
            // set the desired barcode types
            intentScan.putExtra("SCAN_FORMATS", stringDesiredBarcodeFormats);

            String formats = stringDesiredBarcodeFormats.toString();
            // Hack to use a wider viewfinder for CODE 39 barcodes. This should probably be in the main code instead.
            if (formats.contains("CODE_39") && !formats.contains(QR_CODE_TYPES)) {
                Display display = activity.getWindowManager().getDefaultDisplay();
                int displayWidth = display.getWidth();
                int displayHeight = display.getHeight();
                if (displayHeight > displayWidth) {
                    // This is portrait dimensions, but the barcode scanner is always in landscape mode.
                    int temp = displayWidth;
                    //noinspection SuspiciousNameCombination
                    displayWidth = displayHeight;
                    displayHeight = temp;
                }

                int desiredWidth = displayWidth * 9 / 10;
                int desiredHeight = Math.min(displayHeight * 3 / 4, 400);    // Limit to 400px

                intentScan.putExtra("SCAN_WIDTH", desiredWidth);
                intentScan.putExtra("SCAN_HEIGHT", desiredHeight);
            }
        }

        if (prompt != null) {
            intentScan.putExtra("PROMPT_MESSAGE", prompt);
        }
        intentScan.putExtra("RESULT_DISPLAY_DURATION_MS", 0L);


        activity.startActivityForResult(intentScan, REQUEST_CODE);
    }


    /**
     * <p>Call this from your {@link android.app.Activity}'s
     * {@link android.app.Activity#onActivityResult(int, int, android.content.Intent)} method.</p>
     *
     * @return null if the event handled here was not related to this class, 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;
    }

    /**
     * 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
     */
    public static void shareText(Activity activity, CharSequence text) {
        // TODO: fix this
        Intent intent = new Intent();
        intent.setAction(PACKAGE + ".ENCODE");

        intent.putExtra("ENCODE_TYPE", "TEXT_TYPE");
        intent.putExtra("ENCODE_DATA", text);

        activity.startActivity(intent);
    }

    private static Intent createScanIntent(Activity activity) {
        Intent intent = new Intent(activity, com.google.zxing.client.android.CaptureActivity.class);
        intent.setAction(Intents.Scan.ACTION);
        return intent;
    }
}