如何在android中以编程方式删除联系人

如何在android中以编程方式删除联系人,android,android-contacts,android-contentresolver,Android,Android Contacts,Android Contentresolver,我尝试使用以下代码删除指定号码的联系人: private void removeContact(Context context, String phone) { //context.getContentResolver().delete(Contacts.Phones.CONTENT_URI, phone, null); context.getContentResolver().delete(Contacts.Phones.CONTENT_URI, Conta

我尝试使用以下代码删除指定号码的联系人:

private void removeContact(Context context, String phone) {
    //context.getContentResolver().delete(Contacts.Phones.CONTENT_URI, phone, null);
    context.getContentResolver().delete(Contacts.Phones.CONTENT_URI,
          Contacts.PhonesColumns.NUMBER+"=?", new String[] {phone});
}
但我有一个例外:

java.lang.UnsupportedOperationException: Cannot delete that URL: content://contacts/phones
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:130)
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:110)
    at android.content.ContentProviderProxy.delete(ContentProviderNative.java:362)
    at android.content.ContentResolver.delete(ContentResolver.java:386)
你能告诉我如何解决我的问题吗


谢谢。

您是否在清单中声明了相应的权限

您需要android.permission.READ\u CONTACTS和android.permission.WRITE\u CONTACTS使用权限标签,android才会允许您与联系人提供商发生冲突:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.android.app.myapp" >

  <uses-permission android:name="android.permission.READ_CONTACTS" />
  <uses-permission android:name="android.permission.WRITE_CONTACTS" />

</manifest>

迟来的回答,但无论如何可能会有帮助:

如果您查看并搜索“Matter .Aduri”(如果它在中间停止加载,请不要惊讶,它在一两分钟后恢复加载),那么您可以看到它有一组可以处理的URI方案。它有一个用于“phones/#”的处理程序,但不用于“phones”,这正是您需要的

这意味着,没有代码可以删除所有电话号码,您必须先获取所有号码的ID,然后一次删除每个号码。当然,这需要更多的CPU和内存资源,但至少它可以工作

以下代码删除特定的数字。请注意,我没有测试这段代码,但它与我用来删除给定人员的所有号码的代码90%相同,这需要类似的处理,因为Android不能删除“people/#/phones”,而是“people/#/phones/#”

编辑:我刚刚意识到我误解了这个问题。我以为你想删除电话号码,我的代码就是这么做的。但是现在我看到你想删除contanct

private void deletePhoneNumber(Uri peopleUri,String numberToDelete){
Uri.Builder=peopleUri.buildon();
appendEncodedPath(People.Phones.CONTENT\u目录);
Uri PhoneNumberURI=builder.build();
字符串[]mPhoneNumberProjection={People.Phones.\u ID,People.Phones.NUMBER};
Cursor cur=resolver.query(PhoneNumberURI、mPhoneNumberProjection、,
空,空,空);
ArrayList idstodelite=新的ArrayList();
if(cur.moveToFirst()){
final int colId=cur.getColumnIndex(People.Phones.\u ID);
final int colNumber=cur.getColumnIndex(People.Phones.NUMBER);
做{
String id=cur.getString(colId);
字符串编号=cur.getString(colNumber);
if(number.equals(numberToDelete))
idsToDelete.add(id);
}while(cur.moveToNext());
}
cur.close();
用于(字符串id:idsToDelete){
builder.encodedPath(People.Phones.CONTENT_目录+“/”+id);
PhoneNumberURI=builder.build();
删除(PhoneNumberURI,“1=1”,null);
}
}
代码有点冗长,因为它有两个假设:

  • 可能有多行要删除(例如,号码存储两次)
  • 获取光标、删除行并继续使用光标可能不安全
这两种假设都是通过先将
idsToDelete
存储在
ArrayList
中,然后删除来处理的


你也可以考虑对你所搜索的数字进行规范化,并使用列<代码>人.Posi.NoMyByKix< /Cord>,因为它包含了标准化的数字。 要删除所有联系人,请使用以下代码:

ContentResolver cr = getContentResolver();
    Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
            null, null, null, null);
    while (cur.moveToNext()) {
        try{
            String lookupKey = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
            Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
            System.out.println("The uri is " + uri.toString());
            cr.delete(uri, null, null);
        }
        catch(Exception e)
        {
            System.out.println(e.getStackTrace());
        }
    }
要删除任何特定联系人,请修改查询

