]> rtime.felk.cvut.cz Git - hornmich/skoda-qr-demo.git/blob - BarCodeScanner/mobile/src/main/java/cz/cvut/fel/dce/barcodescanner/share/ShareActivity.java
Initial commit
[hornmich/skoda-qr-demo.git] / BarCodeScanner / mobile / src / main / java / cz / cvut / fel / dce / barcodescanner / 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 cz.cvut.fel.dce.barcodescanner.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.BaseColumns;
26 import android.provider.Browser;
27 import android.provider.ContactsContract;
28 import android.util.Log;
29 import android.view.KeyEvent;
30 import android.view.View;
31 import android.widget.TextView;
32
33 import com.google.zxing.BarcodeFormat;
34 import cz.cvut.fel.dce.barcodescanner.Contents;
35 import cz.cvut.fel.dce.barcodescanner.Intents;
36 import cz.cvut.fel.dce.barcodescanner.R;
37 import cz.cvut.fel.dce.barcodescanner.clipboard.ClipboardInterface;
38
39 /**
40  * Barcode Scanner can share data like contacts and bookmarks by displaying a QR Code on screen,
41  * such that another user can scan the barcode with their phone.
42  *
43  * @author dswitkin@google.com (Daniel Switkin)
44  */
45 public final class ShareActivity extends Activity {
46
47   private static final String TAG = ShareActivity.class.getSimpleName();
48
49   private static final int PICK_BOOKMARK = 0;
50   private static final int PICK_CONTACT = 1;
51   private static final int PICK_APP = 2;
52
53   private View clipboardButton;
54
55   private final View.OnClickListener contactListener = new View.OnClickListener() {
56     @Override
57     public void onClick(View v) {
58       Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
59       intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
60       startActivityForResult(intent, PICK_CONTACT);
61     }
62   };
63
64   private final View.OnClickListener bookmarkListener = new View.OnClickListener() {
65     @Override
66     public void onClick(View v) {
67       Intent intent = new Intent(Intent.ACTION_PICK);
68       intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
69       intent.setClassName(ShareActivity.this, BookmarkPickerActivity.class.getName());
70       startActivityForResult(intent, PICK_BOOKMARK);
71     }
72   };
73
74   private final View.OnClickListener appListener = new View.OnClickListener() {
75     @Override
76     public void onClick(View v) {
77       Intent intent = new Intent(Intent.ACTION_PICK);
78       intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
79       intent.setClassName(ShareActivity.this, AppPickerActivity.class.getName());
80       startActivityForResult(intent, PICK_APP);
81     }
82   };
83
84   private final View.OnClickListener clipboardListener = new View.OnClickListener() {
85     @Override
86     public void onClick(View v) {
87       // Should always be true, because we grey out the clipboard button in onResume() if it's empty
88       CharSequence text = ClipboardInterface.getText(ShareActivity.this);
89       if (text != null) {
90         launchSearch(text.toString());
91       }
92     }
93   };
94
95   private final View.OnKeyListener textListener = new View.OnKeyListener() {
96     @Override
97     public boolean onKey(View view, int keyCode, KeyEvent event) {
98       if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_DOWN) {
99         String text = ((TextView) view).getText().toString();
100         if (text != null && !text.isEmpty()) {
101           launchSearch(text);
102         }
103         return true;
104       }
105       return false;
106     }
107   };
108
109   private void launchSearch(String text) {
110     Intent intent = new Intent(Intents.Encode.ACTION);
111     intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
112     intent.putExtra(Intents.Encode.TYPE, Contents.Type.TEXT);
113     intent.putExtra(Intents.Encode.DATA, text);
114     intent.putExtra(Intents.Encode.FORMAT, BarcodeFormat.QR_CODE.toString());
115     startActivity(intent);
116   }
117
118   @Override
119   public void onCreate(Bundle icicle) {
120     super.onCreate(icicle);
121     setContentView(R.layout.share);
122
123     findViewById(R.id.share_contact_button).setOnClickListener(contactListener);
124     findViewById(R.id.share_bookmark_button).setOnClickListener(bookmarkListener);
125     findViewById(R.id.share_app_button).setOnClickListener(appListener);
126     clipboardButton = findViewById(R.id.share_clipboard_button);
127     clipboardButton.setOnClickListener(clipboardListener);
128     findViewById(R.id.share_text_view).setOnKeyListener(textListener);
129   }
130
131   @Override
132   protected void onResume() {
133     super.onResume();
134     clipboardButton.setEnabled(ClipboardInterface.hasText(this));
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
179     Cursor cursor;
180     try {
181       // We're seeing about six reports a week of this exception although I don't understand why.
182       cursor = resolver.query(contactUri, null, null, null, null);
183     } catch (IllegalArgumentException ignored) {
184       return;
185     }
186     if (cursor == null) {
187       return;
188     }
189
190     String id;
191     String name;
192     boolean hasPhone;
193     try {
194       if (!cursor.moveToFirst()) {
195         return;
196       }
197
198       id = cursor.getString(cursor.getColumnIndex(BaseColumns._ID));
199       name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
200       hasPhone = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)) > 0;
201
202
203     } finally {
204       cursor.close();
205     }
206
207     // Don't require a name to be present, this contact might be just a phone number.
208     Bundle bundle = new Bundle();
209     if (name != null && !name.isEmpty()) {
210       bundle.putString(ContactsContract.Intents.Insert.NAME, massageContactData(name));
211     }
212
213     if (hasPhone) {
214       Cursor phonesCursor = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
215                                            null,
216                                            ContactsContract.CommonDataKinds.Phone.CONTACT_ID + '=' + id,
217                                            null,
218                                            null);
219       if (phonesCursor != null) {
220         try {
221           int foundPhone = 0;
222           int phonesNumberColumn = phonesCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
223           int phoneTypeColumn = phonesCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE);
224           while (phonesCursor.moveToNext() && foundPhone < Contents.PHONE_KEYS.length) {
225             String number = phonesCursor.getString(phonesNumberColumn);
226             if (number != null && !number.isEmpty()) {
227               bundle.putString(Contents.PHONE_KEYS[foundPhone], massageContactData(number));
228             }
229             int type = phonesCursor.getInt(phoneTypeColumn);
230             bundle.putInt(Contents.PHONE_TYPE_KEYS[foundPhone], type);
231             foundPhone++;
232           }
233         } finally {
234           phonesCursor.close();
235         }
236       }
237     }
238
239     Cursor methodsCursor = resolver.query(ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI,
240                                           null,
241                                           ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID + '=' + id,
242                                           null,
243                                           null);
244     if (methodsCursor != null) {
245       try {
246         if (methodsCursor.moveToNext()) {
247           String data = methodsCursor.getString(
248               methodsCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS));
249           if (data != null && !data.isEmpty()) {
250             bundle.putString(ContactsContract.Intents.Insert.POSTAL, massageContactData(data));
251           }
252         }
253       } finally {
254         methodsCursor.close();
255       }
256     }
257
258     Cursor emailCursor = resolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,
259                                         null,
260                                         ContactsContract.CommonDataKinds.Email.CONTACT_ID + '=' + id,
261                                         null,
262                                         null);
263     if (emailCursor != null) {
264       try {
265         int foundEmail = 0;
266         int emailColumn = emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA);
267         while (emailCursor.moveToNext() && foundEmail < Contents.EMAIL_KEYS.length) {
268           String email = emailCursor.getString(emailColumn);
269           if (email != null && !email.isEmpty()) {
270             bundle.putString(Contents.EMAIL_KEYS[foundEmail], massageContactData(email));
271           }
272           foundEmail++;
273         }
274       } finally {
275         emailCursor.close();
276       }
277     }
278
279     Intent intent = new Intent(Intents.Encode.ACTION);
280     intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
281     intent.putExtra(Intents.Encode.TYPE, Contents.Type.CONTACT);
282     intent.putExtra(Intents.Encode.DATA, bundle);
283     intent.putExtra(Intents.Encode.FORMAT, BarcodeFormat.QR_CODE.toString());
284
285     Log.i(TAG, "Sending bundle for encoding: " + bundle);
286     startActivity(intent);
287   }
288
289   private static String massageContactData(String data) {
290     // For now -- make sure we don't put newlines in shared contact data. It messes up
291     // any known encoding of contact data. Replace with space.
292     if (data.indexOf('\n') >= 0) {
293       data = data.replace("\n", " ");
294     }
295     if (data.indexOf('\r') >= 0) {
296       data = data.replace("\r", " ");
297     }
298     return data;
299   }
300 }