Loading AndroidManifest.xml +8 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <uses-permission android:name="android.permission.COPY_PROTECTED_DATA" /> <uses-permission android:name="android.permission.MANAGE_USERS" /> <uses-permission android:name="android.permission.READ_PROFILE" /> <application android:label="@string/settings_label" android:icon="@mipmap/ic_launcher_settings" Loading Loading @@ -1489,5 +1490,12 @@ </intent-filter> </receiver> <!-- Watch for ContactsContract.Profile changes and update the user's photo. --> <receiver android:name=".users.ProfileUpdateReceiver"> <intent-filter> <action android:name="android.provider.Contacts.PROFILE_CHANGED" /> </intent-filter> </receiver> </application> </manifest> src/com/android/settings/users/ProfileUpdateReceiver.java 0 → 100644 +82 −0 Original line number Diff line number Diff line /* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.users; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.pm.UserInfo; import android.net.Uri; import android.os.ParcelFileDescriptor; import android.os.UserHandle; import android.os.UserManager; import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Profile; import android.util.Log; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; /** * Watches for changes to Me Profile in Contacts and writes the photo to the User Manager. */ public class ProfileUpdateReceiver extends BroadcastReceiver { @Override public void onReceive(final Context context, Intent intent) { // Profile changed, lets get the photo and write to user manager new Thread() { public void run() { copyProfilePhoto(context, null); } }.start(); } /* Used by UserSettings as well. Call this on a non-ui thread. */ static boolean copyProfilePhoto(Context context, UserInfo user) { Uri contactUri = Profile.CONTENT_URI; InputStream avatarDataStream = Contacts.openContactPhotoInputStream( context.getContentResolver(), contactUri, true); // If there's no profile photo, assign a default avatar if (avatarDataStream == null) { return false; } int userId = user != null ? user.id : UserHandle.myUserId(); UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); ParcelFileDescriptor fd = um.setUserIcon(userId); FileOutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(fd); byte[] buffer = new byte[4096]; int readSize; try { while ((readSize = avatarDataStream.read(buffer)) > 0) { os.write(buffer, 0, readSize); } return true; } catch (IOException ioe) { Log.e("copyProfilePhoto", "Error copying profile photo " + ioe); } finally { try { os.close(); avatarDataStream.close(); } catch (IOException ioe) { } } return false; } } src/com/android/settings/users/UserSettings.java +36 −53 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.graphics.BitmapFactory; import android.graphics.Bitmap.CompressFormat; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; Loading Loading @@ -98,10 +99,10 @@ public class UserSettings extends SettingsPreferenceFragment private EditTextPreference mNicknamePreference; private int mRemovingUserId = -1; private boolean mAddingUser; private boolean mProfileExists; private final Object mUserLock = new Object(); private UserManager mUserManager; private boolean mProfileChanged; private Handler mHandler = new Handler() { @Override Loading @@ -114,13 +115,6 @@ public class UserSettings extends SettingsPreferenceFragment } }; private ContentObserver mProfileObserver = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange) { mProfileChanged = true; } }; private BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() { @Override Loading @@ -143,11 +137,8 @@ public class UserSettings extends SettingsPreferenceFragment mNicknamePreference = (EditTextPreference) findPreference(KEY_USER_NICKNAME); mNicknamePreference.setOnPreferenceChangeListener(this); mNicknamePreference.setSummary(mUserManager.getUserInfo(UserHandle.myUserId()).name); loadProfile(false); loadProfile(); setHasOptionsMenu(true); // Register to watch for profile changes getActivity().getContentResolver().registerContentObserver( ContactsContract.Profile.CONTENT_URI, false, mProfileObserver); getActivity().registerReceiver(mUserChangeReceiver, new IntentFilter(Intent.ACTION_USER_REMOVED)); } Loading @@ -155,17 +146,13 @@ public class UserSettings extends SettingsPreferenceFragment @Override public void onResume() { super.onResume(); if (mProfileChanged) { loadProfile(true); mProfileChanged = false; } loadProfile(); updateUserList(); } @Override public void onDestroy() { super.onDestroy(); getActivity().getContentResolver().unregisterContentObserver(mProfileObserver); getActivity().unregisterReceiver(mUserChangeReceiver); } Loading Loading @@ -198,13 +185,29 @@ public class UserSettings extends SettingsPreferenceFragment } } private void loadProfile(boolean force) { private void loadProfile() { mProfileExists = false; new AsyncTask<Void, Void, String>() { @Override protected void onPostExecute(String result) { finishLoadProfile(result); } @Override protected String doInBackground(Void... values) { UserInfo user = mUserManager.getUserInfo(UserHandle.myUserId()); if (force || user.iconPath == null || user.iconPath.equals("")) { if (user.iconPath == null || user.iconPath.equals("")) { assignProfilePhoto(user); } String profileName = getProfileName(); return profileName; } }.execute(); } private void finishLoadProfile(String profileName) { mMePreference.setTitle(profileName); setPhotoId(mMePreference, mUserManager.getUserInfo(UserHandle.myUserId())); } private void onAddUserClicked() { Loading Loading @@ -343,37 +346,10 @@ public class UserSettings extends SettingsPreferenceFragment getActivity().invalidateOptionsMenu(); } /* TODO: Put this in an AsyncTask */ private void assignProfilePhoto(final UserInfo user) { // If the contact is "me", then use my local profile photo. Otherwise, build a // uri to get the avatar of the contact. Uri contactUri = Profile.CONTENT_URI; InputStream avatarDataStream = Contacts.openContactPhotoInputStream( getActivity().getContentResolver(), contactUri, true); // If there's no profile photo, assign a default avatar if (avatarDataStream == null) { if (!ProfileUpdateReceiver.copyProfilePhoto(getActivity(), user)) { assignDefaultPhoto(user); setPhotoId(mMePreference, user); return; } ParcelFileDescriptor fd = mUserManager.setUserIcon(user.id); FileOutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(fd); byte[] buffer = new byte[4096]; int readSize; try { while ((readSize = avatarDataStream.read(buffer)) > 0) { os.write(buffer, 0, readSize); } os.close(); avatarDataStream.close(); } catch (IOException ioe) { Log.e(TAG, "Error copying profile photo " + ioe); } setPhotoId(mMePreference, user); } private String getProfileName() { Loading @@ -387,6 +363,7 @@ public class UserSettings extends SettingsPreferenceFragment try { if (cursor.moveToFirst()) { mProfileExists = true; return cursor.getString(cursor.getColumnIndex(Phone.DISPLAY_NAME)); } } finally { Loading Loading @@ -421,8 +398,14 @@ public class UserSettings extends SettingsPreferenceFragment @Override public boolean onPreferenceClick(Preference pref) { if (pref == mMePreference) { Intent editProfile = new Intent(Intent.ACTION_EDIT); editProfile.setData(ContactsContract.Profile.CONTENT_URI); Intent editProfile; if (!mProfileExists) { editProfile = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI); // TODO: Make this a proper API editProfile.putExtra("newLocalProfile", true); } else { editProfile = new Intent(Intent.ACTION_EDIT, ContactsContract.Profile.CONTENT_URI); } // To make sure that it returns back here when done // TODO: Make this a proper API editProfile.putExtra("finishActivityOnSaveCompleted", true); Loading Loading
AndroidManifest.xml +8 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <uses-permission android:name="android.permission.COPY_PROTECTED_DATA" /> <uses-permission android:name="android.permission.MANAGE_USERS" /> <uses-permission android:name="android.permission.READ_PROFILE" /> <application android:label="@string/settings_label" android:icon="@mipmap/ic_launcher_settings" Loading Loading @@ -1489,5 +1490,12 @@ </intent-filter> </receiver> <!-- Watch for ContactsContract.Profile changes and update the user's photo. --> <receiver android:name=".users.ProfileUpdateReceiver"> <intent-filter> <action android:name="android.provider.Contacts.PROFILE_CHANGED" /> </intent-filter> </receiver> </application> </manifest>
src/com/android/settings/users/ProfileUpdateReceiver.java 0 → 100644 +82 −0 Original line number Diff line number Diff line /* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.users; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.pm.UserInfo; import android.net.Uri; import android.os.ParcelFileDescriptor; import android.os.UserHandle; import android.os.UserManager; import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Profile; import android.util.Log; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; /** * Watches for changes to Me Profile in Contacts and writes the photo to the User Manager. */ public class ProfileUpdateReceiver extends BroadcastReceiver { @Override public void onReceive(final Context context, Intent intent) { // Profile changed, lets get the photo and write to user manager new Thread() { public void run() { copyProfilePhoto(context, null); } }.start(); } /* Used by UserSettings as well. Call this on a non-ui thread. */ static boolean copyProfilePhoto(Context context, UserInfo user) { Uri contactUri = Profile.CONTENT_URI; InputStream avatarDataStream = Contacts.openContactPhotoInputStream( context.getContentResolver(), contactUri, true); // If there's no profile photo, assign a default avatar if (avatarDataStream == null) { return false; } int userId = user != null ? user.id : UserHandle.myUserId(); UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); ParcelFileDescriptor fd = um.setUserIcon(userId); FileOutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(fd); byte[] buffer = new byte[4096]; int readSize; try { while ((readSize = avatarDataStream.read(buffer)) > 0) { os.write(buffer, 0, readSize); } return true; } catch (IOException ioe) { Log.e("copyProfilePhoto", "Error copying profile photo " + ioe); } finally { try { os.close(); avatarDataStream.close(); } catch (IOException ioe) { } } return false; } }
src/com/android/settings/users/UserSettings.java +36 −53 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.graphics.BitmapFactory; import android.graphics.Bitmap.CompressFormat; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; Loading Loading @@ -98,10 +99,10 @@ public class UserSettings extends SettingsPreferenceFragment private EditTextPreference mNicknamePreference; private int mRemovingUserId = -1; private boolean mAddingUser; private boolean mProfileExists; private final Object mUserLock = new Object(); private UserManager mUserManager; private boolean mProfileChanged; private Handler mHandler = new Handler() { @Override Loading @@ -114,13 +115,6 @@ public class UserSettings extends SettingsPreferenceFragment } }; private ContentObserver mProfileObserver = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange) { mProfileChanged = true; } }; private BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() { @Override Loading @@ -143,11 +137,8 @@ public class UserSettings extends SettingsPreferenceFragment mNicknamePreference = (EditTextPreference) findPreference(KEY_USER_NICKNAME); mNicknamePreference.setOnPreferenceChangeListener(this); mNicknamePreference.setSummary(mUserManager.getUserInfo(UserHandle.myUserId()).name); loadProfile(false); loadProfile(); setHasOptionsMenu(true); // Register to watch for profile changes getActivity().getContentResolver().registerContentObserver( ContactsContract.Profile.CONTENT_URI, false, mProfileObserver); getActivity().registerReceiver(mUserChangeReceiver, new IntentFilter(Intent.ACTION_USER_REMOVED)); } Loading @@ -155,17 +146,13 @@ public class UserSettings extends SettingsPreferenceFragment @Override public void onResume() { super.onResume(); if (mProfileChanged) { loadProfile(true); mProfileChanged = false; } loadProfile(); updateUserList(); } @Override public void onDestroy() { super.onDestroy(); getActivity().getContentResolver().unregisterContentObserver(mProfileObserver); getActivity().unregisterReceiver(mUserChangeReceiver); } Loading Loading @@ -198,13 +185,29 @@ public class UserSettings extends SettingsPreferenceFragment } } private void loadProfile(boolean force) { private void loadProfile() { mProfileExists = false; new AsyncTask<Void, Void, String>() { @Override protected void onPostExecute(String result) { finishLoadProfile(result); } @Override protected String doInBackground(Void... values) { UserInfo user = mUserManager.getUserInfo(UserHandle.myUserId()); if (force || user.iconPath == null || user.iconPath.equals("")) { if (user.iconPath == null || user.iconPath.equals("")) { assignProfilePhoto(user); } String profileName = getProfileName(); return profileName; } }.execute(); } private void finishLoadProfile(String profileName) { mMePreference.setTitle(profileName); setPhotoId(mMePreference, mUserManager.getUserInfo(UserHandle.myUserId())); } private void onAddUserClicked() { Loading Loading @@ -343,37 +346,10 @@ public class UserSettings extends SettingsPreferenceFragment getActivity().invalidateOptionsMenu(); } /* TODO: Put this in an AsyncTask */ private void assignProfilePhoto(final UserInfo user) { // If the contact is "me", then use my local profile photo. Otherwise, build a // uri to get the avatar of the contact. Uri contactUri = Profile.CONTENT_URI; InputStream avatarDataStream = Contacts.openContactPhotoInputStream( getActivity().getContentResolver(), contactUri, true); // If there's no profile photo, assign a default avatar if (avatarDataStream == null) { if (!ProfileUpdateReceiver.copyProfilePhoto(getActivity(), user)) { assignDefaultPhoto(user); setPhotoId(mMePreference, user); return; } ParcelFileDescriptor fd = mUserManager.setUserIcon(user.id); FileOutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(fd); byte[] buffer = new byte[4096]; int readSize; try { while ((readSize = avatarDataStream.read(buffer)) > 0) { os.write(buffer, 0, readSize); } os.close(); avatarDataStream.close(); } catch (IOException ioe) { Log.e(TAG, "Error copying profile photo " + ioe); } setPhotoId(mMePreference, user); } private String getProfileName() { Loading @@ -387,6 +363,7 @@ public class UserSettings extends SettingsPreferenceFragment try { if (cursor.moveToFirst()) { mProfileExists = true; return cursor.getString(cursor.getColumnIndex(Phone.DISPLAY_NAME)); } } finally { Loading Loading @@ -421,8 +398,14 @@ public class UserSettings extends SettingsPreferenceFragment @Override public boolean onPreferenceClick(Preference pref) { if (pref == mMePreference) { Intent editProfile = new Intent(Intent.ACTION_EDIT); editProfile.setData(ContactsContract.Profile.CONTENT_URI); Intent editProfile; if (!mProfileExists) { editProfile = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI); // TODO: Make this a proper API editProfile.putExtra("newLocalProfile", true); } else { editProfile = new Intent(Intent.ACTION_EDIT, ContactsContract.Profile.CONTENT_URI); } // To make sure that it returns back here when done // TODO: Make this a proper API editProfile.putExtra("finishActivityOnSaveCompleted", true); Loading