sim卡联系人的增删改查主要是通过ContentProvider来进行操作的,在android中对sim卡联系人操作的provider是定义在IccProvider.java这个类中的,这个类位于android源码的位置frameworks/base/telephony/java/com/android/internal/telephony/IccProvider.java,里面有对sim操作的uri定义和增删改查方法的定义
具体对sim卡联系人的增删改查都是通过AIDL IIccPhoneBook调用完成对sim的具体操作,在这里推荐一个查看android源码在线观看的网址,有兴趣的可以自己去看看。
对sim操作的uri单卡手机和双卡手机是不同的,你也可以查看相应的源码查看具体uri的定义
一般单卡为: "content://icc/adn" 双卡为 "content://icc/adn/subid/0" "content://icc/adn/subid/1"
1.查询sim卡里的联系人
public void queryAllContact() { Cursor cursor = getContentResolver().query(uri, null, null, null, null); Log.d(TAG, "cursor count=" + cursor.getCount()); while (cursor.moveToNext()) { String[] columnNames = cursor.getColumnNames(); for (int i = 0; i < columnNames.length; i++) { String name = cursor.getString(0); String number = cursor.getString(1); String emails = cursor.getString(2); String id = cursor.getString(3); simCardInfo cardInfo = new simCardInfo(id, name, emails, number); if (i == columnNames.length - 1) { Log.d(TAG, "simcardinfo=" + cardInfo.toString()); } } } }
public void insertContact(String name, String phoneNumber) { ContentValues values = new ContentValues(); values.put("tag", name); values.put("number", phoneNumber); Uri insertInfo = getContentResolver().insert(uri, values); Log.d(TAG, insertInfo.toString()); }
public void updateContact(String oldName, String oldPhone, String newName, String newPhone) { ContentValues values = new ContentValues(); values.put("tag", oldName); values.put("number", oldPhone); values.put("newTag", newName); values.put("newNumber", newPhone); int update = getContentResolver().update(uri, values, null, null); Log.d(TAG, "update =" + update); }
public void deleteContact(String name, String phone) { // 这种方式删除数据时不行,查阅IccProvider源码发现,在provider中重写的delete方法并没有用到String[] // whereArgs这个参数 // int delete = getContentResolver().delete(uri, // " tag = ? AND number = ? ", // new String[] { "jason", "1800121990" }); String where = "tag='" + name + "'"; where += " AND number='" + phone + "'"; int delete = getContentResolver().delete(uri, where, null); Log.d(TAG, "delete =" + delete); }在删除sim卡联系人时,开始利用下面的语句,发现删除返回的值一直为0,并没有删除成功。
int delete = getContentResolver().delete(uri, " tag = ? AND number = ? ", new String[] { "jason", "1800121990" });
通过查看Iccprovider具体定义的delete的地方并没有用到String[] whereArgs这个参数,而是通过where中对”AND“和“=”进行切割来实现的,具体代码如下
@Override public int delete(Uri url, String where, String[] whereArgs) { int efType; int subId; int match = URL_MATCHER.match(url); switch (match) { case ADN: efType = IccConstants.EF_ADN; subId = SubscriptionManager.getDefaultSubId(); break; case ADN_SUB: efType = IccConstants.EF_ADN; subId = getRequestSubId(url); break; case FDN: efType = IccConstants.EF_FDN; subId = SubscriptionManager.getDefaultSubId(); break; case FDN_SUB: efType = IccConstants.EF_FDN; subId = getRequestSubId(url); break; default: throw new UnsupportedOperationException( "Cannot insert into URL: " + url); } if (DBG) log("delete"); // parse where clause String tag = null; String number = null; String[] emails = null; String pin2 = null; String[] tokens = where.split("AND"); int n = tokens.length; while (--n >= 0) { String param = tokens[n]; if (DBG) log("parsing '" + param + "'"); String[] pair = param.split("="); if (pair.length != 2) { Rlog.e(TAG, "resolve: bad whereClause parameter: " + param); continue; } String key = pair[0].trim(); String val = pair[1].trim(); if (STR_TAG.equals(key)) { tag = normalizeValue(val); } else if (STR_NUMBER.equals(key)) { number = normalizeValue(val); } else if (STR_EMAILS.equals(key)) { //TODO(): Email is null. emails = null; } else if (STR_PIN2.equals(key)) { pin2 = normalizeValue(val); } } if (efType == FDN && TextUtils.isEmpty(pin2)) { return 0; } boolean success = deleteIccRecordFromEf(efType, tag, number, emails, pin2, subId); if (!success) { return 0; } getContext().getContentResolver().notifyChange(url, null); return 1; }
注册内容观察者
getContentResolver().registerContentObserver(uri, true, myContentObserver);定义自己的内容观察者继承ContentObserver
private class myContentObserve extends ContentObserver { public myContentObserve(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); Log.d(TAG, "数据库发生了改变。。。"); } }
if (myContentObserver != null) { getContentResolver().unregisterContentObserver(myContentObserver); }
当ContentProvider数据源发生改变后,如果想通知其监听对象, 例如ContentObserver时,必须在其对应方法 update / insert / delete时,显示的调用this.getContentReslover().notifychange(uri , null)方法,回调监听处理逻辑。否则,我们 的ContentObserver是不会监听到数据发生改变的,即onChange方法不会调用
另外,对sim卡联系人操作需要在清单文件中配置下面的权限
<uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.WRITE_CONTACTS"/>