ContactDeletionInteraction.java revision 69e7fec6dd8a3d24054863c6c648512577fce35c
1/* 2 * Copyright (C) 2010 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 */ 16 17package com.android.contacts.interactions; 18 19import com.android.contacts.R; 20import com.android.contacts.model.ContactsSource; 21import com.android.contacts.model.Sources; 22 23import android.app.Activity; 24import android.app.AlertDialog; 25import android.app.Dialog; 26import android.content.ContentUris; 27import android.content.Context; 28import android.content.CursorLoader; 29import android.content.DialogInterface; 30import android.content.Loader; 31import android.database.Cursor; 32import android.net.Uri; 33import android.os.Bundle; 34import android.provider.ContactsContract.RawContacts; 35import android.util.Log; 36 37// TODO: This should respect the lookup element. The Id might by now refer to a different contact 38/** 39 * An interaction invoked to delete a contact. 40 */ 41public class ContactDeletionInteraction { 42 43 private static final String TAG = "ContactDeletionInteraction"; 44 45 public static final String EXTRA_KEY_CONTACT_URI = "contactUri"; 46 public static final String EXTRA_KEY_MESSAGE_ID = "messageId"; 47 48 private static final String[] RAW_CONTACTS_PROJECTION = new String[] { 49 RawContacts._ID, //0 50 RawContacts.ACCOUNT_TYPE, //1 51 }; 52 53 private final class RawContactLoader extends CursorLoader { 54 private final Uri mContactUri; 55 56 private RawContactLoader(Context context, Uri contactUri) { 57 super(context, 58 RawContacts.CONTENT_URI, 59 RAW_CONTACTS_PROJECTION, 60 RawContacts.CONTACT_ID + "=?", 61 new String[] { String.valueOf(ContentUris.parseId(contactUri)) }, 62 null); 63 this.mContactUri = contactUri; 64 } 65 66 @Override 67 public void deliverResult(Cursor data) { 68 if (data == null || data.getCount() == 0) { 69 Log.e(TAG, "No such contact: " + mContactUri); 70 return; 71 } 72 73 showConfirmationDialog(data, mContactUri); 74 } 75 } 76 77 private final class ConfirmationDialogClickListener implements DialogInterface.OnClickListener { 78 private final Uri mContactUri; 79 80 public ConfirmationDialogClickListener(Uri contactUri) { 81 this.mContactUri = contactUri; 82 } 83 84 public void onClick(DialogInterface dialog, int which) { 85 doDeleteContact(mContactUri); 86 } 87 } 88 89 private Context mContext; 90 private CursorLoader mLoader; 91 92 public void attachToActivity(Activity activity) { 93 setContext(activity); 94 } 95 96 /* Visible for testing */ 97 void setContext(Context context) { 98 mContext = context; 99 } 100 101 public void deleteContact(Uri contactUri) { 102 if (mLoader != null) { 103 mLoader.destroy(); 104 } 105 mLoader = new RawContactLoader(mContext, contactUri); 106 startLoading(mLoader); 107 } 108 109 protected void showConfirmationDialog(Cursor cursor, Uri contactUri) { 110 int writableSourcesCnt = 0; 111 int readOnlySourcesCnt = 0; 112 113 Sources sources = getSources(); 114 try { 115 while (cursor.moveToNext()) { 116 final long rawContactId = cursor.getLong(0); 117 final String accountType = cursor.getString(1); 118 ContactsSource contactsSource = sources.getInflatedSource(accountType, 119 ContactsSource.LEVEL_SUMMARY); 120 boolean readonly = contactsSource != null && contactsSource.readOnly; 121 if (readonly) { 122 readOnlySourcesCnt ++; 123 } else { 124 writableSourcesCnt ++; 125 } 126 } 127 } finally { 128 cursor.close(); 129 } 130 131 int messageId; 132 if (readOnlySourcesCnt > 0 && writableSourcesCnt > 0) { 133 messageId = R.string.readOnlyContactDeleteConfirmation; 134 } else if (readOnlySourcesCnt > 0 && writableSourcesCnt == 0) { 135 messageId = R.string.readOnlyContactWarning; 136 } else if (readOnlySourcesCnt == 0 && writableSourcesCnt > 1) { 137 messageId = R.string.multipleContactDeleteConfirmation; 138 } else { 139 messageId = R.string.deleteConfirmation; 140 } 141 142 Bundle bundle = new Bundle(); 143 bundle.putParcelable(EXTRA_KEY_CONTACT_URI, contactUri); 144 bundle.putInt(EXTRA_KEY_MESSAGE_ID, messageId); 145 146 showDialog(bundle); 147 } 148 149 /** 150 * Creates a delete confirmation dialog and returns it. Returns null if the 151 * id is not for a deletion confirmation. 152 */ 153 public Dialog onCreateDialog(int id, Bundle bundle) { 154 if (id != R.id.dialog_delete_contact_confirmation) { 155 return null; 156 } 157 158 return new AlertDialog.Builder(mContext) 159 .setTitle(R.string.deleteConfirmation_title) 160 .setIcon(android.R.drawable.ic_dialog_alert) 161 .setMessage(R.string.deleteConfirmation) 162 .setNegativeButton(android.R.string.cancel, null) 163 .setPositiveButton(android.R.string.ok, null) 164 .create(); 165 } 166 167 public boolean onPrepareDialog(int id, Dialog dialog, Bundle bundle) { 168 if (id != R.id.dialog_delete_contact_confirmation) { 169 return false; 170 } 171 172 Uri contactUri = bundle.getParcelable(EXTRA_KEY_CONTACT_URI); 173 int messageId = bundle.getInt(EXTRA_KEY_MESSAGE_ID, R.string.deleteConfirmation); 174 175 ((AlertDialog)dialog).setMessage(mContext.getText(messageId)); 176 ((AlertDialog)dialog).setButton(DialogInterface.BUTTON_POSITIVE, 177 mContext.getText(android.R.string.ok), 178 new ConfirmationDialogClickListener(contactUri)); 179 180 return true; 181 } 182 183 protected void doDeleteContact(Uri contactUri) { 184 mContext.getContentResolver().delete(contactUri, null, null); 185 } 186 187 /* Visible for testing */ 188 void startLoading(Loader<Cursor> loader) { 189 loader.startLoading(); 190 } 191 192 /* Visible for testing */ 193 Sources getSources() { 194 return Sources.getInstance(mContext); 195 } 196 197 /* Visible for testing */ 198 void showDialog(Bundle bundle) { 199 ((Activity)mContext).showDialog(R.id.dialog_delete_contact_confirmation, bundle); 200 } 201} 202