批量/批量删除联系人 - 采取长期的方式

时间:2014-02-13 12:34:04

标签: android contacts android-contacts contactscontract

我正在开发一个REST应用程序来批量删除联系人(我的意思是联系人,而不是原始联系人)。删除一批约116个联系人需要3分钟以上,这在我看来很多。有时会打印Contacts deleted,但它们仍然在手机的联系人列表中,有时则会被删除。

有人能指出我的问题在哪里吗?

我收到一个JSONArray,其中包含要删除的联系人ID(以及其他一些细节,但只有在此方法中使用的ID)。

这是我的删除联系人代码:

public Boolean deleteBatchContact(final JSONArray jsonArray) throws JSONException, RemoteException, OperationApplicationException
{
    final ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
    final Long startTime = System.currentTimeMillis();

    if(jsonArray.length() != 0) // there must be something in the JSONArray
    {
        for(int i = 0; i < jsonArray.length(); i++)
        {
            final JSONObject jsonContactObject = jsonArray.getJSONObject(i);
            final String contactId = jsonContactObject.getString("id");
            Long id = Long.parseLong(contactId);

            ops.add(ContentProviderOperation.newDelete(ContentUris.withAppendedId(Contacts.CONTENT_URI, Long.parseLong(contactId)))
                    .withYieldAllowed(true)
                    .build());
        }

        try {
            final ContentProviderResult[] cpr = contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
            final Long endTimeTry = System.currentTimeMillis();
            final Integer numberOfContactsDeleted = cpr.length;

            if(numberOfContactsDeleted > 0)
            {
                Log.d(TAG, numberOfContactsDeleted + " Contacts deleted!");
                final Long totalSuccess = endTimeTry-startTime;
                Log.d(TAG, "Total Time (Sucess): " + totalSuccess);

                return true;
            }
            else 
            {
                Log.d(TAG, "Menor ou igual a zero...");
                final Long totalFailed = endTimeTry-startTime;
                Log.d(TAG, "Total Time (No deletes): " + totalFailed);
                return false;
            }

        } catch (Exception e) {
            Log.d(TAG, "deleteBatchContact: " + e.getMessage());
            return false;
        }
    }
    Long endTimeReturnFalse = System.currentTimeMillis();
    Long totalTimeReturnFalse = endTimeReturnFalse - startTime;
    Log.d(TAG, "Total time return false: " + totalTimeReturnFalse);
    return false;
}

这就是我调用deleteBatchContact方法的地方:

else if(type.equalsIgnoreCase("delete"))
    {
        Log.d(TAG, "DELETE REQUEST");
        String strJson = request.getEntityAsText();
        int age = response.getAge();
        Log.d(TAG, "age1: " + age);
        Log.d(TAG, "is commited1? " + response.isCommitted());
        try {
            Log.d(TAG, "Try...");
            JSONArray jsonArray = new JSONArray(strJson);
            if(processDelete(jsonArray) == true)
            {
                Log.d(TAG, "Response -> Deleted with Success!");
                response.setEntity("Deleted with success!", MediaType.TEXT_ALL);
                age = response.getAge();
                Log.d(TAG, "age2: " + age);
                Log.d(TAG, "is commited2? " + response.isCommitted());
            }
            else
            {
                Log.d(TAG, "Response -> No contacts deleted...");
                response.setEntity("No contacts deleted...", MediaType.TEXT_ALL);
                age = response.getAge();
                Log.d(TAG, "age3: " + age);
                Log.d(TAG, "is commited3? " + response.isCommitted());
            }
        } catch (RemoteException e) {
            Log.d(TAG, "processDelete exception: " + e.getMessage());
            e.printStackTrace();
        } catch (JSONException e) {
            Log.d(TAG, "processDelete exception: " + e.getMessage());
            e.printStackTrace();
        } catch (OperationApplicationException e) {
            Log.d(TAG, "processDelete exception: " + e.getMessage());
            e.printStackTrace();
        }

    }

这是输出:

