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