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