02-13 01:28:04.484: D/ContactRestlet(17638): DELETE REQUEST
02-13 01:28:04.507: D/ContactRestlet(17638): age1: 0
02-13 01:28:04.507: D/ContactRestlet(17638): is commited1? false
02-13 01:28:04.507: D/ContactRestlet(17638): Try...
02-13 01:30:04.671: D/ContactRestlet(17638): DELETE REQUEST
02-13 01:30:04.671: D/ContactRestlet(17638): age1: 0
02-13 01:30:04.671: D/ContactRestlet(17638): is commited1? false
02-13 01:30:04.671: D/ContactRestlet(17638): Try...
02-13 01:31:07.468: D/ContactList(17638): 116 Contacts deleted!
02-13 01:31:07.468: D/ContactList(17638): Total Time (Sucess): 182911
02-13 01:31:07.468: D/ContactRestlet(17638): Response -> Deleted with Success!
02-13 01:31:07.472: D/ContactRestlet(17638): age2: 0
02-13 01:31:07.472: D/ContactRestlet(17638): is commited2? false
02-13 01:31:07.476: W/System.err(17638): 2014-02-13 01:31:07    -   -   -   8080    DELETE  /contacts   -   1001    21  12590   62837   http://10.17.1.72:8080  Apache-HttpClient/4.3.1 (java 1.5)  -

修改 正如@RocketRandom所建议的,这是我的新代码:

    public Boolean deleteBatchContact(final JSONArray jsonArray) throws JSONException, RemoteException, OperationApplicationException
{
    final ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
    final Long startTime = System.currentTimeMillis();

    if(jsonArray.length() != 0) // there must be something in the JSONArray
    {
        StringBuilder query = new StringBuilder(" in {");
        for(int i = 0; i < jsonArray.length(); i++)
        {   
            final JSONObject jsonContactObject = jsonArray.getJSONObject(i);
            final String contactId = jsonContactObject.getString("id");

            query.append(contactId).append(",");
        }
        query.deleteCharAt(query.length()-1);
        query.append("}");

        ops.add(ContentProviderOperation.newDelete(Contacts.CONTENT_URI)
        .withSelection(Contacts._ID + " in { 1 , 2 , 3 , 4 , 5, 6, 7, 8, 9}", null).build()); 

        try {
            final ContentProviderResult[] cpr = contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
            final Long endTimeTry = System.currentTimeMillis();
            final Integer numberOfContactsDeleted = cpr.length;

            if(numberOfContactsDeleted > 0)
            {
                Log.d(TAG, numberOfContactsDeleted + " Contacts deleted!");
                final Long totalSuccess = endTimeTry-startTime;
                Log.d(TAG, "Total Time (Sucess): " + totalSuccess);

                return true;
            }
            else 
            {
                Log.d(TAG, "Menor ou igual a zero...");
                final Long totalFailed = endTimeTry-startTime;
                Log.d(TAG, "Total Time (No deletes): " + totalFailed);
                return false;
            }
        } catch (Exception e) {
            Log.d(TAG, "deleteBatchContact: " + e.getMessage());
            return false;
        }
    }
    Long endTimeReturnFalse = System.currentTimeMillis();
    Long totalTimeReturnFalse = endTimeReturnFalse - startTime;
    Log.d(TAG, "Total time return false: " + totalTimeReturnFalse);
    return false;
}

这是输出:

03-06 01:42:10.367: D/ContactList(8925): 1 Contacts deleted!
03-06 01:42:10.367: D/ContactList(8925): Total Time (Sucess): 84

现在它没有删除任何联系人,你能发现错误在哪里吗? 即使它说删除了一个联系人,也没有删除。所有这些联系ID都是有效的(它们存在于我的联系人表中,我已经从我的设备上下载并检查它。)

1 个答案:

答案 0 :(得分:1)

编辑:删除了之前建议的解决方案。这是行不通的。 (对不起)

我检查了联系人提供商代码,只有原始联系人支持批量删除。对于联系人他们在那里所做的只是返回,他们在那里有一个不错的小“TODO”。

您的原始代码是正确的方法。 当您删除联系人(没有isCallerSyncAdapter标志)时,提供程序执行的操作是查询具有该联系人ID的所有原始联系人并逐个设置脏标记(这需要一段时间)

我在我的结尾尝试了:

03-19 13:28:11.620:D / tmp(5912):188联系人被删除!

03-19 13:28:11.620:D / tmp(5912):总时间(成功):387496

即每次接触大约需要2秒钟,这太可怕了。 但是,如果不修改Android Contacts ContentProvider

,我就没有办法让它更快