making stuff final, weakening types, etc. per IntelliJ analysis
[zxing.git] / android / src / com / google / zxing / client / android / result / ResultHandler.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.result;
18
19 import android.app.Activity;
20 import android.content.Intent;
21 import android.net.Uri;
22 import android.provider.Contacts;
23 import com.google.zxing.client.android.Intents;
24 import com.google.zxing.client.android.R;
25 import com.google.zxing.client.android.SearchBookContentsActivity;
26 import com.google.zxing.client.android.LocaleManager;
27 import com.google.zxing.client.result.ParsedResult;
28 import com.google.zxing.client.result.ParsedResultType;
29
30 import java.text.ParsePosition;
31 import java.text.SimpleDateFormat;
32 import java.util.Calendar;
33 import java.text.DateFormat;
34 import java.util.Date;
35 import java.util.GregorianCalendar;
36
37 public abstract class ResultHandler {
38
39   public static final int MAX_BUTTON_COUNT = 4;
40
41   protected final ParsedResult mResult;
42   private final Activity mActivity;
43
44   public ResultHandler(Activity activity, ParsedResult result) {
45     mResult = result;
46     mActivity = activity;
47   }
48
49   /**
50    * Indicates how many buttons the derived class wants shown.
51    *
52    * @return The integer button count.
53    */
54   public abstract int getButtonCount();
55
56   /**
57    * The text of the nth action button.
58    *
59    * @param index From 0 to getButtonCount() - 1
60    * @return The button text as a resource ID
61    */
62   public abstract int getButtonText(int index);
63
64
65   /**
66    * Execute the action which corresponds to the nth button.
67    *
68    * @param index The button that was clicked.
69    */
70   public abstract void handleButtonPress(int index);
71
72   /**
73    * Create a possibly styled string for the contents of the current barcode.
74    *
75    * @return The text to be displayed.
76    */
77   public CharSequence getDisplayContents() {
78     String contents = mResult.getDisplayResult();
79     return contents.replace("\r", "");
80   }
81
82   /**
83    * A string describing the kind of barcode that was found, e.g. "Found contact info".
84    *
85    * @return The resource ID of the string.
86    */
87   public abstract int getDisplayTitle();
88
89   /**
90    * A convenience method to get the parsed type. Should not be overridden.
91    *
92    * @return The parsed type, e.g. URI or ISBN
93    */
94   public final ParsedResultType getType() {
95     return mResult.getType();
96   }
97
98   /**
99    * Sends an intent to create a new calendar event by prepopulating the Add Event UI. Older
100    * versions of the system have a bug where the event title will not be filled out.
101    *
102    * @param summary A description of the event
103    * @param start   The start time as yyyyMMdd or yyyyMMdd'T'HHmmss or yyyyMMdd'T'HHmmss'Z'
104    * @param end     The end time as yyyyMMdd or yyyyMMdd'T'HHmmss or yyyyMMdd'T'HHmmss'Z'
105    */
106   public final void addCalendarEvent(String summary, String start, String end) {
107     Intent intent = new Intent(Intent.ACTION_EDIT);
108     intent.setType("vnd.android.cursor.item/event");
109     intent.putExtra("beginTime", calculateMilliseconds(start));
110     if (start.length() == 8) {
111       intent.putExtra("allDay", true);
112     }
113     intent.putExtra("endTime", calculateMilliseconds(end));
114     intent.putExtra("title", summary);
115     launchIntent(intent);
116   }
117
118   private long calculateMilliseconds(String when) {
119     if (when.length() == 8) {
120       // Only contains year/month/day
121       DateFormat format = new SimpleDateFormat("yyyyMMdd");
122       Date date = format.parse(when, new ParsePosition(0));
123       return date.getTime();
124     } else {
125       // The when string can be local time, or UTC if it ends with a Z
126       DateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
127       Date date = format.parse(when.substring(0, 15), new ParsePosition(0));
128       long milliseconds = date.getTime();
129       if (when.length() == 16 && when.charAt(15) == 'Z') {
130         Calendar calendar = new GregorianCalendar();
131         int offset = (calendar.get(java.util.Calendar.ZONE_OFFSET) +
132             calendar.get(java.util.Calendar.DST_OFFSET));
133         milliseconds += offset;
134       }
135       return milliseconds;
136     }
137   }
138
139   public final void addContact(String[] names, String[] phoneNumbers, String[] emails, String note,
140                          String address, String org, String title) {
141
142     Intent intent = new Intent(Contacts.Intents.Insert.ACTION, Contacts.People.CONTENT_URI);
143     putExtra(intent, Contacts.Intents.Insert.NAME, names);
144     putExtra(intent, Contacts.Intents.Insert.PHONE, phoneNumbers);
145     putExtra(intent, Contacts.Intents.Insert.EMAIL, emails);
146     putExtra(intent, Contacts.Intents.Insert.NOTES, note);
147     putExtra(intent, Contacts.Intents.Insert.POSTAL, address);
148     putExtra(intent, Contacts.Intents.Insert.COMPANY, org);
149     putExtra(intent, Contacts.Intents.Insert.JOB_TITLE, title);
150     launchIntent(intent);
151   }
152
153   public final void shareByEmail(String contents) {
154     sendEmailFromUri("mailto:", mActivity.getString(R.string.msg_share_subject_line), contents);
155   }
156
157   public final void sendEmail(String address, String subject, String body) {
158     sendEmailFromUri("mailto:" + address, subject, body);
159   }
160
161   public final void sendEmailFromUri(String uri, String subject, String body) {
162     Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse(uri));
163     putExtra(intent, "subject", subject);
164     putExtra(intent, "body", body);
165     launchIntent(intent);
166   }
167
168   public final void shareBySMS(String contents) {
169     sendSMSFromUri("smsto:", mActivity.getString(R.string.msg_share_subject_line) + ":\n" + contents);
170   }
171
172   public final void sendSMS(String phoneNumber, String body) {
173     sendSMSFromUri("smsto:" + phoneNumber, body);
174   }
175
176   public final void sendSMSFromUri(String uri, String body) {
177     Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse(uri));
178     putExtra(intent, "sms_body", body);
179     // Exit the app once the SMS is sent
180     intent.putExtra("compose_mode", true);
181     launchIntent(intent);
182   }
183
184   public final void sendMMS(String phoneNumber, String subject, String body) {
185     sendMMSFromUri("mmsto:" + phoneNumber, subject, body);
186   }
187
188   public final void sendMMSFromUri(String uri, String subject, String body) {
189     Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse(uri));
190     // The Messaging app needs to see a valid subject or else it will treat this an an SMS.
191     if (subject == null || subject.length() == 0) {
192       putExtra(intent, "subject", mActivity.getString(R.string.msg_default_mms_subject));
193     } else {
194       putExtra(intent, "subject", subject);
195     }
196     putExtra(intent, "sms_body", body);
197     intent.putExtra("compose_mode", true);
198     launchIntent(intent);
199   }
200
201   public final void dialPhone(String phoneNumber) {
202     launchIntent(new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber)));
203   }
204
205   public final void dialPhoneFromUri(String uri) {
206     launchIntent(new Intent(Intent.ACTION_DIAL, Uri.parse(uri)));
207   }
208
209   public final void openMap(String geoURI) {
210     launchIntent(new Intent(Intent.ACTION_VIEW, Uri.parse(geoURI)));
211   }
212
213   /**
214    * Do a geo search using the address as the query.
215    *
216    * @param address The address to find
217    * @param title An optional title, e.g. the name of the business at this address
218    */
219   public final void searchMap(String address, String title) {
220     String query = address;
221     if (title != null && title.length() > 0) {
222       query = query + " (" + title + ")";
223     }
224     launchIntent(new Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q=" + Uri.encode(query))));
225   }
226
227   public final void getDirections(float latitude, float longitude) {
228     launchIntent(new Intent(Intent.ACTION_VIEW,
229         Uri.parse("http://maps.google." + LocaleManager.getCountryTLD() + "/maps?f=d&daddr=" + latitude + "," + longitude)));
230   }
231
232   public final void openProductSearch(String upc) {
233     Uri uri = Uri.parse("http://www.google." + LocaleManager.getCountryTLD() + "/products?q=" + upc);
234     launchIntent(new Intent(Intent.ACTION_VIEW, uri));
235   }
236
237   public final void openBookSearch(String isbn) {
238     Uri uri = Uri.parse("http://books.google." + LocaleManager.getCountryTLD() + "/books?vid=isbn" + isbn);
239     launchIntent(new Intent(Intent.ACTION_VIEW, uri));
240   }
241
242   public final void searchBookContents(String isbn) {
243     Intent intent = new Intent(Intents.SearchBookContents.ACTION);
244     intent.setClassName(mActivity, SearchBookContentsActivity.class.getName());
245     putExtra(intent, Intents.SearchBookContents.ISBN, isbn);
246     launchIntent(intent);
247   }
248
249   public final void openURL(String url) {
250     launchIntent(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
251   }
252
253   public final void webSearch(String query) {
254     Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
255     intent.putExtra("query", query);
256     launchIntent(intent);
257   }
258
259   private void launchIntent(Intent intent) {
260     if (intent != null) {
261       mActivity.startActivity(intent);
262     }
263   }
264
265   private static void putExtra(Intent intent, String key, String value) {
266     if (value != null && value.length() > 0) {
267       intent.putExtra(key, value);
268     }
269   }
270
271   // TODO: The current Contacts Intent API can only accept one value for each field, so we pick the
272   // first element in the array for names, phone numbers, and emails. It would be great to fix this.
273   private static void putExtra(Intent intent, String key, String[] value) {
274     if (value != null && value.length > 0) {
275       putExtra(intent, key, value[0]);
276     }
277   }
278
279 }