美文网首页Android相关
Android通讯录,通话记录,短信

Android通讯录,通话记录,短信

作者: 你怕是很皮哦 | 来源:发表于2017-08-13 20:28 被阅读567次

    最近数据部需要上传用户的通讯录,通话记录,短信等内容做分析,于是整理下这方面的知识。说句实话,其实获取的方式都是一个样子的,都是通过ContentProvider,知其一就可以举一反三了。
    首先定义了一个接口,包含查询数据,解析数据和关闭cursor,如下

    public interface IResolverHelper {
    
        /**
         * 查询手机相关db,获取cursor
         *
         * @param context
         * @return
         */
        Cursor query(Context context);
    
        /**
         * 从cursor中读取数据
         */
        void readData();
    
        /**
         * 关闭cursor
         */
        void close();
    }
    

    然后写了个实现类,如下所示

    public abstract class ResolverHelperImpl<T> implements IResolverHelper {
    
        protected Handler mHandler;
    
        protected Uri contentUri/*读取哪个表的数据*/
        protected String[] mColumns;/*读取哪些列*/
        protected String mCondition;/*限制条件*/
        protected String[] mArgs;/*参数*/
        protected String mSort;/*排序方式*/
    
        protected T mData;
        protected Cursor mCursor;
    
        public ResolverHelperImpl(Context context, Handler handler) {
            mHandler = handler;
            initParams();
            mCursor = query(context);
        }
    
        protected abstract void initParams();
    
        @Override
        public Cursor query(Context context) {
            ContentResolver resolver = context.getContentResolver();
            Cursor cursor = null;
            try {
                cursor = resolver.query(contentUri, mColumns, mCondition, mArgs, mSort);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return cursor;
        }
    
        @Override
        public void readData() {
            new Thread() {
                @Override
                public void run() {
                    try {
                        parseData();
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        if (mHandler != null) {
                            Message msg = mHandler.obtainMessage();
                            msg.what = getMsgWhat();
                            msg.obj = mData;
                            mHandler.sendMessage(msg);
                        }
                        close();
                    }
                }
            }.start();
        }
    
        protected abstract void parseData();
    
        protected abstract int getMsgWhat();
    
        @Override
        public void close() {
            if (mCursor != null) {
                try {
                    mCursor.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    initParams()主要是做一些初始化操作,getMsgWhat()是异步消息传递的what字段的值,主要是parseData()方法,继承这个类重写这个方法,在里面进行数据解析就可以了。

    通讯录

    通讯录这里分为两部分说,一部分是手机通讯录获取,另外一部分是sim卡通讯录获取。

    手机通讯录

    public final class ContactHelper extends ResolverHelperImpl<List<ContactItem>> {
        public ContactHelper(Context context, Handler handler) {
            super(context, handler);
            mData = new ArrayList<>();
        }
    
        @Override
        protected void initParams() {
            contentUri = ContactsContract.Data.CONTENT_URI;
    
            mColumns = new String[]{
                    ContactsContract.Data.RAW_CONTACT_ID,/*联系人id*/
                    ContactsContract.Data.MIMETYPE,/*data1字段类型*/
                    ContactsContract.Data.DATA1,/*数据*/
                    ContactsContract.Data.CONTACT_LAST_UPDATED_TIMESTAMP/*时间*/
            };
    
            mCondition = ContactsContract.Data.MIMETYPE + " in (?,?)";
    
            mArgs = new String[]{
                    ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
                    ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
            };
    
            mSort = ContactsContract.Data.RAW_CONTACT_ID;
        }
    
        @Override
        protected void parseData() {
            int cid = -1;/*当前联系人id*/
            int size = 0;
            ContactItem contact = null;
            ArrayList<String> phones = null;
            while (mCursor != null && mCursor.moveToNext()) {
                /*数据库当前操作的联系人id*/
                int _id = mCursor.getInt(mCursor.getColumnIndex(ContactsContract.Data.RAW_CONTACT_ID));
                String mimetype = mCursor.getString(mCursor.getColumnIndex(ContactsContract.Data.MIMETYPE));
                String data1 = mCursor.getString(mCursor.getColumnIndex(ContactsContract.Data.DATA1));
                if (_id != cid) {
                    cid = _id;
                    if (contact != null) {
                        /*添加到集合中*/
                        if (phones != null && phones.size() > 0) {
                            mData.add(contact);
                        }
                    }
                    /*新的联系人开始了*/
                    contact = new ContactItem();
                    phones = new ArrayList<>();
                    contact.setContactPhones(phones);
                    size = 0;
    
                    /*设置联系人最后修改时间,避免后面重复设置*/
                    try {
                        String time = mCursor.getString(mCursor.getColumnIndex(ContactsContract.Data.CONTACT_LAST_UPDATED_TIMESTAMP));
                        time = DateUtils.getFormatTimeFromMillis(Long.parseLong(time));
                        contact.setCreateDate(time);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                switch (mimetype) {
                    case ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE:
                        contact.setContactName(data1);
                        break;
                    case ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE:
                        size++;
                        if (size > 5) {
                            continue;
                        } else {
                            if (!TextUtils.isEmpty(data1)) {
                                phones.add(data1.replaceAll("^(\\+86)", "").replaceAll("-", ""));
                            }
                        }
                        break;
                }
            }
            /*添加最后一条数据*/
            if (contact != null) {
                /*添加到集合中*/
                if (phones != null && phones.size() > 0) {
                    mData.add(contact);
                }
            }
        }
    
        @Override
        protected int getMsgWhat() {
            return 100000;
        }
    }
    

    sim卡通讯录

    公司的测试机有限,测试的部分测试机在联系人全部存放在sim卡里面时,通过上面的方式也是可以获取的,但是部分测试机获取不到,需要通过下面的方式进行获取,具体Uri在哪里找到的,你们可以看看ICCProvider这个类就知道了,和我们写ContentProvider是一个样的。具体的contentUri是content://icc/adn。代码如下:

    public final class SimHelper extends ResolverHelperImpl<List<ContactItem>> {
    
        public SimHelper(Context context, Handler handler) {
            super(context, handler);
            mData = new ArrayList<>();
        }
    
        @Override
        protected void initParams() {
            contentUri = Uri.parse("content://icc/adn");/*可以参考IccProvider*/
    
            mColumns = new String[]{
                    "name",/*姓名*/
                    "number"/*号码*/
            };
        }
    
        @Override
        protected void parseData() {
            while (mCursor != null && mCursor.moveToNext()) {
                String name = mCursor.getString(mCursor.getColumnIndex("name"));
                String phone = mCursor.getString(mCursor.getColumnIndex("number"));
                if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(phone)) {
                    try {
                        ContactItem d = new ContactItem();
                        ArrayList<String> phones = new ArrayList();
                        phones.add(phone.replaceAll("^(\\+86)", "").replaceAll("-", ""));
                        d.setContactName(name);
                        d.setContactPhones(phones);
                        mData.add(d);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        @Override
        protected int getMsgWhat() {
            return 100003;
        }
    }
    

    短信内容

    短信存放的地方和通讯录不一样

    image.png

    在这个表下面。具体代码如下

    public final class SmsHelper extends ResolverHelperImpl<List<SmsItem>> {
    
        public SmsHelper(Context context, Handler handler) {
            super(context, handler);
            mData = new ArrayList<>();
        }
    
        @Override
        protected void initParams() {
            contentUri = Uri.parse("content://sms");
    
            /*筛选列*/
            mColumns = new String[]{
                    Telephony.Sms.ADDRESS,/*短信发送者号码*/
                    Telephony.Sms.DATE,/*发送日期,时间戳,需要转换*/
                    Telephony.Sms.BODY/*短信内容*/
            };
    
            /*筛选条件*/
            mCondition = Telephony.Sms.DATE + ">= ? and " + Telephony.Sms.DATE + " <= ?";
    
            /*短信筛选两个月的*/
            long max = Calendar.getInstance().getTimeInMillis();
            long min = max - 60 * 24 * 3600 * 1000;
    
            mArgs = new String[]{String.valueOf(min), String.valueOf(max)};
        }
    
        @Override
        protected void parseData() {
            while (mCursor != null && mCursor.moveToNext()) {
                try {
                    SmsItem sms = new SmsItem();
                    String addr = mCursor.getString(mCursor.getColumnIndex(Telephony.Sms.ADDRESS));
                    String body = mCursor.getString(mCursor.getColumnIndex(Telephony.Sms.BODY));
                    String date = mCursor.getString(mCursor.getColumnIndex(Telephony.Sms.DATE));
                    sms.setAddress(addr);
                    sms.setBody(body);
                    sms.setDate(DateUtils.getFormatTimeFromMillis(Long.parseLong(date)));
                    mData.add(sms);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        @Override
        protected int getMsgWhat() {
            return 100001;
        }
    }
    

    通话记录

    通话记录和通讯录都是在contacts.db中,只是对应不同的表而已


    image.png

    没错就是这张表,里面存放的是通话记录数据,代码如下。

    public final class CallLogHelper extends ResolverHelperImpl<List<CallLogItem>> {
    
        public CallLogHelper(Context context, Handler handler) {
            super(context, handler);
            mData = new ArrayList<>();
        }
    
        @Override
        protected void initParams() {
            contentUri = CallLog.Calls.CONTENT_URI;
    
            mColumns = new String[]{
                    CallLog.Calls.NUMBER,/*手机号*/
                    CallLog.Calls.CACHED_NORMALIZED_NUMBER,/*格式化手机号*/
                    CallLog.Calls.CACHED_NAME,/*匹配通讯录的名称*/
                    CallLog.Calls.DATE,/*通话日期*/
                    CallLog.Calls.DURATION,/*通话时长,秒数*/
                    CallLog.Calls.TYPE,/*1来电,2拨出,3未接*/
                    CallLog.Calls.VOICEMAIL_URI,/*语音地址*/
                    CallLog.Calls.GEOCODED_LOCATION,/*号码归属地*/
                    CallLog.Calls.COUNTRY_ISO,/*国家简称CN,US等*/
                    CallLog.Calls.PHONE_ACCOUNT_ID/*SIM卡标记,用来区分是否是双卡手机*/
            };
        }
    
        @Override
        protected void parseData() {
            while (mCursor != null && mCursor.moveToNext()) {
                try {
                    CallLogItem log = new CallLogItem();
                    String number = mCursor.getString(mCursor.getColumnIndex(CallLog.Calls.NUMBER));
                    String formatNumber = mCursor.getString(mCursor.getColumnIndex(CallLog.Calls.CACHED_NORMALIZED_NUMBER));
                    String name = mCursor.getString(mCursor.getColumnIndex(CallLog.Calls.CACHED_NAME));
                    String date = mCursor.getString(mCursor.getColumnIndex(CallLog.Calls.DATE));
                    String duration = mCursor.getString(mCursor.getColumnIndex(CallLog.Calls.DURATION));
                    String type = mCursor.getString(mCursor.getColumnIndex(CallLog.Calls.TYPE));
                    String voicemailUri = mCursor.getString(mCursor.getColumnIndex(CallLog.Calls.VOICEMAIL_URI));
                    String geo = mCursor.getString(mCursor.getColumnIndex(CallLog.Calls.GEOCODED_LOCATION));
                    String iso = mCursor.getString(mCursor.getColumnIndex(CallLog.Calls.COUNTRY_ISO));
                    String imsi = mCursor.getString(mCursor.getColumnIndex(CallLog.Calls.PHONE_ACCOUNT_ID));
                    log.setNumber(number);
                    log.setFormatNumber(formatNumber);
                    log.setName(name);
                    log.setDate(DateUtils.getFormatTimeFromMillis(Long.parseLong(date)));
                    log.setDuration(duration);
                    log.setType(type);
                    log.setVoicemailUri(voicemailUri);
                    log.setGeocodedLocation(geo);
                    log.setCountryIso(iso);
                    log.setPhoneAccountId(imsi);
                    mData.add(log);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        @Override
        protected int getMsgWhat() {
            return 100002;
        }
    }
    

    over

    嗯,大致上就是这些,其实都很简单。大家写的时候别忘了相应的权限。---我在成长!

    相关文章

      网友评论

        本文标题:Android通讯录,通话记录,短信

        本文链接:https://www.haomeiwen.com/subject/pdierxtx.html