AI2 Component  (Version nb184)
PhoneNumberPicker.java
Go to the documentation of this file.
1 // -*- mode: java; c-basic-offset: 2; -*-
2 // Copyright 2009-2011 Google, All Rights reserved
3 // Copyright 2011-2012 MIT, All rights reserved
4 // Released under the Apache License, Version 2.0
5 // http://www.apache.org/licenses/LICENSE-2.0
6 
7 package com.google.appinventor.components.runtime;
8 
19 
20 import android.app.Activity;
21 import android.content.ContentUris;
22 import android.content.Intent;
23 import android.database.Cursor;
24 import android.net.Uri;
25 import android.provider.Contacts;
26 import android.util.Log;
27 
28 import java.util.Arrays;
29 import java.util.ArrayList;
30 import java.util.List;
31 
51 @DesignerComponent(version = YaVersion.PHONENUMBERPICKER_COMPONENT_VERSION,
52  description = "A button that, when clicked on, displays a list of " +
53  "the contacts' phone numbers to choose among. After the user has made a " +
54  "selection, the following properties will be set to information about " +
55  "the chosen contact: <ul>\n" +
56  "<li> <code>ContactName</code>: the contact's name </li>\n " +
57  "<li> <code>PhoneNumber</code>: the contact's phone number </li>\n " +
58  "<li> <code>EmailAddress</code>: the contact's email address </li> " +
59  "<li> <code>Picture</code>: the name of the file containing the contact's " +
60  "image, which can be used as a <code>Picture</code> property value for " +
61  "the <code>Image</code> or <code>ImageSprite</code> component.</li></ul>\n" +
62  "</p><p>Other properties affect the appearance of the button " +
63  "(<code>TextAlignment</code>, <code>BackgroundColor</code>, etc.) and " +
64  "whether it can be clicked on (<code>Enabled</code>).</p>\n" +
65  "<p>The PhoneNumberPicker component may not work on all Android " +
66  "devices. For example, on Android systems before system 3.0, the " +
67  "returned lists of phone numbers and email addresses will be empty.\n",
68  category = ComponentCategory.SOCIAL)
69 @SimpleObject
70 @UsesPermissions(permissionNames = "android.permission.READ_CONTACTS")
71 public class PhoneNumberPicker extends ContactPicker {
72 
73  private static String[] NAME_PROJECTION;
74  private static String[] DATA_PROJECTION;
75  private static final String[] PROJECTION = {
76  Contacts.PeopleColumns.NAME,
77  Contacts.PhonesColumns.NUMBER,
78  Contacts.Phones.PERSON_ID,
79  Contacts.People.PRIMARY_EMAIL_ID,
80  };
81  private static final int NAME_INDEX = 0;
82  private static final int NUMBER_INDEX = 1;
83  private static final int PERSON_INDEX = 2;
84  private static final int EMAIL_INDEX = 3;
85  private static final String LOG_TAG = "PhoneNumberPicker";
86 
93  super(container, Contacts.Phones.CONTENT_URI);
94  }
95 
101  category = PropertyCategory.BEHAVIOR)
102  public String PhoneNumber() {
103  return ensureNotNull(phoneNumber);
104  }
105 
114  // TODO(halabelson): Rework how the content selection is done to make this overlap
115  // more with Contact Picker. Note that the two components use different intents, so that
116  // the returned URIs are different (contacts/people vs, contacts/phones)
117  // This really should be fixed by updating the way we handle contacts. See the comments
118  // on checkUri in ContactPicker.
119 
120  @Override
121  public void resultReturned(int requestCode, int resultCode, Intent data) {
122  if (requestCode == this.requestCode && resultCode == Activity.RESULT_OK) {
123  Log.i(LOG_TAG, "received intent is " + data);
124  Uri phoneUri = data.getData();
125 
126  String desiredPhoneUri = "";
128  desiredPhoneUri = "//com.android.contacts/data";
129  } else {
130  desiredPhoneUri = "//contacts/phones";
131  }
132 
133  if (checkContactUri(phoneUri, desiredPhoneUri)) {
134  Cursor contactCursor = null;
135  Cursor dataCursor = null;
136  try {
138  NAME_PROJECTION = HoneycombMR1Util.getNameProjection();
139  contactCursor = activityContext.getContentResolver().query(phoneUri,
140  NAME_PROJECTION, null, null, null);
141  String id = postHoneycombGetContactNameAndPicture(contactCursor);
142 
143  DATA_PROJECTION = HoneycombMR1Util.getDataProjection();
144  dataCursor = HoneycombMR1Util.getDataCursor(id, activityContext, DATA_PROJECTION);
145  postHoneycombGetContactEmailsAndPhones(dataCursor);
146  } else {
147  contactCursor = activityContext.getContentResolver().query(phoneUri,
148  PROJECTION, null, null, null);
149  preHoneycombGetContactInfo(contactCursor);
150  }
151 
152  Log.i(LOG_TAG,
153  "Contact name = " + contactName + ", phone number = " + phoneNumber +
154  ", emailAddress = " + emailAddress + ", contactPhotoUri = " + contactPictureUri);
155  } catch (Exception e) {
156  // There was an exception in trying to compute the cursor from the activity context.
157  // It's bad form to catch an arbitrary exception, but if there is an error here
158  // it's unclear what's going on.
159  Log.e(LOG_TAG, "Exception in resultReturned", e);
161  } finally {
162  if (contactCursor != null) {
163  contactCursor.close();
164  }
165  if (dataCursor != null){
166  dataCursor.close();
167  }
168  }
169  } // ends if (checkContactUri ...
170  AfterPicking();
171  } // ends if (requestCode ...
172  }
173 
174 
178  public void preHoneycombGetContactInfo(Cursor cursor) {
179  if (cursor.moveToFirst()) {
180  contactName = guardCursorGetString(cursor, NAME_INDEX);
181  phoneNumber = guardCursorGetString(cursor, NUMBER_INDEX);
182  int contactId = cursor.getInt(PERSON_INDEX);
183  Uri cUri = ContentUris.withAppendedId(Contacts.People.CONTENT_URI, contactId);
184  contactPictureUri = cUri.toString();
185  String emailId = guardCursorGetString(cursor, EMAIL_INDEX);
186  emailAddress = getEmailAddress(emailId);
187  }
188  }
189 
194  public String postHoneycombGetContactNameAndPicture(Cursor contactCursor) {
195  String id = "";
196  if (contactCursor.moveToFirst()) {
197  final int CONTACT_ID_INDEX = HoneycombMR1Util.getContactIdIndex(contactCursor);
198  final int NAME_INDEX = HoneycombMR1Util.getNameIndex(contactCursor);
199  final int PHOTO_INDEX = HoneycombMR1Util.getThumbnailIndex(contactCursor);
200  final int PHONE_INDEX = HoneycombMR1Util.getPhoneIndex(contactCursor);
201  phoneNumber = guardCursorGetString(contactCursor, PHONE_INDEX);
202  id = guardCursorGetString(contactCursor, CONTACT_ID_INDEX);
203  contactName = guardCursorGetString(contactCursor, NAME_INDEX);
204  contactPictureUri = guardCursorGetString(contactCursor, PHOTO_INDEX);
205  }
206  return id;
207  }
208 
213  public void postHoneycombGetContactEmailsAndPhones(Cursor dataCursor) {
214  List<String> phoneListToStore = new ArrayList<String>();
215  List<String> emailListToStore = new ArrayList<String>();
216  if (dataCursor.moveToFirst()) {
217  final int PHONE_INDEX = HoneycombMR1Util.getPhoneIndex(dataCursor);
218  final int EMAIL_INDEX = HoneycombMR1Util.getEmailIndex(dataCursor);
219  final int MIME_INDEX = HoneycombMR1Util.getMimeIndex(dataCursor);
220 
221  String phoneType = HoneycombMR1Util.getPhoneType();
222  String emailType = HoneycombMR1Util.getEmailType();
223 
224  // Get the first (default) email and phone number associated with the contact.
225  while (!dataCursor.isAfterLast()) {
226  String type = guardCursorGetString(dataCursor, MIME_INDEX);
227  if (type.contains(phoneType)) {
228  phoneListToStore.add(guardCursorGetString(dataCursor, PHONE_INDEX));
229  } else if (type.contains(emailType)) {
230  emailListToStore.add(guardCursorGetString(dataCursor, EMAIL_INDEX));
231  } else {
232  Log.i("ContactPicker", "Type mismatch: " + type +
233  " not " + phoneType +
234  " or " + emailType);
235  }
236  dataCursor.moveToNext();
237  }
238  phoneNumberList = phoneListToStore;
239  emailAddressList = emailListToStore;
240  if (!emailAddressList.isEmpty()) {
241  emailAddress = (String) emailAddressList.get(0);
242  } else {
243  emailAddress = "";
244  }
245  }
246  }
247 }
com.google.appinventor.components.runtime.util.HoneycombMR1Util.getDataCursor
static Cursor getDataCursor(String id, Activity activityContext, String[] dataProjection)
Definition: HoneycombMR1Util.java:192
com.google.appinventor.components.runtime.util.ErrorMessages
Definition: ErrorMessages.java:17
com.google.appinventor.components.runtime.util
-*- mode: java; c-basic-offset: 2; -*-
Definition: AccountChooser.java:7
com.google.appinventor.components.common.YaVersion
Definition: YaVersion.java:14
com.google.appinventor.components.runtime.ContactPicker
Definition: ContactPicker.java:80
com.google.appinventor.components.runtime.PhoneNumberPicker.PhoneNumberPicker
PhoneNumberPicker(ComponentContainer container)
Definition: PhoneNumberPicker.java:92
com.google.appinventor.components.runtime.util.HoneycombMR1Util.getDataProjection
static String[] getDataProjection()
Definition: HoneycombMR1Util.java:84
com.google.appinventor.components
com.google.appinventor.components.runtime.util.HoneycombMR1Util
Definition: HoneycombMR1Util.java:29
com.google.appinventor.components.runtime.util.HoneycombMR1Util.getNameProjection
static String[] getNameProjection()
Definition: HoneycombMR1Util.java:71
com.google.appinventor.components.annotations.DesignerComponent
Definition: DesignerComponent.java:22
com.google.appinventor.components.runtime.util.ErrorMessages.ERROR_PHONE_UNSUPPORTED_CONTACT_PICKER
static final int ERROR_PHONE_UNSUPPORTED_CONTACT_PICKER
Definition: ErrorMessages.java:144
com.google.appinventor.components.annotations.PropertyCategory.BEHAVIOR
BEHAVIOR
Definition: PropertyCategory.java:15
com.google.appinventor.components.runtime.util.HoneycombMR1Util.getEmailIndex
static int getEmailIndex(Cursor dataCursor)
Definition: HoneycombMR1Util.java:147
com.google.appinventor.components.runtime.PhoneNumberPicker.preHoneycombGetContactInfo
void preHoneycombGetContactInfo(Cursor cursor)
Definition: PhoneNumberPicker.java:178
com.google.appinventor.components.runtime.PhoneNumberPicker.postHoneycombGetContactEmailsAndPhones
void postHoneycombGetContactEmailsAndPhones(Cursor dataCursor)
Definition: PhoneNumberPicker.java:213
com.google.appinventor.components.runtime.util.HoneycombMR1Util.getContactIdIndex
static int getContactIdIndex(Cursor contactCursor)
Definition: HoneycombMR1Util.java:118
com.google.appinventor.components.annotations.UsesPermissions
Definition: UsesPermissions.java:21
com.google.appinventor.components.runtime.util.SdkLevel
Definition: SdkLevel.java:19
com.google.appinventor.components.annotations.SimpleProperty
Definition: SimpleProperty.java:23
com.google.appinventor.components.runtime.PhoneNumberPicker
Definition: PhoneNumberPicker.java:71
com.google.appinventor.components.runtime.util.HoneycombMR1Util.getThumbnailIndex
static int getThumbnailIndex(Cursor contactCursor)
Definition: HoneycombMR1Util.java:132
com.google.appinventor.components.annotations.PropertyCategory
Definition: PropertyCategory.java:13
com.google.appinventor.components.runtime.PhoneNumberPicker.resultReturned
void resultReturned(int requestCode, int resultCode, Intent data)
Definition: PhoneNumberPicker.java:121
com.google.appinventor.components.runtime.ComponentContainer
Definition: ComponentContainer.java:16
com.google.appinventor.components.runtime.util.SdkLevel.getLevel
static int getLevel()
Definition: SdkLevel.java:45
com.google.appinventor.components.runtime
Copyright 2009-2011 Google, All Rights reserved.
Definition: AccelerometerSensor.java:8
com.google.appinventor.components.runtime.util.HoneycombMR1Util.getPhoneType
static String getPhoneType()
Definition: HoneycombMR1Util.java:157
com.google.appinventor.components.common
Definition: ComponentCategory.java:7
com.google.appinventor.components.common.ComponentCategory
Definition: ComponentCategory.java:48
com.google.appinventor.components.runtime.util.HoneycombMR1Util.getNameIndex
static int getNameIndex(Cursor contactCursor)
Definition: HoneycombMR1Util.java:125
com.google.appinventor.components.annotations.SimpleObject
Definition: SimpleObject.java:23
com.google.appinventor.components.runtime.util.HoneycombMR1Util.getEmailType
static String getEmailType()
Definition: HoneycombMR1Util.java:164
com.google
com
com.google.appinventor.components.runtime.util.HoneycombMR1Util.getPhoneIndex
static int getPhoneIndex(Cursor dataCursor)
Definition: HoneycombMR1Util.java:143
com.google.appinventor.components.runtime.PhoneNumberPicker.postHoneycombGetContactNameAndPicture
String postHoneycombGetContactNameAndPicture(Cursor contactCursor)
Definition: PhoneNumberPicker.java:194
com.google.appinventor.components.annotations
com.google.appinventor
com.google.appinventor.components.runtime.util.HoneycombMR1Util.getMimeIndex
static int getMimeIndex(Cursor dataCursor)
Definition: HoneycombMR1Util.java:151
com.google.appinventor.components.runtime.util.SdkLevel.LEVEL_HONEYCOMB_MR1
static final int LEVEL_HONEYCOMB_MR1
Definition: SdkLevel.java:29