Small updates and improvements to the Android client.
[zxing.git] / android / src / com / android / barcodes / QRCodeEncoder.java
1 /*
2  * Copyright (C) 2008 Google Inc.
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.android.barcodes;
18
19 import android.app.Activity;
20 import android.content.Intent;
21 import android.graphics.Bitmap;
22 import android.graphics.BitmapFactory;
23 import android.net.http.AndroidHttpClient;
24 import android.os.Bundle;
25 import android.os.Handler;
26 import android.os.Message;
27 import android.provider.Contacts;
28 import android.util.Log;
29 import org.apache.http.HttpEntity;
30 import org.apache.http.HttpResponse;
31 import org.apache.http.client.methods.HttpGet;
32
33 import java.net.URI;
34
35 public class QRCodeEncoder {
36
37     private static final String TAG = "QRCodeEncoder";
38     private static final String CHART_SERVER_URL = "//chart.apis.google.com/chart?cht=qr&chs=";
39
40     private Activity mActivity;
41     private String mContents;
42     private String mDisplayContents;
43     private String mTitle;
44     private NetworkThread mNetworkThread;
45
46     public QRCodeEncoder(Activity activity, Intent intent) {
47         mActivity = activity;
48         if (!encodeContents(intent)) {
49             throw new IllegalArgumentException("No valid data to encode.");
50         }
51     }
52
53     // Once the core ZXing library supports encoding, we'll be able to generate the bitmap
54     // synchronously. For now, it's a network request, so it's handled on a thread.
55     public void requestBarcode(Handler handler, int pixelResolution) {
56         mNetworkThread = new NetworkThread(mContents, handler, pixelResolution);
57         mNetworkThread.start();
58     }
59
60     public String getContents() {
61         return mContents;
62     }
63
64     public String getDisplayContents() {
65         return mDisplayContents;
66     }
67
68     public String getTitle() {
69         return mTitle;
70     }
71
72     // Perhaps the string encoding should live in the core ZXing library too.
73     private boolean encodeContents(Intent intent) {
74         if (intent == null) return false;
75         String type = intent.getStringExtra(Intents.Encode.TYPE);
76         if (type == null || type.length() == 0) return false;
77
78         if (type.equals(Contents.Type.TEXT)) {
79             String string = intent.getStringExtra(Intents.Encode.DATA);
80             if (string != null && string.length() > 0) {
81                 mContents = string;
82                 mDisplayContents = string;
83                 mTitle = mActivity.getString(R.string.contents_text);
84             }
85         } else if (type.equals(Contents.Type.EMAIL)) {
86             String string = intent.getStringExtra(Intents.Encode.DATA);
87             if (string != null && string.length() > 0) {
88                 mContents = "mailto:" + string;
89                 mDisplayContents = string;
90                 mTitle = mActivity.getString(R.string.contents_email);
91             }
92         } else if (type.equals(Contents.Type.PHONE)) {
93             String string = intent.getStringExtra(Intents.Encode.DATA);
94             if (string != null && string.length() > 0) {
95                 mContents = "tel:" + string;
96                 mDisplayContents = string;
97                 mTitle = mActivity.getString(R.string.contents_phone);
98             }
99         } else if (type.equals(Contents.Type.SMS)) {
100             String string = intent.getStringExtra(Intents.Encode.DATA);
101             if (string != null && string.length() > 0) {
102                 mContents = "sms:" + string;
103                 mDisplayContents = string;
104                 mTitle = mActivity.getString(R.string.contents_sms);
105             }
106         } else if (type.equals(Contents.Type.CONTACT)) {
107             Bundle bundle = intent.getBundleExtra(Intents.Encode.DATA);
108             if (bundle != null) {
109                 String name = bundle.getString(Contacts.Intents.Insert.NAME);
110                 if (name != null && !name.equals("")) {
111                     mContents = "MECARD:N:" + name + ";";
112                     mDisplayContents = name;
113                     String phone = bundle.getString(Contacts.Intents.Insert.PHONE);
114                     if (phone != null && !phone.equals("")) {
115                         mContents += "TEL:" + phone + ";";
116                         mDisplayContents += "\n" + phone;
117                     }
118                     String email = bundle.getString(Contacts.Intents.Insert.EMAIL);
119                     if (email != null && !email.equals("")) {
120                         mContents += "EMAIL:" + email + ";";
121                         mDisplayContents += "\n" + email;
122                     }
123                     mContents += ";";
124                     mTitle = mActivity.getString(R.string.contents_contact);
125                 }
126             }
127         } else if (type.equals(Contents.Type.LOCATION)) {
128             Bundle bundle = intent.getBundleExtra(Intents.Encode.DATA);
129             if (bundle != null) {
130                 float latitude = bundle.getFloat("LAT", Float.MAX_VALUE);
131                 float longitude = bundle.getFloat("LONG", Float.MAX_VALUE);
132                 if (latitude != Float.MAX_VALUE && longitude != Float.MAX_VALUE) {
133                     mContents = "geo:" + latitude + "," + longitude;
134                     mDisplayContents = latitude + "," + longitude;
135                     mTitle = mActivity.getString(R.string.contents_location);
136                 }
137             }
138         }
139         return mContents != null && mContents.length() > 0;
140     }
141
142     private class NetworkThread extends Thread {
143
144         private String mContents;
145         private Handler mHandler;
146         private int mPixelResolution;
147
148         public NetworkThread(String contents, Handler handler, int pixelResolution) {
149             mContents = contents;
150             mHandler = handler;
151             mPixelResolution = pixelResolution;
152         }
153
154         public void run() {
155             String url = CHART_SERVER_URL + mPixelResolution + "x" + mPixelResolution + "&chl=" +
156                     mContents;
157             try {
158                 URI uri = new URI("http", url, null);
159                 HttpGet get = new HttpGet(uri);
160                 AndroidHttpClient client = AndroidHttpClient.newInstance("Android-Barcodes/0.1");
161                 HttpResponse response = client.execute(get);
162                 HttpEntity entity = response.getEntity();
163                 Bitmap image = BitmapFactory.decodeStream(entity.getContent());
164                 if (image != null) {
165                     Message message = Message.obtain(mHandler, R.id.encode_succeeded);
166                     message.obj = image;
167                     message.sendToTarget();
168                 } else {
169                     Log.e(TAG, "Could not decode png from the network");
170                     Message message = Message.obtain(mHandler, R.id.encode_failed);
171                     message.sendToTarget();
172                 }
173             } catch (Exception e) {
174                 Log.e(TAG, e.toString());
175                 Message message = Message.obtain(mHandler, R.id.encode_failed);
176                 message.sendToTarget();
177             }
178         }
179     }
180
181 }