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