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