讀取短信和聯繫人經常會用到,要了解的是這是內容提供者(contentProvider)的知識點,大家都知道數據庫是在data–>data 對應的包目錄下,其他應用是不可以訪問到的,如果有些數據要提供給其他的應用,比如通信錄,其他應用想獲取它的數據怎麼辦呢,這時內容提供者就出現了,預先寫好了一些操作數據庫的方法,因爲方法是開發這個應用的開發者提供的,所以保證了數據庫的安全操作,又能共享數據。

短信

開始切入正題,先說短信,要從數據庫中獲取數據,就要了解其結構

短信數據庫在data–>data中的下面路徑

它的表結構如下,有3個是我們要注意的,這3個是我們待會要用到的,其中date是毫秒值

Java代碼爲

//獲取內容提供者
ContentResolver contentResolver = getContentResolver();
//獲取短信表的路徑
Uri uri = Uri.parse("content://sms");
//設置要查詢的列名
String[] line = {"address", "date", "body"};
//各個參數的意思,路徑、列名、條件、條件參數、排序
Cursor cursor = contentResolver.query(uri, line, null, null, null);
//下面就跟操作普通數據庫一樣了
if (cursor != null) {
    while (cursor.moveToNext()) {
        String address = cursor.getString(cursor.getColumnIndex("address"));
        String date = cursor.getString(cursor.getColumnIndex("date"));
        String body = cursor.getString(cursor.getColumnIndex("body"));
        Log.e("短信", "address:" + address + "\ndate:" + date + "\nbody:" + body);
    }
    cursor.close();
}

聯繫人

獲取聯繫人就比較複雜了,其表結構也比較複雜,我們獲取聯繫人的姓名、電話號碼、郵箱,要通過3張表去提取

數據庫所在位置data–>data中的下面路徑

data表,這個表中的“data1”列幾乎包含了我們想要的數據,但是如何通過分類提取,第四列的代號說明了data1數據的類型,這些代號在mimetypes表中有對應的說明,要找到這些數據,又要通過raw_contact_id去查找,這些ID又來於raw_contacts表中

mimetypes表,對代號類型的說明

raw_contacts表,我們通信錄中要顯示的信息必須要在這裏找到對應的ID,當我們刪除了聯繫人,data表中的數據並沒有刪除,只是刪除了證張表contact_id變爲null,而不是真的刪除

瞭解其表結構後,就開始寫代碼了

//獲取內容提供者
ContentResolver contentResolver = getContentResolver();
//獲取raw_contacts表的路徑
Uri raw_contact_uri = Uri.parse("content://com.android.contacts/raw_contacts");
//各個參數的意思,路徑、列名、條件、條件參數、排序
Cursor contactId = contentResolver.query(raw_contact_uri, new String[]{"contact_id"}, null, null, null);
//下面就跟操作普通數據庫一樣了
if (contactId != null) {
    while (contactId.moveToNext()) {
        //獲取contact_id的值,它對應data表中raw_contact_id的值
        String id = contactId.getString(contactId.getColumnIndex("contact_id"));

        //獲取data表的路徑
        Uri data_uri = Uri.parse("content://com.android.contacts/data");
        //各個參數的意思,路徑、列名、條件、條件參數、排序
        Cursor dataCursor = contentResolver.query(data_uri, new String[]{"mimetype", "data1"},
                "raw_contact_id=?", new String[]{id}, null);
        if (dataCursor != null) {
            //每次循環創建一個實例用於保存data表中的數據
            ContactsData contactsData = new ContactsData();
            while (dataCursor.moveToNext()) {
                String type = dataCursor.getString(dataCursor.getColumnIndex("mimetype"));
                switch (type) {
                    case "vnd.android.cursor.item/email_v2":
                        //這是郵箱信息
                        contactsData.setEmail(dataCursor.getString(dataCursor.getColumnIndex("data1")));
                        break;
                    case "vnd.android.cursor.item/phone_v2":
                        //這是手機號碼信息
                        contactsData.setNumber(dataCursor.getString(dataCursor.getColumnIndex("data1")));
                        break;
                    case "vnd.android.cursor.item/name":
                        //這是聯繫人的名字
                        contactsData.setName(dataCursor.getString(dataCursor.getColumnIndex("data1")));
                        break;
                }
            }
            //把查詢到的信息添加到集合中
            contactsDatas.add(contactsData);
            dataCursor.close();
        }
    }
    contactId.close();
}
Log.d("測試","開始打印");
public class ContactsData {
    private String email;
    private String number;
    private String name;
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "ContactsData{" +
                "email='" + email + '\'' +
                ", number='" + number + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}
for (ContactsData c : contactsDatas) { Log.e("聯繫人", c.toString()); }

爲了方便管理創建一個Javabean

public class ContactsData {
    private String email;
    private String number;
    private String name;
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "ContactsData{" +
                "email='" + email + '\'' +
                ", number='" + number + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}

最後別忘了加上權限

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

如過是Android 6.0以上的版本還要動態獲取權限

獲取聯繫人的效果圖

真正應用

通常不會這樣直接寫它的路徑的,因爲手機廠商會修改它的路徑,還是這樣寫的話會報錯,說不存在這一列,需要使用Android提供的API

     /**
         * 通過ContactsContract.Contacts.CONTENT_URI來獲取_ID和DISPLAY_NAME
         * _ID 該聯繫人的索引
         * 通過這個ID可以在ContactsContract.CommonDataKinds.Phone.CONTENT_URI 中找到該聯繫人的電話號碼
         * 通過這個ID可以在ContactsContract.CommonDataKinds.Email.CONTENT_URI 找到該聯繫人的郵箱
         * DISPLAY_NAME 是該聯繫人的姓名
         */
        Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
        if (cursor != null) {
            while (cursor.moveToNext()) {
                ContactsData contactsData = new ContactsData();
                //獲取該聯繫人的ID
                String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
                //該聯繫人的姓名
                String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
                contactsData.setName(name);

                /**
                 * 查找該聯繫人的phone信息
                 * 在ContactsContract.CommonDataKinds.Phone.CONTENT_URI 中查詢
                 * 條件爲ContactsContract.CommonDataKinds.Phone.CONTACT_ID = 上面查詢到的ID
                 */
                Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                        ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + contactId, null, null);
                if (phones != null && phones.moveToNext()) {
                    //獲取該聯繫人的手機號碼
                    String number = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                    contactsData.setNumber(number);
                    phones.close();
                }

                /**
                 * 查找該聯繫人的email信息
                 * 在ContactsContract.CommonDataKinds.Email.CONTENT_URI 中查詢
                 * 條件爲ContactsContract.CommonDataKinds.Phone.CONTACT_ID = 上面查詢到的ID
                 */
                Cursor emails = getContentResolver().query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null,
                        ContactsContract.CommonDataKinds.Email.CONTACT_ID + "=" + contactId, null, null);
                if (emails != null && emails.moveToNext()) {
                    //獲取該聯繫人的郵箱
                    String email = emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
                    contactsData.setEmail(email);
                    emails.close();
                }
                contactsDatas.add(contactsData);
            }
            cursor.close();
        }
        Log.d("測試","開始打印");
        for (ContactsData c : contactsDatas) {
            Log.e("聯繫人", c.toString());
        }

看起來好像有點複雜,我們先看看下面的圖片再去看代碼,可能會容易理解,這些代碼一共操作了3個表,嚴格來說是視圖,在這3個表中獲得他們共同的ID,根據ID在這3個表中分別提取對應的姓名、電話號碼、郵箱

小夜