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