数据库中删除SIM卡联系人

时间:2021-03-28 07:52:20

4,SIM卡联系人

Contacts2.db数据库中联系人其实包括2部分,手机上面的联系人以及SIM卡中的联系人。

当然, SIM卡中的联系人是保存在单独的数据库中,其对应的Provider为IccProvider,在packages\services\Telephony 路径下,也就是phone进程中。

AndroidManifest.xml对应的定义如下,

<provider android:name="IccProvider"
    android:authorities="icc"
    android:multiprocess="true"
    android:exported="true"
    android:readPermission="android.permission.READ_CONTACTS"
    android:writePermission="android.permission.WRITE_CONTACTS" />

IccProvider定义如下,

public class IccProvider extends com.android.internal.telephony.IccProvider {
    public IccProvider() {
        super();
    }
}

直接继承系统jar包中的IccProvider类。因此,增删改查直接看jar包中的IccProvider类就可以了。

----找了好久都找不到对应的db数据库。

在联系人相关界面上,可以看到,

1,拔出SIM卡,仅显示phone中的联系人;

2,插上SIM卡,又会显示SIM卡上的联系人。

因此,可以这样推断,当拨号SIM卡时,会从Contacts2.db数据库中删除SIM卡的联系人;

当插上SIM卡时,会将插上SIM卡中的联系人同步到Contacts2.db数据库中。并且在这2种情况下,导出Contacts2.db数据库,的确是这样的。到底是怎么发生的呢?

分析SimContacts apk,路径:vendor\qcom\proprietary\telephony-apps\SimContacts

4.1 删除联系人

AndroidManifest.xml的SimStateReceiver服务,配置如下,

<receiver android:name="SimStateReceiver">
<intent-filter android:priority="1000">
   <action android:name="android.intent.action.SIM_STATE_CHANGED"/>
   <action android:name="android.intent.action.BOOT_COMPLETED" />
   <action android:name="org.codeaurora.intent.action.ACTION_SIM_REFRESH_UPDATE"/>
 </intent-filter>
</receiver>

注册了三个广播。分别是开机广播,SIM卡状态变化的广播,SIM卡状态更新的广播。

SimStateReceiver的逻辑也很简单,就是启动SimStateReceiver服务完成真正的功能。

sendPhoneBoot/sendSimState/sendSimRefreshUpdate/这三个方法最后都会启动SimContactsService服务,

mContext.startService(new Intent(mContext, SimContactsService.class).putExtras(args));

AndroidManifest.xml的SimStateReceiver服务,配置如下,

<receiver android:name="SimStateReceiver">
 <intent-filter android:priority="1000">
    <action android:name="android.intent.action.SIM_STATE_CHANGED"/>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
   <action android:name="org.codeaurora.intent.action.ACTION_SIM_REFRESH_UPDATE"/>
 </intent-filter>
</receiver>

注册了三个action,分别是开机,SIM卡状态变化的广播,SIM卡插拔的广播。也就是说, SimContactsService服务在Android系统启动之后就会启动。

SimContactsService是利用Handler切换到UI线程来执行的。

当SIM卡状态变化时, SimContactsService 的onCreate方法内的匿名Handler的handleMessage方法对应的处理如下,

case MSG_SIM_STATE_CHANGED:
•••
if (mSimState[slotId] == SimContactsConstants.SIM_STATE_NOT_READY
     || mSimState[slotId] == SimContactsConstants.SIM_STATE_ERROR) {
       // To handle card absent/error, hot swap related cases.
   deleteDatabaseSimContacts(slotId);
break;
•••

调用deleteDatabaseSimContacts方法删除Contacts2.db数据库中的SIM联系人。

deleteDatabaseSimContacts方法如下,

getContentResolver().delete(ContactsContract.RawContacts.CONTENT_URI,
  SIM_DATABASE_SELECTION, getSimAccountDBSelectArgs(slotId));

调用ContentResolver的delete方法从Contacts2.db数据库的raw_contacts表中删除对应SIM卡联系人。

SIM_DATABASE_SELECTION变量如下,

static final String SIM_DATABASE_SELECTION = RawContacts.ACCOUNT_TYPE + "=?" + " AND " +RawContacts.ACCOUNT_NAME + "=?" + " AND " + RawContacts.DELETED + "=?";

getSimAccountDBSelectArgs方法如下,

return new String[] {
   SimContactsConstants.ACCOUNT_TYPE_SIM,
   SimContactsConstants.getSimAccountName(slotId), "0"
};

SimContactsConstants的ACCOUNT_TYPE_SIM定义如下,

public static final String ACCOUNT_TYPE_SIM = "com.android.sim";

SimContactsConstants的getSimAccountName方法如下,

if (TelephonyManager.getDefault().isMultiSimEnabled()) {
    return ACCOUNT_NAME_SIM + (slotId + 1);
} else {
    return ACCOUNT_NAME_SIM;
}

ACCOUNT_NAME_SIM定义如下,

public static final String ACCOUNT_NAME_SIM = "SIM";

因此,删除语句意思为:

从raw_contacts表中删除account_type为"com.android.sim", account_name为SIM1,并且deleted为0的联系人。

 

Contacts2.db数据库的account表单部分如下,

数据库中删除SIM卡联系人

raw_contacts表单部分如下,

数据库中删除SIM卡联系人

分析这2张表单, deleted为0表示当前的联系人,为1表示已经删除的联系人。

account_type为1的表示是phone联系人,其他的表示从SIM卡同步的联系人,当前还有双卡的情况。

在此,就一目了然了。稍微有点不同的是,这里并没有在子线程中采用异步的方法。