系统的电话记录保存在contacts2.db这张表中,而我们的通话记录则保存在calls这张表中,如图:
那么清除通话记录需要访问源码,打开联系人源码的清单文件:
我们看到主机名如下:
再进入.java文件中查看CallLogProvider类,我们看到路径名是什么了:
/**
* 利用内容提供者去删除通话记录
*
* @param incomingNumber
*/
public void deleteCallLog(String incomingNumber) {
//内容提供者解析器
ContentResolver resolver = getContentResolver();
//呼叫记录的uri路径
Uri uri = Uri.parse("content://call_log/calls");
//CallLog.CONTENT_URI 直接使用常量也可以
resolver.delete(uri, "number=?", new String[]{incomingNumber});
}
也可以直接使用Android提供的CallLog类:
调用:
endCall();// 在另外一个进程里面运行的远程服务的方法,方法调用后,呼叫记录可能还没有生成,导致清除不掉呼叫记录
// 删除呼叫记录
// 另外一个应用程序的私有的联系人数据库
deleteCallLog(incomingNumber);//本方法和endCall()不在一个进程中运行
那么此时会有很大的问题:
我们会发现有时候log清除的很及时,有时候又不是很及时,原因在于endCall()这个方法,这个方法是在另外一个进程里面运行的远程服务的方法,而删除记录的方法是在另外一个进程中运行的。
我们可以让清除的方法睡眠两秒进行,但是这样的体验很差,实践的做法是:
注册一个ContentObserver去监听数据库中呼叫记录的变化,当有呼叫记录变化时,调用清除的方法,同时,当监听到呼叫记录变化时,ContentObserver也不需要了,可以取消注册。
private class MyListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
String mode = dao.findMode(incomingNumber);
if ("1".equals(mode) || "3".equals(mode)) {
// 挂断电话
Log.i(TAG, "挂断电话");
//观察呼叫记录数据库内容的变化
// 呼叫记录的uri路径
Uri uri = Uri.parse("content://call_log/calls");
getContentResolver().registerContentObserver(uri, true, new CallLogObserver(incomingNumber,new Handler()));
endCall();// 在另外一个进程里面运行的远程服务的方法,方法调用后,呼叫记录可能还没有生成,导致清除不掉呼叫记录
// 删除呼叫记录
// 另外一个应用程序的私有的联系人数据库
//deleteCallLog(incomingNumber);//本方法和endCall()不在一个进程中运行
}
break;
case TelephonyManager.CALL_STATE_IDLE:
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
default:
break;
}
super.onCallStateChanged(state, incomingNumber);
}
}
private class CallLogObserver extends ContentObserver{
private String incomingNumber;
public CallLogObserver(String incomingNumber,Handler handler) {
super(handler);
this.incomingNumber = incomingNumber;
}
@Override
public void onChange(boolean selfChange) {
Log.i(TAG, "数据库的内容变化了,产生了呼叫记录");
//取消注册
getContentResolver().unregisterContentObserver(this);
deleteCallLog(incomingNumber);
super.onChange(selfChange);
}
}
incomingNumber通过构造器传过去。
清除呼叫记录需要两个权限:
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
<uses-permission android:name="android.permission.WRITE_CALL_LOG"/>