diff options
author | Wesley.CW Wang <wesleycwwang@google.com> | 2018-08-15 17:39:07 +0800 |
---|---|---|
committer | Wesley.CW Wang <wesleycwwang@google.com> | 2018-10-04 16:15:05 +0800 |
commit | e7772e0bb866a8ae72cdef69f097ffa8164ebeb7 (patch) | |
tree | afbd3a1a14299a9956649468a30d414f3604ca35 /src | |
parent | b5a739669ddc4e2ebe3cd7af5a2440406bb009d3 (diff) | |
download | EmergencyInfo-e7772e0bb866a8ae72cdef69f097ffa8164ebeb7.tar.gz |
Emergency Info user name preference design change
- User name preference now will launch dialog same as change user name &
icon in Multiple users.
- Add permission for edit user name.
- Change robolectric properties sdk to 23 for fixing robolectric initialize
objects bug.
Test: make RunEmergencyInfoRoboTests
Bug: 111967295
Bug: 116770817
Change-Id: I938983eaa0d21442ade59dde0f3f74eec3a62d22
Diffstat (limited to 'src')
4 files changed, 328 insertions, 10 deletions
diff --git a/src/com/android/emergency/PreferenceKeys.java b/src/com/android/emergency/PreferenceKeys.java index 89db2a66..bdfd47d0 100644 --- a/src/com/android/emergency/PreferenceKeys.java +++ b/src/com/android/emergency/PreferenceKeys.java @@ -32,7 +32,7 @@ public interface PreferenceKeys { /** Key for the add emergency contact preference */ public static final String KEY_ADD_EMERGENCY_CONTACT = "add_emergency_contact"; - /** Key to store and read the name of the user. */ + /** Key for emergency name preference */ public static final String KEY_NAME = "name"; /** Key to store and read the address of the user. */ @@ -58,7 +58,7 @@ public interface PreferenceKeys { * * <p>Note: Do not change the order of these keys, since the order is used to collect TRON stats */ - public static final String[] KEYS_EDIT_EMERGENCY_INFO = {KEY_NAME, KEY_ADDRESS, + public static final String[] KEYS_EDIT_EMERGENCY_INFO = {KEY_ADDRESS, KEY_BLOOD_TYPE, KEY_ALLERGIES, KEY_MEDICATIONS, KEY_MEDICAL_CONDITIONS, KEY_ORGAN_DONOR}; diff --git a/src/com/android/emergency/edit/EditInfoFragment.java b/src/com/android/emergency/edit/EditInfoFragment.java index f774640b..53cae381 100644 --- a/src/com/android/emergency/edit/EditInfoFragment.java +++ b/src/com/android/emergency/edit/EditInfoFragment.java @@ -16,10 +16,10 @@ package com.android.emergency.edit; import android.app.Activity; +import android.app.DialogFragment; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract; @@ -27,7 +27,6 @@ import androidx.preference.Preference.OnPreferenceChangeListener; import androidx.preference.PreferenceFragment; import androidx.preference.Preference; import androidx.preference.PreferenceGroup; -import androidx.preference.PreferenceManager; import android.util.Log; import android.widget.Toast; @@ -35,8 +34,11 @@ import com.android.emergency.PreferenceKeys; import com.android.emergency.R; import com.android.emergency.ReloadablePreferenceInterface; import com.android.emergency.preferences.EmergencyContactsPreference; +import com.android.emergency.preferences.EmergencyNamePreference; import com.android.emergency.util.PreferenceUtils; import com.android.internal.annotations.VisibleForTesting; +import com.android.settingslib.CustomDialogPreference; +import com.android.settingslib.CustomEditTextPreference; import java.util.HashMap; import java.util.Map; @@ -48,12 +50,16 @@ public class EditInfoFragment extends PreferenceFragment { /** Result code for contact picker */ private static final int CONTACT_PICKER_RESULT = 1001; + private static final String DIALOG_PREFERENCE_TAG = "dialog_preference"; + private final Map<String, Preference> mMedicalInfoPreferences = new HashMap<String, Preference>(); /** The category that holds the emergency contacts. */ private EmergencyContactsPreference mEmergencyContactsPreferenceCategory; + private EmergencyNamePreference mEmergencyNamePreference; + @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.edit_emergency_info, rootKey); @@ -69,6 +75,9 @@ public class EditInfoFragment extends PreferenceFragment { } } + mEmergencyNamePreference = (EmergencyNamePreference) findPreference( + PreferenceKeys.KEY_NAME); + // Fill in emergency contacts. mEmergencyContactsPreferenceCategory = (EmergencyContactsPreference) findPreference(PreferenceKeys.KEY_EMERGENCY_CONTACTS); @@ -101,6 +110,7 @@ public class EditInfoFragment extends PreferenceFragment { public void onResume() { super.onResume(); reloadFromPreference(); + mEmergencyNamePreference.reloadFromUserManager(); } /** Reloads the contacts by reading the value from the shared preferences. */ @@ -120,6 +130,24 @@ public class EditInfoFragment extends PreferenceFragment { } @Override + public void onDisplayPreferenceDialog(Preference preference) { + DialogFragment fragment = null; + if (preference instanceof CustomEditTextPreference) { + fragment = CustomEditTextPreference.CustomPreferenceDialogFragment + .newInstance(preference.getKey()); + } else if (preference instanceof CustomDialogPreference) { + fragment = EmergencyNamePreference.EmergencyNamePreferenceDialogFragment + .newInstance(preference.getKey()); + } + if (fragment != null) { + fragment.setTargetFragment(this, 0); + fragment.show(getFragmentManager(), DIALOG_PREFERENCE_TAG); + } else { + super.onDisplayPreferenceDialog(preference); + } + } + + @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == CONTACT_PICKER_RESULT && resultCode == Activity.RESULT_OK) { Uri phoneUri = data.getData(); diff --git a/src/com/android/emergency/edit/EditMedicalInfoFragment.java b/src/com/android/emergency/edit/EditMedicalInfoFragment.java index d132c696..b8567a50 100644 --- a/src/com/android/emergency/edit/EditMedicalInfoFragment.java +++ b/src/com/android/emergency/edit/EditMedicalInfoFragment.java @@ -18,23 +18,31 @@ package com.android.emergency.edit; import android.app.DialogFragment; import android.app.Fragment; import android.os.Bundle; -import androidx.preference.PreferenceFragment; + import androidx.preference.Preference; -import android.text.TextUtils; +import androidx.preference.PreferenceFragment; import com.android.emergency.PreferenceKeys; import com.android.emergency.R; import com.android.emergency.ReloadablePreferenceInterface; -import com.android.emergency.preferences.AutoCompleteEditTextPreference; +import com.android.emergency.preferences.EmergencyNamePreference; import com.android.emergency.util.PreferenceUtils; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.settingslib.CustomDialogPreference; import com.android.settingslib.CustomEditTextPreference; +import android.text.TextUtils; + /** * Fragment that displays personal and medical information. */ public class EditMedicalInfoFragment extends PreferenceFragment { + + private EmergencyNamePreference mEmergencyNamePreference; + + private static final String DIALOG_PREFERENCE_TAG = "dialog_preference"; + @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.edit_medical_info, rootKey); @@ -67,12 +75,16 @@ public class EditMedicalInfoFragment extends PreferenceFragment { } }); } + + mEmergencyNamePreference = (EmergencyNamePreference) findPreference( + PreferenceKeys.KEY_NAME); } @Override public void onResume() { super.onResume(); reloadFromPreference(); + mEmergencyNamePreference.reloadFromUserManager(); } @Override @@ -81,13 +93,13 @@ public class EditMedicalInfoFragment extends PreferenceFragment { if (preference instanceof CustomEditTextPreference) { fragment = CustomEditTextPreference.CustomPreferenceDialogFragment .newInstance(preference.getKey()); - } else if (preference instanceof AutoCompleteEditTextPreference) { - fragment = AutoCompleteEditTextPreference.AutoCompleteEditTextPreferenceDialogFragment + } else if (preference instanceof CustomDialogPreference) { + fragment = EmergencyNamePreference.EmergencyNamePreferenceDialogFragment .newInstance(preference.getKey()); } if (fragment != null) { fragment.setTargetFragment(this, 0); - fragment.show(getFragmentManager(), "dialog_preference"); + fragment.show(getFragmentManager(), DIALOG_PREFERENCE_TAG); } else { super.onDisplayPreferenceDialog(preference); } diff --git a/src/com/android/emergency/preferences/EmergencyNamePreference.java b/src/com/android/emergency/preferences/EmergencyNamePreference.java new file mode 100644 index 00000000..b6a754f0 --- /dev/null +++ b/src/com/android/emergency/preferences/EmergencyNamePreference.java @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2018 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.emergency.preferences; + +import android.app.AlertDialog; +import android.app.Fragment; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.UserHandle; +import android.os.UserManager; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageView; +import androidx.annotation.VisibleForTesting; +import androidx.preference.DialogPreference; +import com.android.emergency.CircleFramedDrawable; +import com.android.emergency.R; +import com.android.internal.util.UserIcons; +import com.android.settingslib.CustomDialogPreference; + +import java.io.File; + +/** + * Custom {@link DialogPreference} that allows us to editing the user name and photo. + */ +public class EmergencyNamePreference extends CustomDialogPreference { + + private static final String KEY_AWAITING_RESULT = "awaiting_result"; + private static final String KEY_SAVED_PHOTO = "pending_photo"; + + private UserManager mUserManager = getContext().getSystemService(UserManager.class); + private EditUserPhotoController mEditUserPhotoController; + private Fragment mFragment; + private Bitmap mSavedPhoto; + private EditText mUserNameView; + private ImageView mUserPhotoView; + private boolean mWaitingForActivityResult = false; + + public EmergencyNamePreference(Context context, AttributeSet attrs, + int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + setSummary(mUserManager.getUserName()); + setIcon(getCircularUserIcon()); + setDialogLayoutResource(R.layout.edit_user_info_dialog_content); + } + + public EmergencyNamePreference(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public EmergencyNamePreference(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.dialogPreferenceStyle); + } + + public EmergencyNamePreference(Context context) { + this(context, null); + } + + /** + * Setup fragment for Dialog and EditUserPhotoController. + */ + public void setFragment(Fragment fragment) { + mFragment = fragment; + } + + /** + * Reload user name and photo form UserManager. + */ + public void reloadFromUserManager() { + setSummary(mUserManager.getUserName()); + setIcon(getCircularUserIcon()); + } + + /** + * Restore user photo when EditUserPhotoController had pending photo. + */ + public void onRestoreInstanceState(Bundle icicle) { + String pendingPhoto = icicle.getString(KEY_SAVED_PHOTO); + if (pendingPhoto != null) { + mSavedPhoto = EditUserPhotoController.loadNewUserPhotoBitmap(new File(pendingPhoto)); + } + mWaitingForActivityResult = icicle.getBoolean(KEY_AWAITING_RESULT, false); + } + + /** + * Save a temp user photo when layout need to recreating but Dialog is showing. + */ + public void onSaveInstanceState(Bundle outState) { + if (getDialog() != null && getDialog().isShowing() + && mEditUserPhotoController != null) { + // Bitmap cannot be stored into bundle because it may exceed parcel limit + // Store it in a temporary file instead + File file = mEditUserPhotoController.saveNewUserPhotoBitmap(); + if (file != null) { + outState.putString(KEY_SAVED_PHOTO, file.getPath()); + } + } + if (mWaitingForActivityResult) { + outState.putBoolean(KEY_AWAITING_RESULT, mWaitingForActivityResult); + } + } + + /** + * Set mWaitingForActivityResult to true when EmergencyNamePreferenceDialogFragment + * startActivityForResult, means we are waiting the activity result. + */ + public void startingActivityForResult() { + mWaitingForActivityResult = true; + } + + /** + * Reset mWaitingForActivityResult and send the result code to EditUserPhotoController when + * EmergencyNamePreferenceDialogFragment onActivityResult. + */ + public void onActivityResult(int requestCode, int resultCode, Intent data) { + mWaitingForActivityResult = false; + + if (getDialog() != null) { + mEditUserPhotoController.onActivityResult(requestCode, resultCode, data); + } + } + + @Override + protected void onBindDialogView(View view) { + super.onBindDialogView(view); + + mUserNameView = view.findViewById(R.id.user_name); + mUserNameView.setText(mUserManager.getUserName()); + mUserPhotoView = view.findViewById(R.id.user_photo); + Drawable drawable; + if (mSavedPhoto != null) { + drawable = CircleFramedDrawable.getInstance(getContext(), mSavedPhoto); + } else { + drawable = getCircularUserIcon(); + } + mUserPhotoView.setImageDrawable(drawable); + + mEditUserPhotoController = createEditUserPhotoController(mUserPhotoView, + getCircularUserIcon()); + } + + @Override + protected void onPrepareDialogBuilder(AlertDialog.Builder builder, + DialogInterface.OnClickListener listener) { + super.onPrepareDialogBuilder(builder, listener); + builder.setTitle(R.string.name) + .setCancelable(true) + .setPositiveButton(android.R.string.ok, listener) + .setNegativeButton(android.R.string.cancel, listener) + .create(); + } + + @Override + protected void onDialogClosed(boolean positiveResult) { + super.onDialogClosed(positiveResult); + if (positiveResult) { + // Update the name if changed. + CharSequence userName = mUserNameView.getText(); + if (!TextUtils.isEmpty(userName)) { + if (mUserManager.getUserName() == null + || !userName.toString().equals(mUserManager.getUserName())) { + mUserManager.setUserName(UserHandle.myUserId(), userName.toString()); + setSummary(userName); + } + } + // Update the photo if changed. + Drawable drawable = mEditUserPhotoController.getNewUserPhotoDrawable(); + Bitmap bitmap = mEditUserPhotoController.getNewUserPhotoBitmap(); + if (drawable != null && bitmap != null + && !drawable.equals(getCircularUserIcon())) { + new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... params) { + mUserManager.setUserIcon(UserHandle.myUserId(), + mEditUserPhotoController.getNewUserPhotoBitmap()); + return null; + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); + setIcon(drawable); + } + if (mFragment != null) { + mFragment.getActivity().removeDialog(1); + } + } + clear(); + } + + private void clear() { + mEditUserPhotoController.removeNewUserPhotoBitmapFile(); + mSavedPhoto = null; + } + + private Drawable getCircularUserIcon() { + Bitmap bitmapUserIcon = mUserManager.getUserIcon(UserHandle.myUserId()); + + if (bitmapUserIcon == null) { + // get default user icon. + final Drawable defaultUserIcon = UserIcons.getDefaultUserIcon( + getContext().getResources(), UserHandle.myUserId(), false); + bitmapUserIcon = UserIcons.convertToBitmap(defaultUserIcon); + } + Drawable drawableUserIcon = new CircleFramedDrawable(bitmapUserIcon, + (int) getContext().getResources().getDimension(R.dimen.circle_avatar_size)); + + return drawableUserIcon; + } + + @VisibleForTesting + EditUserPhotoController createEditUserPhotoController(ImageView userPhotoView, + Drawable drawable) { + return new EditUserPhotoController(mFragment, userPhotoView, + mSavedPhoto, drawable, mWaitingForActivityResult); + } + + public static class EmergencyNamePreferenceDialogFragment extends + CustomPreferenceDialogFragment { + + public static CustomDialogPreference.CustomPreferenceDialogFragment newInstance( + String key) { + final CustomDialogPreference.CustomPreferenceDialogFragment + fragment = new EmergencyNamePreferenceDialogFragment(); + final Bundle b = new Bundle(1 /* capacity */); + b.putString(ARG_KEY, key); + fragment.setArguments(b); + return fragment; + } + + private EmergencyNamePreference getEmergencyNamePreference() { + return (EmergencyNamePreference) getPreference(); + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + getEmergencyNamePreference().setFragment(this); + if (icicle != null) { + getEmergencyNamePreference().onRestoreInstanceState(icicle); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + getEmergencyNamePreference().onSaveInstanceState(outState); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + getEmergencyNamePreference().onActivityResult(requestCode, resultCode, data); + } + + @Override + public void startActivityForResult(Intent intent, int requestCode) { + getEmergencyNamePreference().startingActivityForResult(); + super.startActivityForResult(intent, requestCode); + } + } +} |