-
-
Save remelpugh/4072663 to your computer and use it in GitHub Desktop.
Utility to retrieve user profile on Android device
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A collection of authentication and account connection utilities. With strong inspiration from the Google IO session | |
* app. | |
* @author Dandré Allison | |
*/ | |
public class AccountUtils { | |
/** | |
* Interface for interacting with the result of {@link AccountUtils#getUserProfile}. | |
*/ | |
public static class UserProfile { | |
/** | |
* Adds an email address to the list of possible email addresses for the user | |
* @param email the possible email address | |
*/ | |
public void addPossibleEmail(String email) { | |
addPossibleEmail(email, false); | |
} | |
/** | |
* Adds an email address to the list of possible email addresses for the user. Retains information about whether this | |
* email address is the primary email address of the user. | |
* @param email the possible email address | |
* @param is_primary whether the email address is the primary email address | |
*/ | |
public void addPossibleEmail(String email, boolean is_primary) { | |
if (email == null) return; | |
if (is_primary) { | |
_primary_email = email; | |
_possible_emails.add(email); | |
} else | |
_possible_emails.add(email); | |
} | |
/** | |
* Adds a name to the list of possible names for the user. | |
* @param name the possible name | |
*/ | |
public void addPossibleName(String name) { | |
if (name != null) _possible_names.add(name); | |
} | |
/** | |
* Adds a phone number to the list of possible phone numbers for the user. | |
* @param phone_number the possible phone number | |
*/ | |
public void addPossiblePhoneNumber(String phone_number) { | |
if (phone_number != null) _possible_phone_numbers.add(phone_number); | |
} | |
/** | |
* Adds a phone number to the list of possible phone numbers for the user. Retains information about whether this | |
* phone number is the primary phone number of the user. | |
* @param phone_number the possible phone number | |
* @param is_primary whether the phone number is teh primary phone number | |
*/ | |
public void addPossiblePhoneNumber(String phone_number, boolean is_primary) { | |
if (phone_number == null) return; | |
if (is_primary) { | |
_primary_phone_number = phone_number; | |
_possible_phone_numbers.add(phone_number); | |
} else | |
_possible_phone_numbers.add(phone_number); | |
} | |
/** | |
* Sets the possible photo for the user. | |
* @param photo the possible photo | |
*/ | |
public void addPossiblePhoto(Uri photo) { | |
if (photo != null) _possible_photo = photo; | |
} | |
/** | |
* Retrieves the list of possible email addresses. | |
* @return the list of possible email addresses | |
*/ | |
public List<String> possibleEmails() { | |
return _possible_emails; | |
} | |
/** | |
* Retrieves the list of possible names. | |
* @return the list of possible names | |
*/ | |
public List<String> possibleNames() { | |
return _possible_names; | |
} | |
/** | |
* Retrieves the list of possible phone numbers | |
* @return the list of possible phone numbers | |
*/ | |
public List<String> possiblePhoneNumbers() { | |
return _possible_phone_numbers; | |
} | |
/** | |
* Retrieves the possible photo. | |
* @return the possible photo | |
*/ | |
public Uri possiblePhoto() { | |
return _possible_photo; | |
} | |
/** | |
* Retrieves the primary email address. | |
* @return the primary email address | |
*/ | |
public String primaryEmail() { | |
return _primary_email; | |
} | |
/** | |
* Retrieves the primary phone number | |
* @return the primary phone number | |
*/ | |
public String primaryPhoneNumber() { | |
return _primary_phone_number; | |
} | |
/** The primary email address */ | |
private String _primary_email; | |
/** The primary name */ | |
private String _primary_name; | |
/** The primary phone number */ | |
private String _primary_phone_number; | |
/** A list of possible email addresses for the user */ | |
private List<String> _possible_emails = Lists.newArrayList(); | |
/** A list of possible names for the user */ | |
private List<String> _possible_names = Lists.newArrayList(); | |
/** A list of possible phone numbers for the user */ | |
private List<String> _possible_phone_numbers = Lists.newArrayList(); | |
/** A possible photo for the user */ | |
private Uri _possible_photo; | |
} | |
/** | |
* Retrieves the user profile information. | |
* @param context the context from which to retrieve the user profile | |
* @return the user profile | |
*/ | |
public static UserProfile getUserProfile(Context context) { | |
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH | |
? getUserProfileOnIcsDevice(context) | |
: getUserProfileOnGingerbreadDevice(context); | |
} | |
/** | |
* Retrieves the user profile information in a manner supported by Gingerbread devices. | |
* @param context the context from which to retrieve the user's email address and name | |
* @return a list of the possible user's email address and name | |
*/ | |
private static UserProfile getUserProfileOnGingerbreadDevice(Context context) { | |
// Other that using Patterns (API level 8) this works on devices down to API level 5 | |
final Matcher valid_email_address = Patterns.EMAIL_ADDRESS.matcher(""); | |
final Account[] accounts = AccountManager.get(context).getAccountsByType(GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE); | |
final UserProfile user_profile = new UserProfile(); | |
// As far as I can tell, there is no way to get the real name or phone number from the Google account | |
for (Account account : accounts) { | |
if (valid_email_address.reset(account.name).matches()) | |
user_profile.addPossibleEmail(account.name); | |
} | |
// Gets the phone number of the device is the device has one | |
if (context.getPackageManager().hasSystemFeature(TELEPHONY_SERVICE)) { | |
final TelephonyManager telephony = (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE); | |
user_profile.addPossiblePhoneNumber(telephony.getLine1Number()); | |
} | |
return user_profile; | |
} | |
/** | |
* Retrieves the user profile information in a manner supported by Ice Cream Sandwich devices. | |
* @param context the context from which to retrieve the user's email address and name | |
* @return a list of the possible user's email address and name | |
*/ | |
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) | |
private static UserProfile getUserProfileOnIcsDevice(Context context) { | |
final ContentResolver content = context.getContentResolver(); | |
final Cursor cursor = content.query( | |
// Retrieves data rows for the device user's 'profile' contact | |
Uri.withAppendedPath( | |
ContactsContract.Profile.CONTENT_URI, | |
ContactsContract.Contacts.Data.CONTENT_DIRECTORY), | |
ProfileQuery.PROJECTION, | |
// Selects only email addresses or names | |
ContactsContract.Contacts.Data.MIMETYPE + "=? OR " | |
+ ContactsContract.Contacts.Data.MIMETYPE + "=? OR " | |
+ ContactsContract.Contacts.Data.MIMETYPE + "=? OR " | |
+ ContactsContract.Contacts.Data.MIMETYPE + "=?", | |
new String[]{ | |
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE, | |
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, | |
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE, | |
ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE | |
}, | |
// Show primary rows first. Note that there won't be a primary email address if the | |
// user hasn't specified one. | |
ContactsContract.Contacts.Data.IS_PRIMARY + " DESC" | |
); | |
final UserProfile user_profile = new UserProfile(); | |
String mime_type; | |
while (cursor.moveToNext()) { | |
mime_type = cursor.getString(ProfileQuery.MIME_TYPE); | |
if (mime_type.equals(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) | |
user_profile.addPossibleEmail(cursor.getString(ProfileQuery.EMAIL), | |
cursor.getInt(ProfileQuery.IS_PRIMARY_EMAIL) > 0); | |
else if (mime_type.equals(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)) | |
user_profile.addPossibleName(cursor.getString(ProfileQuery.GIVEN_NAME) + " " + cursor.getString(ProfileQuery.FAMILY_NAME)); | |
else if (mime_type.equals(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)) | |
user_profile.addPossiblePhoneNumber(cursor.getString(ProfileQuery.PHONE_NUMBER), | |
cursor.getInt(ProfileQuery.IS_PRIMARY_PHONE_NUMBER) > 0); | |
else if (mime_type.equals(ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)) | |
user_profile.addPossiblePhoto(Uri.parse(cursor.getString(ProfileQuery.PHOTO))); | |
} | |
cursor.close(); | |
return user_profile; | |
} | |
/** | |
* Contacts user profile query interface. | |
*/ | |
private interface ProfileQuery { | |
/** The set of columns to extract from the profile query results */ | |
String[] PROJECTION = { | |
ContactsContract.CommonDataKinds.Email.ADDRESS, | |
ContactsContract.CommonDataKinds.Email.IS_PRIMARY, | |
ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, | |
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, | |
ContactsContract.CommonDataKinds.Phone.NUMBER, | |
ContactsContract.CommonDataKinds.Phone.IS_PRIMARY, | |
ContactsContract.CommonDataKinds.Photo.PHOTO_URI, | |
ContactsContract.Contacts.Data.MIMETYPE | |
}; | |
/** Column index for the email address in the profile query results */ | |
int EMAIL = 0; | |
/** Column index for the primary email address indicator in the profile query results */ | |
int IS_PRIMARY_EMAIL = 1; | |
/** Column index for the family name in the profile query results */ | |
int FAMILY_NAME = 2; | |
/** Column index for the given name in the profile query results */ | |
int GIVEN_NAME = 3; | |
/** Column index for the phone number in the profile query results */ | |
int PHONE_NUMBER = 4; | |
/** Column index for the primary phone number in the profile query results */ | |
int IS_PRIMARY_PHONE_NUMBER = 5; | |
/** Column index for the photo in the profile query results */ | |
int PHOTO = 6; | |
/** Column index for the MIME type in the profile query results */ | |
int MIME_TYPE = 7; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:paddingTop="8dp" | |
android:paddingLeft="@dimen/page_padding" | |
android:paddingRight="@dimen/page_padding" | |
android:orientation="vertical" | |
android:gravity="center"> | |
<TextView style="?android:listSeparatorTextViewStyle" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_gravity="left" | |
android:paddingTop="8dp" | |
android:paddingBottom="8dp" | |
android:singleLine="true" | |
android:paddingLeft="13dp" | |
android:text="account" /> | |
<AutoCompleteTextView | |
android:id="@+id/email_address" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_marginBottom="@dimen/view_margin" | |
android:layout_marginRight="@dimen/view_margin" | |
android:singleLine="true" | |
android:inputType="textEmailAddress" | |
android:imeOptions="actionNext" | |
android:hint="email address" /> | |
<EditText | |
android:id="@+id/password" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_marginTop="@dimen/view_margin" | |
android:layout_marginBottom="@dimen/view_margin" | |
android:singleLine="true" | |
android:inputType="textPassword" | |
android:hint="password" /> | |
<TextView style="?android:listSeparatorTextViewStyle" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_gravity="left" | |
android:paddingTop="8dp" | |
android:paddingBottom="8dp" | |
android:singleLine="true" | |
android:paddingLeft="13dp" | |
android:text="information" /> | |
<AutoCompleteTextView | |
android:id="@+id/full_name" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_marginBottom="@dimen/view_margin" | |
android:singleLine="true" | |
android:inputType="textPersonName" | |
android:imeOptions="actionNext" | |
android:capitalize="words" | |
android:hint="full name" /> | |
<AutoCompleteTextView | |
android:id="@+id/phone_number" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_marginTop="@dimen/view_margin" | |
android:layout_marginBottom="@dimen/view_margin" | |
android:singleLine="true" | |
android:phoneNumber="true" | |
android:inputType="phone" | |
android:imeOptions="actionNext" | |
android:hint="phone number" /> | |
<ImageButton style="?android:attr/borderlessButtonStyle" | |
android:id="@+id/photo_picker" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginTop="@dimen/view_margin" | |
android:layout_marginBottom="@dimen/view_margin" | |
android:maxHeight="128dp" | |
android:src="@drawable/anonymous_image_2" | |
android:adjustViewBounds="true" | |
android:scaleType="fitCenter" | |
android:cropToPadding="true" | |
android:contentDescription="choose an avatar picture, this is the picture set for user by default." | |
android:onClick="startPhotoPicker" /> | |
<Button | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:layout_marginTop="@dimen/view_margin" | |
android:text="create account" | |
android:onClick="startHomeScreen" /> | |
</LinearLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CreateAccountActivity extends FragmentActivity | |
implements LoaderManager.LoaderCallbacks<AccountUtils.UserProfile> { | |
@Override | |
protected void onCreate(Bundle icicle) { | |
super.onCreate(icicle); | |
// ... | |
getSupportLoaderManager().initLoader(0, Bundle.EMPTY, this); | |
} | |
@Override | |
public Loader<AccountUtils.UserProfile> onCreateLoader(int _, Bundle __) { | |
return new UserProfileLoader(this); | |
} | |
@Override | |
public void onLoadFinished(Loader<AccountUtils.UserProfile> loader, AccountUtils.UserProfile user_profile) { | |
final List<String> possible_emails = user_profile.possibleEmails(); | |
final List<String> possible_names = user_profile.possibleNames(); | |
final List<String> possible_phone_numbers = user_profile.possiblePhoneNumbers(); | |
final String primary_email = user_profile.primaryEmail(); | |
final String primary_phone_number = user_profile.primaryPhoneNumber(); | |
// Sets the text to the likely possibility, this is the user defined primary possibility or the first possibility if there | |
// isn't a primary possibility | |
if (possible_emails.size() > 0) _email_address.setText(primary_email == null ? possible_emails.get(0) : | |
primary_email); | |
if (possible_names.size() > 0) _full_name.setText(possible_names.get(0)); | |
if (possible_phone_numbers.size() > 0) _phone_number.setText(primary_phone_number == null? possible_phone_numbers.get(0) : primary_phone_number); | |
_photo_picker.setImageURI(user_profile.possiblePhoto()); | |
_email_address.setAdapter(new ArrayAdapter<String>(this, | |
android.R.layout.simple_dropdown_item_1line, | |
possible_emails)); | |
_full_name.setAdapter(new ArrayAdapter<String>(this, | |
android.R.layout.simple_dropdown_item_1line, | |
possible_names)); | |
_phone_number.setAdapter(new ArrayAdapter<String>(this, | |
android.R.layout.simple_dropdown_item_1line, | |
possible_phone_numbers)); | |
} | |
@Override | |
public void onLoaderReset(Loader<AccountUtils.UserProfile> loader) { } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context; | |
import android.support.v4.content.AsyncTaskLoader; | |
/** | |
* A custom {@link android.support.v4.content.Loader} that retrieves the {@link AccountUtils.UserProfile} asynchronously. | |
* @author Dandré Allison | |
*/ | |
public class UserProfileLoader extends AsyncTaskLoader<AccountUtils.UserProfile> { | |
public UserProfileLoader(Context context) { | |
super(context); | |
} | |
@Override | |
public AccountUtils.UserProfile loadInBackground() { | |
return AccountUtils.getUserProfile(getContext()); | |
} | |
@Override | |
public void deliverResult(AccountUtils.UserProfile user_profile) { | |
_user_profile = user_profile; | |
if (isStarted()) | |
// If the Loader is currently started, we can immediately | |
// deliver its results. | |
super.deliverResult(user_profile); | |
} | |
@Override | |
protected void onStartLoading() { | |
if (_user_profile != null) | |
// Delivers the result immediately when it's already available | |
deliverResult(_user_profile); | |
if (takeContentChanged() || _user_profile == null) { | |
// If the data has changed since the last time it was loaded | |
// or is not currently available, start a load. | |
forceLoad(); | |
} | |
} | |
@Override | |
protected void onStopLoading() { | |
// Attempts to cancel the current load task if possible. | |
cancelLoad(); | |
} | |
/** | |
* Handles a request to completely reset the Loader. | |
*/ | |
@Override protected void onReset() { | |
super.onReset(); | |
// Ensures the loader is stopped | |
onStopLoading(); | |
// Clears the stored list | |
if (_user_profile != null) | |
_user_profile = null; | |
} | |
/** The list of the user's possible email address and name */ | |
private AccountUtils.UserProfile _user_profile; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I am not able to get the details of the profile. The cursor is empty.