ContactPreference.java revision 9e2eea1a8a4d34f8530fc9b042601d4a378bbf43
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package com.android.emergency.preferences; 17 18import android.app.AlertDialog; 19import android.content.Context; 20import android.content.DialogInterface; 21import android.content.Intent; 22import android.graphics.drawable.Drawable; 23import android.net.Uri; 24import android.os.Bundle; 25import android.os.Parcel; 26import android.os.Parcelable; 27import android.preference.Preference; 28import android.support.annotation.NonNull; 29import android.support.annotation.Nullable; 30import android.view.View; 31 32import com.android.emergency.EmergencyContactManager; 33import com.android.emergency.R; 34import com.android.internal.annotations.VisibleForTesting; 35import com.android.internal.logging.MetricsLogger; 36import com.android.internal.logging.MetricsProto.MetricsEvent; 37import com.android.settingslib.drawable.CircleFramedDrawable; 38 39 40/** 41 * A {@link Preference} to display or call a contact using the specified URI string. 42 */ 43public class ContactPreference extends Preference { 44 45 private EmergencyContactManager.Contact mContact; 46 @Nullable private RemoveContactPreferenceListener mRemoveContactPreferenceListener; 47 @Nullable private AlertDialog mRemoveContactDialog; 48 49 /** 50 * Listener for removing a contact. 51 */ 52 public interface RemoveContactPreferenceListener { 53 /** 54 * Callback to remove a contact preference. 55 */ 56 void onRemoveContactPreference(ContactPreference preference); 57 } 58 59 /** 60 * Instantiates a ContactPreference that displays an emergency contact, taking in a Context and 61 * the Uri. 62 */ 63 public ContactPreference(Context context, @NonNull Uri contactUri) { 64 super(context); 65 setOrder(DEFAULT_ORDER); 66 67 setUri(contactUri); 68 69 setWidgetLayoutResource(R.layout.preference_user_delete_widget); 70 setPersistent(false); 71 } 72 73 public void setUri(@NonNull Uri contactUri) { 74 if (mContact != null && !contactUri.equals(mContact.getContactUri()) && 75 mRemoveContactDialog != null) { 76 mRemoveContactDialog.dismiss(); 77 } 78 79 mContact = EmergencyContactManager.getContact(getContext(), contactUri); 80 81 setTitle(mContact.getName()); 82 setKey(mContact.getContactUri().toString()); 83 String summary = mContact.getPhoneType() == null ? 84 mContact.getPhoneNumber() : 85 String.format( 86 getContext().getResources().getString(R.string.phone_type_and_phone_number), 87 mContact.getPhoneType(), 88 mContact.getPhoneNumber()); 89 setSummary(summary); 90 91 // Update the message to show the correct name. 92 if (mRemoveContactDialog != null) { 93 mRemoveContactDialog.setMessage( 94 String.format(getContext().getString(R.string.remove_contact), 95 mContact.getName())); 96 } 97 98 //TODO: Consider doing the following in a non-UI thread. 99 Drawable icon; 100 if (mContact.getPhoto() != null) { 101 icon = new CircleFramedDrawable(mContact.getPhoto(), 102 (int) getContext().getResources().getDimension(R.dimen.circle_avatar_size)); 103 } else { 104 icon = getContext().getResources().getDrawable(R.drawable.ic_person_black_24dp); 105 } 106 setIcon(icon); 107 } 108 109 /** Listener to be informed when a contact preference should be deleted. */ 110 public void setRemoveContactPreferenceListener( 111 RemoveContactPreferenceListener removeContactListener) { 112 mRemoveContactPreferenceListener = removeContactListener; 113 if (mRemoveContactPreferenceListener == null) { 114 mRemoveContactDialog = null; 115 return; 116 } 117 if (mRemoveContactDialog != null) { 118 return; 119 } 120 // Create the remove contact dialog 121 AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); 122 builder.setNegativeButton(getContext().getString(R.string.cancel), null); 123 builder.setPositiveButton(getContext().getString(R.string.remove), 124 new DialogInterface.OnClickListener() { 125 @Override 126 public void onClick(DialogInterface dialogInterface, 127 int which) { 128 if (mRemoveContactPreferenceListener != null) { 129 mRemoveContactPreferenceListener 130 .onRemoveContactPreference(ContactPreference.this); 131 } 132 } 133 }); 134 builder.setMessage(String.format(getContext().getString(R.string.remove_contact), 135 mContact.getName())); 136 mRemoveContactDialog = builder.create(); 137 } 138 139 @Override 140 protected void onBindView(View view) { 141 super.onBindView(view); 142 View deleteContactIcon = view.findViewById(R.id.delete_contact); 143 if (mRemoveContactPreferenceListener == null) { 144 deleteContactIcon.setVisibility(View.GONE); 145 } else { 146 deleteContactIcon.setOnClickListener(new View.OnClickListener() { 147 @Override 148 public void onClick(View view) { 149 showRemoveContactDialog(null); 150 } 151 }); 152 153 } 154 } 155 156 public Uri getContactUri() { 157 return mContact.getContactUri(); 158 } 159 160 @VisibleForTesting 161 EmergencyContactManager.Contact getContact() { 162 return mContact; 163 } 164 165 @VisibleForTesting 166 AlertDialog getRemoveContactDialog() { 167 return mRemoveContactDialog; 168 } 169 170 /** 171 * Calls the contact. 172 */ 173 public void callContact() { 174 Intent callIntent = 175 new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + mContact.getPhoneNumber())); 176 MetricsLogger.action(getContext(), MetricsEvent.ACTION_CALL_EMERGENCY_CONTACT); 177 getContext().startActivity(callIntent); 178 } 179 180 /** 181 * Displays a contact card for the contact. 182 */ 183 public void displayContact() { 184 Intent contactIntent = new Intent(Intent.ACTION_VIEW); 185 contactIntent.setData(mContact.getContactLookupUri()); 186 getContext().startActivity(contactIntent); 187 } 188 189 /** Shows the dialog to remove the contact, restoring it from {@code state} if it's not null. */ 190 private void showRemoveContactDialog(Bundle state) { 191 if (mRemoveContactDialog == null) { 192 return; 193 } 194 if (state != null) { 195 mRemoveContactDialog.onRestoreInstanceState(state); 196 } 197 mRemoveContactDialog.show(); 198 } 199 200 @Override 201 protected Parcelable onSaveInstanceState() { 202 final Parcelable superState = super.onSaveInstanceState(); 203 if (mRemoveContactDialog == null || !mRemoveContactDialog.isShowing()) { 204 return superState; 205 } 206 final SavedState myState = new SavedState(superState); 207 myState.isDialogShowing = true; 208 myState.dialogBundle = mRemoveContactDialog.onSaveInstanceState(); 209 return myState; 210 } 211 212 @Override 213 protected void onRestoreInstanceState(Parcelable state) { 214 if (state == null || !state.getClass().equals(SavedState.class)) { 215 // Didn't save state for us in onSaveInstanceState 216 super.onRestoreInstanceState(state); 217 return; 218 } 219 SavedState myState = (SavedState) state; 220 super.onRestoreInstanceState(myState.getSuperState()); 221 if (myState.isDialogShowing) { 222 showRemoveContactDialog(myState.dialogBundle); 223 } 224 } 225 226 private static class SavedState extends BaseSavedState { 227 boolean isDialogShowing; 228 Bundle dialogBundle; 229 230 public SavedState(Parcel source) { 231 super(source); 232 isDialogShowing = source.readInt() == 1; 233 dialogBundle = source.readBundle(); 234 } 235 236 @Override 237 public void writeToParcel(Parcel dest, int flags) { 238 super.writeToParcel(dest, flags); 239 dest.writeInt(isDialogShowing ? 1 : 0); 240 dest.writeBundle(dialogBundle); 241 } 242 243 public SavedState(Parcelable superState) { 244 super(superState); 245 } 246 247 public static final Parcelable.Creator<SavedState> CREATOR = 248 new Parcelable.Creator<SavedState>() { 249 public SavedState createFromParcel(Parcel in) { 250 return new SavedState(in); 251 } 252 253 public SavedState[] newArray(int size) { 254 return new SavedState[size]; 255 } 256 }; 257 } 258}