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  */
16 
17 package com.android.contacts.group;
18 
19 import android.content.Context;
20 import android.content.Intent;
21 import android.database.Cursor;
22 import android.net.Uri;
23 import android.os.AsyncTask;
24 import android.provider.ContactsContract;
25 import android.provider.ContactsContract.RawContacts;
26 import android.widget.Toast;
27 
28 import com.android.contacts.ContactSaveService;
29 import com.android.contacts.R;
30 import com.android.contacts.activities.PeopleActivity;
31 
32 /**
33  * Starts an Intent to add/remove the raw contacts for the given contact IDs to/from a group.
34  * Only the raw contacts that belong to the specified account are added or removed.
35  */
36 public class UpdateGroupMembersAsyncTask extends AsyncTask<Void, Void, Intent> {
37     static final int TYPE_ADD = 0;
38     static final int TYPE_REMOVE = 1;
39 
40     private final Context mContext;
41     private final int mType;
42     private final long[] mContactIds;
43     private final long mGroupId;
44     private final String mAccountName;
45     private final String mAccountType;
46     private final String mDataSet;
47 
UpdateGroupMembersAsyncTask(int type, Context context, long[] contactIds, long groupId, String accountName, String accountType, String dataSet)48     public UpdateGroupMembersAsyncTask(int type, Context context, long[] contactIds,
49             long groupId, String accountName, String accountType, String dataSet) {
50         mContext = context;
51         mType = type;
52         mContactIds = contactIds;
53         mGroupId = groupId;
54         mAccountName = accountName;
55         mAccountType = accountType;
56         mDataSet = dataSet;
57     }
58 
59     @Override
doInBackground(Void... params)60     protected Intent doInBackground(Void... params) {
61         final long[] rawContactIds = getRawContactIds();
62         if (rawContactIds.length == 0) {
63             return null;
64         }
65         final long[] rawContactIdsToAdd;
66         final long[] rawContactIdsToRemove;
67         final String action;
68         if (mType == TYPE_ADD) {
69             rawContactIdsToAdd = rawContactIds;
70             rawContactIdsToRemove = null;
71             action = GroupUtil.ACTION_ADD_TO_GROUP;
72         } else if (mType == TYPE_REMOVE) {
73             rawContactIdsToAdd = null;
74             rawContactIdsToRemove = rawContactIds;
75             action = GroupUtil.ACTION_REMOVE_FROM_GROUP;
76         } else {
77             throw new IllegalStateException("Unrecognized type " + mType);
78         }
79         return ContactSaveService.createGroupUpdateIntent(
80                 mContext, mGroupId, /* newLabel */ null, rawContactIdsToAdd,
81                 rawContactIdsToRemove, PeopleActivity.class, action);
82     }
83 
84     // TODO(wjang): prune raw contacts that are already in the group; ContactSaveService will
85     // log a warning if the raw contact is already a member and keep going but it is not ideal.
getRawContactIds()86     private long[] getRawContactIds() {
87         final Uri.Builder builder = RawContacts.CONTENT_URI.buildUpon();
88         // null account names are not valid, see ContactsProvider2#appendAccountFromParameter
89         if (mAccountName != null) {
90             builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, mAccountName);
91             builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, mAccountType);
92         }
93         if (mDataSet != null) {
94             builder.appendQueryParameter(RawContacts.DATA_SET, mDataSet);
95         }
96         final Uri rawContactUri = builder.build();
97         final String[] projection = new String[]{ContactsContract.RawContacts._ID};
98         final StringBuilder selection = new StringBuilder();
99         final String[] selectionArgs = new String[mContactIds.length];
100         for (int i = 0; i < mContactIds.length; i++) {
101             if (i > 0) {
102                 selection.append(" OR ");
103             }
104             selection.append(ContactsContract.RawContacts.CONTACT_ID).append("=?");
105             selectionArgs[i] = Long.toString(mContactIds[i]);
106         }
107         final Cursor cursor = mContext.getContentResolver().query(
108                 rawContactUri, projection, selection.toString(), selectionArgs, null, null);
109         final long[] rawContactIds = new long[cursor.getCount()];
110         try {
111             int i = 0;
112             while (cursor.moveToNext()) {
113                 rawContactIds[i] = cursor.getLong(0);
114                 i++;
115             }
116         } finally {
117             cursor.close();
118         }
119         return rawContactIds;
120     }
121 
122     @Override
onPostExecute(Intent intent)123     protected void onPostExecute(Intent intent) {
124         if (intent == null) {
125             Toast.makeText(mContext, R.string.groupSavedErrorToast, Toast.LENGTH_SHORT).show();
126         } else {
127             mContext.startService(intent);
128         }
129     }
130 }
131