android 通话记录的导入/导出

时间:2025-04-09 13:07:02

涉及到对通话记录的读和写、需要在sd卡上写存放通话记录数据的文件,所以需要加权限:

    <uses-permission android:name=".READ_CALL_LOG"/>
    <uses-permission android:name=".WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name=".WRITE_CALL_LOG"/>

首先,通话记录的获取,只需要获取部分字段即可满足即可:

将数据保存到一个自定义的Model对象中。

Cursor cursor = ().query(.CONTENT_URI, null, "date > ?", new String[] { "" + timestamp }, .DEFAULT_SORT_ORDER);
                while (()) {
                    CalllogModel calllogModel = new CalllogModel();
                    // name
                    (((.CACHED_NAME)));
                    // start call datetime
                    ((()));
                    // phonenumber
                    ((()));
                    // duration
                    ((()));
                    // call type
                    ((()));
                    // is read
                    calllogModel.setIs_read(((.IS_READ)));
                    modifyVector(0, calllogModel, ADD_VECTOR); //调用保存到文件的方法
                }
                ();
                cursor = null;

将通话记录导入到系统的数据库中:

                ContentResolver contentResolver = ();
                (.CACHED_NAME, ());
                (, ());
                (, ());
                (, ());
                (.IS_READ, calllogModel.getIs_read());
                (, ());
                (.CONTENT_URI, values);

还有两点考虑:

1. 通话记录的保存方式:

选择通过文本文件来保存,一行算足一条通话记录。

每个通话记录以字符串的形式保存到文本文件

java中提供BufferReader和BufferWriter两个类可以支持一行一行的读和写

在导入通话记录的时候,读到一行记录,就处理一行:string->json->model->contentvalues->

2. 处理效率和OOM异常避免的情况

在处理导出通话记录的时候,通话记录的条数可能成千上万条。

在这样的情况下,需要注意:
a. 那么多记录数不能全部写到内存中,暂据的内存太大,容易报OOM的错误

b. 将那些数据写入到文件中的时候,不能每一次都打开IO流和关闭IO流,耗时耗资源

解决的方法是,维护一个集合Vector<model>,当从系统数据库中读取到一条记录的时候,将其vector,add(model);当每处理完一个model之后,通过(0)获取新的Model对象进行处理。

读取记录的过程和处理记录的过程,用两个线程同步执行。

保证多线程下数据的安全考虑,对该集合变量的操作,用同步锁对其进行限定

    /**
     * 需要增加一个对象到集合的时候,type=1;需要获取一个对象的时候,type=2
     * @param index
     * @param calllogModel
     * @param type
     * @return
     */
    private static synchronized CalllogModel modifyVector(int index, CalllogModel calllogModel, int type) {
        switch (type) {
        case 1:
            if (()>1000) { //确保集合的体积不会过大
                try {
                    (1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    ();
                }
            } 
            (calllogModel);
            break;
        case 2:
            if (!()) {
                return (0);
            } else {
                return null;
            }
        default:
            break;
        }
        return null;
    }