[mobilesafe] 05_清除通话记录

Android 4.0

清除通话记录

通话记录
通话记录保存在\data\data\com.android.providers.contacts\databases\contacts2.db数据库中calls表
number:电话号码
date:时间
type:通话记录类型
1:呼入电话
2:呼出电话
3:未接通电话
  
查找系统提供的内容提供者:\packages\providers\ContactsProvider\AndroidManifest.xml
<provider android:name="CallLogProvider"
            android:authorities="call_log"
            android:syncable="false" android:multiprocess="false"
            android:exported="true"
            android:readPermission="android.permission.READ_CALL_LOG"
            android:writePermission="android.permission.WRITE_CALL_LOG">
</provider>
a)可以看到主机名为:call_log
b)查看CallLogProvider.java的定义,路径uri怎么写
 static {
    sURIMatcher.addURI(CallLog.AUTHORITY, "calls", CALLS);
    sURIMatcher.addURI(CallLog.AUTHORITY, "calls/#", CALLS_ID);
    sURIMatcher.addURI(CallLog.AUTHORITY, "calls/filter/*", CALLS_FILTER);
}
核心代码:
package cn.zengfansheng.mobilesafe.service;
import java.lang.reflect.Method;
import android.app.Service;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import cn.zengfansheng.mobilesafe.db.dao.BlackNumberDao;
import com.android.internal.telephony.ITelephony;
/**
 * 3、黑名单电话短信监听服务
 * @author hacket
 */
public class CallSmsSafeService extends Service {
    private TelephonyManager tm;// 电话管理者
    private PhoneStateListener listener;// 电话状态监听器
    private BlackNumberDao blackNumberDao;// 黑名单dao
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    // 1、服务开启时
    @Override
    public void onCreate() {
        super.onCreate();
        blackNumberDao = new BlackNumberDao(getApplicationContext());
        // 初始化电话管理者
        tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        listener = new MyPhoneStateListener();
        tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
    }
    // 2、服务停止时
    @Override
    public void onDestroy() {
        super.onDestroy();
        tm.listen(listener, PhoneStateListener.LISTEN_NONE);
        listener = null;
    }
    
    private class MyPhoneStateListener extends PhoneStateListener {
        private static final String TAG = "MyPhoneStateListener";
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            super.onCallStateChanged(state, incomingNumber);
            switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:// 电话响铃的时候,查找数据库来电号码是否在黑名单数据库中
                String blacknumberMode = blackNumberDao.getBlackNumberMode(incomingNumber);
                // 检查当前的号码是否需要拦截,如果需要,挂断电话
                if (!TextUtils.isEmpty(blacknumberMode)) {
                    if ("1".equals(blacknumberMode) || "3".equals(blacknumberMode)) {// 拦截模式为"1",即电话拦截;或者"3",全部拦截
                        Log.i(TAG"拦截黑名单:" + incomingNumber);
                        endCall();// 挂断电话
                        // clearCallLog(incomingNumber);// 清除通话记录,写这里有时会移除不了通话记录
                        // 在呼叫记录产生之后, 才能去移除呼叫记录
                        
                        //注册一个内容观察者-观察通话记录生成,就删除掉
                        Uri uri = Uri.parse("content://call_log/calls");
                        getContentResolver().registerContentObserver(uri, true,
                              new CallLogObserver(new Handler(),incomingNumber));// 参数二:true表示匹配前缀
                        return;
                    }
                }
                break;
            }
        }
    }
    /**
     * 5、通话记录生成的内容观察者
     * @author hacket
     */
    private class CallLogObserver extends ContentObserver {
        
        private static final String TAG = "MyObserver";
        private String incomingNumber;
        public CallLogObserver(Handler handler, String incomingNumber) {
            super(handler);
            this.incomingNumber = incomingNumber;
        }
        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            Log.i(TAG"观察到数据库内容变化.删除呼叫记录");
            clearCallLog(incomingNumber);// 当观察到内容变化,执行删除通话记录的操作
            getContentResolver().unregisterContentObserver(this);
           // 删除通话记录后,将该内容观察者给注销掉,反注册自己(因为this就是这个内容观察者)
        }
    }
    /**
     * 4、清除通话记录
     * @param incomingNumber 要清除的号码的通话记录
     */
    private void clearCallLog(String incomingNumber) {
        /*<provider android:name="CallLogProvider"
            android:authorities="call_log"
            android:syncable="false" android:multiprocess="false"
            android:exported="true"
            android:readPermission="android.permission.READ_CALL_LOG"
            android:writePermission="android.permission.WRITE_CALL_LOG">
        </provider>*/
        // sURIMatcher.addURI(CallLog.AUTHORITY, "calls", CALLS);
        
        // 1、得到内容解析者
        ContentResolver resolver = getContentResolver();
        Uri uri = Uri.parse("content://call_log/calls");
        resolver.delete(uri, "number=?"new String[] { incomingNumber });
    }
    /**
     * 3、挂断电话
     */
    private void endCall() {
        // IBinder b = ServiceManager.getService(LOCATION_SERVICE);
        //利用反射来找到,因为系统给隐藏了
        try {
            Class<?> clazz = getClassLoader().loadClass("android.os.ServiceManager");
            Method method = clazz.getDeclaredMethod("getService", String.class);
            IBinder b = (IBinder) method.invoke(nullTELEPHONY_SERVICE);
            // IBinder 转成接口类型
            ITelephony asInterface = ITelephony.Stub.asInterface(b);
            asInterface.endCall();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
权限:
 <uses-permission android:name="android.permission.READ_CALL_LOG"/>  
 <uses-permission android:name="android.permission.WRITE_CALL_LOG"/>  
问题1:有的时候,通话记录不会被删除掉
分析:这是由于挂断电话,并不会马上生成通话记录,所以有时删除不了
解决:给通话记录产生注册一个内容观察者,观察通话记录的生成,一生成就删除该记录
endCall();// 挂断电话  
getContentResolver().registerContentObserver(uri, true,new CallLogObserver(new Handler(),incomingNumber));// 参数二:true表示匹配前缀  
/**
 * 5、通话记录生成的内容观察者
 * @author hacket
 */
private class CallLogObserver extends ContentObserver {
    private static final String TAG = "MyObserver";
    private String incomingNumber;
    public CallLogObserver(Handler handler, String incomingNumber) {
        super(handler);
        this.incomingNumber = incomingNumber;
    }
    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        Log.i(TAG"观察到数据库内容变化.删除呼叫记录");
        clearCallLog(incomingNumber);// 当观察到内容变化,执行删除通话记录的操作
        getContentResolver().unregisterContentObserver(this);// 删除通话记录后,将该内容观察者给注销掉,反注册自己(因为this就是这个内容观察者)
    }
}
虚拟电话应用