public
Last active

Utility to retrieve user profile on Android device

  • Download Gist
AccountUtils.java
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
/**
* 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;
}
}
CreateAccountActivity.java
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
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) { }
}
UserProfileLoader.java
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
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;
}
create_account.xml
XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
<?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>

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.