Small style stuff
[zxing.git] / android / src / com / google / zxing / client / android / share / ShareActivity.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.share;
18
19 import android.app.Activity;
20 import android.content.ContentResolver;
21 import android.content.Intent;
22 import android.database.Cursor;
23 import android.net.Uri;
24 import android.os.Bundle;
25 import android.provider.Browser;
26 import android.provider.Contacts;
27 import android.provider.BaseColumns;
28 import android.text.ClipboardManager;
29 import android.util.Log;
30 import android.view.View;
31 import android.widget.Button;
32 import com.google.zxing.BarcodeFormat;
33 import com.google.zxing.client.android.Intents;
34 import com.google.zxing.client.android.Contents;
35 import com.google.zxing.client.android.R;
36
37 /**
38  * Barcode Scanner can share data like contacts and bookmarks by displaying a QR Code on screen,
39  * such that another user can scan the barcode with their phone.
40  *
41  * @author dswitkin@google.com (Daniel Switkin)
42  */
43 public final class ShareActivity extends Activity {
44
45   private static final String TAG = ShareActivity.class.getSimpleName();
46
47   private static final int PICK_BOOKMARK = 0;
48   private static final int PICK_CONTACT = 1;
49   private static final int PICK_APP = 2;
50
51   //private static final int METHODS_ID_COLUMN = 0;
52   private static final int METHODS_KIND_COLUMN = 1;
53   private static final int METHODS_DATA_COLUMN = 2;
54
55   private static final String[] METHODS_PROJECTION = {
56       BaseColumns._ID, // 0
57       Contacts.ContactMethodsColumns.KIND, // 1
58       Contacts.ContactMethodsColumns.DATA, // 2
59   };
60
61   private static final int PHONES_NUMBER_COLUMN = 1;
62
63   private static final String[] PHONES_PROJECTION = {
64       BaseColumns._ID, // 0
65       Contacts.PhonesColumns.NUMBER // 1
66   };
67
68   private Button clipboardButton;
69
70   private final Button.OnClickListener contactListener = new Button.OnClickListener() {
71     public void onClick(View v) {
72       Intent intent = new Intent(Intent.ACTION_PICK, Contacts.People.CONTENT_URI);
73       intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
74       startActivityForResult(intent, PICK_CONTACT);
75     }
76   };
77
78   private final Button.OnClickListener bookmarkListener = new Button.OnClickListener() {
79     public void onClick(View v) {
80       Intent intent = new Intent(Intent.ACTION_PICK);
81       intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
82       intent.setClassName(ShareActivity.this, BookmarkPickerActivity.class.getName());
83       startActivityForResult(intent, PICK_BOOKMARK);
84     }
85   };
86
87   private final Button.OnClickListener appListener = new Button.OnClickListener() {
88     public void onClick(View v) {
89       Intent intent = new Intent(Intent.ACTION_PICK);
90       intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
91       intent.setClassName(ShareActivity.this, AppPickerActivity.class.getName());
92       startActivityForResult(intent, PICK_APP);
93     }
94   };
95
96   private final Button.OnClickListener clipboardListener = new Button.OnClickListener() {
97     public void onClick(View v) {
98       ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
99       // Should always be true, because we grey out the clipboard button in onResume() if it's empty
100       if (clipboard.hasText()) {
101         Intent intent = new Intent(Intents.Encode.ACTION);
102         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
103         intent.putExtra(Intents.Encode.TYPE, Contents.Type.TEXT);
104         intent.putExtra(Intents.Encode.DATA, clipboard.getText().toString());
105         intent.putExtra(Intents.Encode.FORMAT, BarcodeFormat.QR_CODE.toString());
106         startActivity(intent);
107       }
108     }
109   };
110
111   @Override
112   public void onCreate(Bundle icicle) {
113     super.onCreate(icicle);
114     setContentView(R.layout.share);
115
116     findViewById(R.id.contact_button).setOnClickListener(contactListener);
117     findViewById(R.id.bookmark_button).setOnClickListener(bookmarkListener);
118     findViewById(R.id.app_button).setOnClickListener(appListener);
119     clipboardButton = (Button) findViewById(R.id.clipboard_button);
120     clipboardButton.setOnClickListener(clipboardListener);
121   }
122
123   @Override
124   protected void onResume() {
125     super.onResume();
126
127     ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
128     if (clipboard.hasText()) {
129       clipboardButton.setEnabled(true);
130       clipboardButton.setText(R.string.button_share_clipboard);
131     } else {
132       clipboardButton.setEnabled(false);
133       clipboardButton.setText(R.string.button_clipboard_empty);
134     }
135   }
136
137   @Override
138   public void onActivityResult(int requestCode, int resultCode, Intent intent) {
139     if (resultCode == RESULT_OK) {
140       switch (requestCode) {
141         case PICK_BOOKMARK:
142         case PICK_APP:
143           showTextAsBarcode(intent.getStringExtra(Browser.BookmarkColumns.URL));
144           break;
145         case PICK_CONTACT:
146           // Data field is content://contacts/people/984
147           showContactAsBarcode(intent.getData());
148           break;
149       }
150     }
151   }
152
153   private void showTextAsBarcode(String text) {
154     Log.i(TAG, "Showing text as barcode: " + text);    
155     if (text == null) {
156       return; // Show error?
157     }
158     Intent intent = new Intent(Intents.Encode.ACTION);
159     intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
160     intent.putExtra(Intents.Encode.TYPE, Contents.Type.TEXT);
161     intent.putExtra(Intents.Encode.DATA, text);
162     intent.putExtra(Intents.Encode.FORMAT, BarcodeFormat.QR_CODE.toString());
163     startActivity(intent);
164   }
165
166   /**
167    * Takes a contact Uri and does the necessary database lookups to retrieve that person's info,
168    * then sends an Encode intent to render it as a QR Code.
169    *
170    * @param contactUri A Uri of the form content://contacts/people/17
171    */
172   private void showContactAsBarcode(Uri contactUri) {
173     Log.i(TAG, "Showing contact URI as barcode: " + contactUri);
174     if (contactUri == null) {
175       return; // Show error?
176     }
177     ContentResolver resolver = getContentResolver();
178     Cursor contactCursor = resolver.query(contactUri, null, null, null, null);
179     Bundle bundle = new Bundle();
180     if (contactCursor != null && contactCursor.moveToFirst()) {
181       int nameColumn = contactCursor.getColumnIndex(Contacts.PeopleColumns.NAME);
182       String name = contactCursor.getString(nameColumn);
183
184       // Don't require a name to be present, this contact might be just a phone number.
185       if (name != null && name.length() > 0) {
186         bundle.putString(Contacts.Intents.Insert.NAME, massageContactData(name));
187       }
188       contactCursor.close();
189
190       Uri phonesUri = Uri.withAppendedPath(contactUri, Contacts.People.Phones.CONTENT_DIRECTORY);
191       Cursor phonesCursor = resolver.query(phonesUri, PHONES_PROJECTION, null, null, null);
192       if (phonesCursor != null) {
193         int foundPhone = 0;
194         while (phonesCursor.moveToNext()) {
195           String number = phonesCursor.getString(PHONES_NUMBER_COLUMN);
196           if (foundPhone < Contents.PHONE_KEYS.length) {
197             bundle.putString(Contents.PHONE_KEYS[foundPhone], massageContactData(number));
198             foundPhone++;
199           }
200         }
201         phonesCursor.close();
202       }
203
204       Uri methodsUri = Uri.withAppendedPath(contactUri,
205           Contacts.People.ContactMethods.CONTENT_DIRECTORY);
206       Cursor methodsCursor = resolver.query(methodsUri, METHODS_PROJECTION, null, null, null);
207       if (methodsCursor != null) {
208         int foundEmail = 0;
209         boolean foundPostal = false;
210         while (methodsCursor.moveToNext()) {
211           int kind = methodsCursor.getInt(METHODS_KIND_COLUMN);
212           String data = methodsCursor.getString(METHODS_DATA_COLUMN);
213           switch (kind) {
214             case Contacts.KIND_EMAIL:
215               if (foundEmail < Contents.EMAIL_KEYS.length) {
216                 bundle.putString(Contents.EMAIL_KEYS[foundEmail], massageContactData(data));
217                 foundEmail++;
218               }
219               break;
220             case Contacts.KIND_POSTAL:
221               if (!foundPostal) {
222                 bundle.putString(Contacts.Intents.Insert.POSTAL, massageContactData(data));
223                 foundPostal = true;
224               }
225               break;
226           }
227         }
228         methodsCursor.close();
229       }
230
231       Intent intent = new Intent(Intents.Encode.ACTION);
232       intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);      
233       intent.putExtra(Intents.Encode.TYPE, Contents.Type.CONTACT);
234       intent.putExtra(Intents.Encode.DATA, bundle);
235       intent.putExtra(Intents.Encode.FORMAT, BarcodeFormat.QR_CODE.toString());
236
237       Log.i(TAG, "Sending bundle for encoding: " + bundle);
238       startActivity(intent);
239     }
240   }
241
242   private static String massageContactData(String data) {
243     // For now -- make sure we don't put newlines in shared contact data. It messes up
244     // any known encoding of contact data. Replace with space.
245     if (data.indexOf('\n') >= 0) {
246       data = data.replace("\n", " ");
247     }
248     if (data.indexOf('\r') >= 0) {
249       data = data.replace("\r", " ");
250     }
251     return data;
252   }
253 }