eead5e58c0c3a16ebffa32a15e94988073f3302f
[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.os.Bundle;
23 import android.os.Handler;
24 import android.os.Message;
25 import android.provider.Contacts;
26 import android.util.Log;
27 import com.google.zxing.BarcodeFormat;
28 import com.google.zxing.MultiFormatWriter;
29 import com.google.zxing.WriterException;
30 import com.google.zxing.common.ByteMatrix;
31
32 public final class QRCodeEncoder {
33
34   private static final String TAG = "QRCodeEncoder";
35
36   private final Activity mActivity;
37   private String mContents;
38   private String mDisplayContents;
39   private String mTitle;
40
41   public QRCodeEncoder(Activity activity, Intent intent) {
42     mActivity = activity;
43     if (!encodeContents(intent)) {
44       throw new IllegalArgumentException("No valid data to encode.");
45     }
46   }
47
48   public void requestBarcode(Handler handler, int pixelResolution) {
49     Thread encodeThread = new EncodeThread(mContents, handler, pixelResolution);
50     encodeThread.start();
51   }
52
53   public String getContents() {
54     return mContents;
55   }
56
57   public String getDisplayContents() {
58     return mDisplayContents;
59   }
60
61   public String getTitle() {
62     return mTitle;
63   }
64
65   // TODO: The string encoding should live in the core ZXing library.
66   private boolean encodeContents(Intent intent) {
67     if (intent == null) return false;
68     String type = intent.getStringExtra(Intents.Encode.TYPE);
69     if (type == null || type.length() == 0) return false;
70
71     if (type.equals(Contents.Type.TEXT)) {
72       String string = intent.getStringExtra(Intents.Encode.DATA);
73       if (string != null && string.length() > 0) {
74         mContents = string;
75         mDisplayContents = string;
76         mTitle = mActivity.getString(R.string.contents_text);
77       }
78     } else if (type.equals(Contents.Type.EMAIL)) {
79       String string = intent.getStringExtra(Intents.Encode.DATA);
80       if (string != null && string.length() > 0) {
81         mContents = "mailto:" + string;
82         mDisplayContents = string;
83         mTitle = mActivity.getString(R.string.contents_email);
84       }
85     } else if (type.equals(Contents.Type.PHONE)) {
86       String string = intent.getStringExtra(Intents.Encode.DATA);
87       if (string != null && string.length() > 0) {
88         mContents = "tel:" + string;
89         mDisplayContents = string;
90         mTitle = mActivity.getString(R.string.contents_phone);
91       }
92     } else if (type.equals(Contents.Type.SMS)) {
93       String string = intent.getStringExtra(Intents.Encode.DATA);
94       if (string != null && string.length() > 0) {
95         mContents = "sms:" + string;
96         mDisplayContents = string;
97         mTitle = mActivity.getString(R.string.contents_sms);
98       }
99     } else if (type.equals(Contents.Type.CONTACT)) {
100       Bundle bundle = intent.getBundleExtra(Intents.Encode.DATA);
101       if (bundle != null) {
102         String name = bundle.getString(Contacts.Intents.Insert.NAME);
103         if (name != null && name.length() > 0) {
104           mContents = "MECARD:N:" + name + ";";
105           mDisplayContents = name;
106           String address = bundle.getString(Contacts.Intents.Insert.POSTAL);
107           if (address != null && address.length() > 0) {
108             mContents += "ADR:" + address + ";";
109             mDisplayContents += "\n" + address;
110           }
111           String phone = bundle.getString(Contacts.Intents.Insert.PHONE);
112           if (phone != null && phone.length() > 0) {
113             mContents += "TEL:" + phone + ";";
114             mDisplayContents += "\n" + phone;
115           }
116           String email = bundle.getString(Contacts.Intents.Insert.EMAIL);
117           if (email != null && email.length() > 0) {
118             mContents += "EMAIL:" + email + ";";
119             mDisplayContents += "\n" + email;
120           }
121           mContents += ";";
122           mTitle = mActivity.getString(R.string.contents_contact);
123         }
124       }
125     } else if (type.equals(Contents.Type.LOCATION)) {
126       Bundle bundle = intent.getBundleExtra(Intents.Encode.DATA);
127       if (bundle != null) {
128         float latitude = bundle.getFloat("LAT", Float.MAX_VALUE);
129         float longitude = bundle.getFloat("LONG", Float.MAX_VALUE);
130         if (latitude != Float.MAX_VALUE && longitude != Float.MAX_VALUE) {
131           mContents = "geo:" + latitude + "," + longitude;
132           mDisplayContents = latitude + "," + longitude;
133           mTitle = mActivity.getString(R.string.contents_location);
134         }
135       }
136     }
137     return mContents != null && mContents.length() > 0;
138   }
139
140   private final static class EncodeThread extends Thread {
141
142     private final String mContents;
143     private final Handler mHandler;
144     private final int mPixelResolution;
145
146     public EncodeThread(String contents, Handler handler, int pixelResolution) {
147       mContents = contents;
148       mHandler = handler;
149       mPixelResolution = pixelResolution;
150     }
151
152     public final void run() {
153       try {
154         ByteMatrix result = new MultiFormatWriter().encode(mContents, BarcodeFormat.QR_CODE,
155              mPixelResolution, mPixelResolution);
156         int width = result.width();
157         int height = result.height();
158         byte[][] array = result.getArray();
159         int[] pixels = new int[width * height];
160         for (int y = 0; y < height; y++) {
161           for (int x = 0; x < width; x++) {
162             int grey = array[y][x] & 0xff;
163             pixels[y * width + x] = (0xff << 24) | (grey << 16) | (grey << 8) | grey;
164           }
165         }
166
167         Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
168         bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
169         Message message = Message.obtain(mHandler, R.id.encode_succeeded);
170         message.obj = bitmap;
171         message.sendToTarget();
172       } catch (WriterException e) {
173         Log.e(TAG, e.toString());
174         Message message = Message.obtain(mHandler, R.id.encode_failed);
175         message.sendToTarget();
176       } catch (IllegalArgumentException e) {
177         Log.e(TAG, e.toString());
178         Message message = Message.obtain(mHandler, R.id.encode_failed);
179         message.sendToTarget();
180       }
181     }
182   }
183
184 }