1. 程式人生 > >資料庫中刪除SIM卡聯絡人

資料庫中刪除SIM卡聯絡人

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表單部分如下,


raw_contacts表單部分如下,


分析這2張表單, deleted為0表示當前的聯絡人,為1表示已經刪除的聯絡人。

account_type為1的表示是phone聯絡人,其他的表示從SIM卡同步的聯絡人,當前還有雙卡的情況。

在此,就一目瞭然了。稍微有點不同的是,這裡並沒有在子執行緒中採用非同步的方法。