因項目需求,需要將本產品的客服電話信息,默默寫入用戶手機通訊錄中,作爲一個程序員,內心是拒絕的,但仍要實現該功能。
1. 動態申請讀寫權限
首先,在 Maniifest.xml 文件中添加如下兩個權限的聲明:
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
然後在代碼中需要用到讀寫權限時,動態申請權限:
requestRuntimePermission(new String[]{Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS}, new PermissionListener() {
@Override
public void onGranted() {
//todo 處理接下來的流程
}
@Override
public void onDenied(List<String> deniedPermission) {
showToast("權限被拒絕");
}
});
2. 判斷該聯繫人是否存在,如果存在,僅追加手機號碼;不存在,則新增該聯繫人的頭像、姓名及手機號等相關信息。
/**
* 添加聯繫人信息
*
*/
public static void insertConstacts(Context context, String name, List<String> list) {
try {
//該店管家用戶是否存在,存在的話,就追加號碼,不存在新增聯繫人
long rawContactId = getContactsId(context, name);
ContentValues values = new ContentValues();
if (rawContactId == 0 ) {
//插入raw_contacts表,並獲取_id屬性
Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
ContentResolver resolver = context.getContentResolver();
rawContactId = ContentUris.parseId(resolver.insert(uri, values));
//插入data表
uri = Uri.parse("content://com.android.contacts/data");
//add Name
values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
values.put(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/name");
values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, name);
resolver.insert(uri, values);
values.clear();
//寫入頭像
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_poraital);
ByteArrayOutputStream out = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
values.clear();
values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Photo.PHOTO, out.toByteArray());
context.getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
}
//寫入手機號碼
values.clear();
values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone1);
values.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
//插入data表
Uri uri = Uri.parse("content://com.android.contacts/data");
context.getContentResolver().insert(uri, values);
} catch (Exception e) {
Log.i(TAG, "insertConstacts: e = " + e.getMessage());
e.printStackTrace();
}
}
/**
* 判斷某個手機號是否存在
*/
public static boolean isThePhoneExist(Context context, String phoneNum) {
//uri= content://com.android.contacts/data/phones/filter/#
Cursor cursor = null;
try {
Uri uri = Uri.parse("content://com.android.contacts/data/phones/filter/" + phoneNum);
ContentResolver resolver = context.getContentResolver();
cursor = resolver.query(uri, new String[]{ContactsContract.Data.DISPLAY_NAME},
null, null, null); //從raw_contact表中返回display_name
if (cursor.moveToFirst()) {
//Log.i(TAG, "name=" + cursor.getString(0) + " , phoneNum = " + phoneNum);
cursor.close();
return true;
}
} catch (Exception e) {
//Log.i(TAG, "163 e =" + e.getMessage());
e.printStackTrace();
} finally {
if (cursor != null) {
cursor.close();
}
}
return false;
}
3. 查詢數據庫中所有的聯繫人
/**
* 獲取所有聯繫人信息
*/
public static List<SysContactsListBean> getAllSysContacts(Context context) {
List<SysContactsListBean> list = new ArrayList<>();
try {
ContentResolver resolver = context.getContentResolver();
SysContactsListBean sysContactsListBean;
Uri uri = Uri.parse("content://com.android.contacts/data/phones");
Cursor cursor1 = resolver.query(uri,
new String[]{ContactsContract.Data.RAW_CONTACT_ID,
ContactsContract.Data.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER},
null, null, null);
while (cursor1.moveToNext()) {
sysContactsListBean = new SysContactsListBean();
sysContactsListBean.setCustomerId(cursor1.getLong(0));
sysContactsListBean.setCustomerName(cursor1.getString(1));
sysContactsListBean.setPhoneNumber(cursor1.getString(2));
list.add(sysContactsListBean);
}
} catch (Exception e) {
e.printStackTrace();
}
if (!CollectorUtils.isEmpty(list)) {
Collections.sort(list, new Comparator<SysContactsListBean>() {
@Override
public int compare(SysContactsListBean o1, SysContactsListBean o2) {
return o2.getCustomerName().compareTo(o1.getCustomerName());
}
});
}
return list;
}
4. 總結
關於通訊錄的更多操作可參考鏈接:https://www.cnblogs.com/liaojie970/p/5744580.html
還有幾個表需要特別注意:
4.1 raw_contacts:存放聯繫人的 ID,_id屬性爲主鍵,聲明爲autoincrement,即不需要手動設置,其他屬性也不需要手動設置就有默認值;display_name屬性爲姓名;sort_key屬性可以用於查詢後的排序
4.2 mimetypes:存放數據的類型,比如"vnd.android.cursor.item/name"表示“姓名”類型的數據,"vnd.android.cursor.item/phone_v2"表示“電話”類型的數據;
4.3 data:存放具體的數據;raw_contact_id 屬性用來連接raw_contacts表,每條記錄表示一個具體數據;raw_contact_id 需要重點記住,手機中顯示的每一個聯繫人對應一個固定的raw_contact_id,raw_contact_id對應着 raw_contacts表的 _id ,他倆是相同的值,兩個表之間的關係必須理清。(我剛開始就是沒有理清表之間的關係,以及各個字段代表的意思,做起來就感覺很混亂,這3個表很重要)我們主要的數據(email、phone等)都存放在data表;
ps:有些手機系統下,data 表的 raw_contact_id 和 data 表的 raw_contacts表的 _id 不一定相同,如果用 後者的id 作爲主鍵來追加手機號碼,就會出現追加不成功的現象。切記,切記。