cr.delete(uri, null, null);
希望有帮助

这就是我们所需要的。 删除电话号码和姓名为的联系人

public static boolean deleteContact(Context ctx, String phone, String name) {
    Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phone));
    Cursor cur = ctx.getContentResolver().query(contactUri, null, null, null, null);
    try {
        if (cur.moveToFirst()) {
            do {
                if (cur.getString(cur.getColumnIndex(PhoneLookup.DISPLAY_NAME)).equalsIgnoreCase(name)) {
                    String lookupKey = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
                    Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
                    ctx.getContentResolver().delete(uri, null, null);
                    return true;
                }

            } while (cur.moveToNext());
        }

    } catch (Exception e) {
        System.out.println(e.getStackTrace());
    } finally {
        cur.close();
    }
    return false;
}
并提醒添加读/写联系人权限

<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />


我已使用此代码删除联系人。它将删除sim卡联系人以及电话联系人或仅删除存储在电话存储器中的联系人。

删除联系人的更好方法是使用联系人id删除所有原始联系人

    final ArrayList ops = new ArrayList();
    final ContentResolver cr = getContentResolver();
    ops.add(ContentProviderOperation
            .newDelete(ContactsContract.RawContacts.CONTENT_URI)
            .withSelection(
                    ContactsContract.RawContacts.CONTACT_ID
                            + " = ?",
                    new String[] { allId.get(i) })
            .build());

        try {
            cr.applyBatch(ContactsContract.AUTHORITY, ops);
            int deletecontact = serialList.get(allId.get(i));

        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (OperationApplicationException e) {
            e.printStackTrace();
        }
        //background_process();
        ops.clear();
    }
别忘了添加权限

        <uses-permission android:name="android.permission.READ_CONTACTS"/>
        <uses-permission android:name="android.permission.WRITE_CONTACTS"/>

此代码非常适合我将联系人从其标识符中删除(Contacts contract.Contacts.\u ID

必须单独删除该联系人所有号码的电话注册

  fun deleteContactById(id: String) {
      val cr = context.contentResolver
      val cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
                    null, null, null, null)
      cur?.let {
          try {
                    if (it.moveToFirst()) {
                        do {
                            if (cur.getString(cur.getColumnIndex(ContactsContract.PhoneLookup._ID)) == id) {
                                val lookupKey = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY))
                                val uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey)
                                cr.delete(uri, null, null)
                                break
                            }

                        } while (it.moveToNext())
                    }

                } catch (e: Exception) {
                    println(e.stackTrace)
                } finally {
                    it.close()
                }
            }
}

权限问题是最让我头疼的。有一次,我花了一周的时间试图弄清楚为什么我的振动代码一直崩溃,直到我发现你需要振动的许可…也许是我太愚蠢了,但我花了一段时间才弄清楚,对这个函数的调用需要像deletePhoneNumber(Contacts.CONTENT_URI,“555”)一样;工作。否则这是一个很好的答案,谢谢!是的,它正在工作,但问题是它没有从contact2.db(android数据库)数据库的
数据表中删除contact。请将查询修改为what?
java.lang.IllegalStateException:无法从CursorWindow读取第1323行第16列。在访问数据之前,请确保光标已正确初始化。
每次删除1323个联系人后,我都会尝试从设备中删除大约100k个联系人。如果联系人没有电话,您不能使用此功能删除。是否有任何方法可以修改此功能以仅删除基于姓名的联系人?请小心上面的代码。以当前的形式,我相信它将删除您手机上的所有联系人。此代码刚刚删除了我手机联系人中的所有内容!小心点,伙计们!为什么要将变量声明为final?此外,您不需要cr变量->可以使用直接getContentResolver().applyBatch(*
        <uses-permission android:name="android.permission.READ_CONTACTS"/>
        <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
  fun deleteContactById(id: String) {
      val cr = context.contentResolver
      val cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
                    null, null, null, null)
      cur?.let {
          try {
                    if (it.moveToFirst()) {
                        do {
                            if (cur.getString(cur.getColumnIndex(ContactsContract.PhoneLookup._ID)) == id) {
                                val lookupKey = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY))
                                val uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey)
                                cr.delete(uri, null, null)
                                break
                            }

                        } while (it.moveToNext())
                    }

                } catch (e: Exception) {
                    println(e.stackTrace)
                } finally {
                    it.close()
                }
            }
}