【数据抓取(一)】手机通讯录数据获取

系列文章目录

总篇:数据抓取:抓取手机设备各种数据
分篇(一):【数据抓取(一)】手机通讯录数据获取
分篇(二):数据抓取(二)&定位方案:地址信息的获取
分篇(二):数据抓取(三):免权限获取所有安装的应用程序信息(系统和非系统)


效果展示:
在这里插入图片描述

前言

很多app在使用的时候,因为要详细分析用户崩溃产生的原因,所以避免不了需要获取用户设备的详细信息,emmm,在信息时代里,数据就是这么的不值钱。我之前完成过这样的一个需求,接下来我会分多篇博客进行讲述内容,最后封装成一个开源库供大家使用。

通讯录记得动态获取权限: <uses-permission android:name="android.permission.READ_CONTACTS" />

一、通讯录数据库字段

在获取通讯录的数据之前,我们需要了解一些常用字段和常量,以及表名

名称作用
ContactsContract.Contacts.CONTENT_URI表示通讯录数据库的内容 URI
ContactsContract.Contacts存储手机通讯录联系人信息的表
ContactsContract.PhoneLookup表示查找电话号码(例如查找来电显示)结果的表
ContactsContract.CommonDataKinds.Phone.CONTENT_URI代表联系人手机号码的 URI,根据id查询手机号
ContactsContract.PhoneLookup.DISPLAY_NAME字段,联系人的显示名称
ContactsContract.Contacts._ID字段,id,用于查询手机号
ContactsContract.CommonDataKinds.Phone.NUMBER字段,联系人电话号码
ContactsContract.PhoneLookup.LAST_TIME_CONTACTED字段,上次通话时间,记住,此字段不适用于谷歌市场应用和安卓10以上版本
ContactsContract.PhoneLookup.TIMES_CONTACTED字段,通话次数
ContactsContract.PhoneLookup.TYPE字段,家庭电话还是工作电话,或者移动电话,其他等等类型
ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP字段,该联系人最后的编辑时间,需要在 Android 12 及更高版本中才可用

二、数据bean类

通过学习上面我列出的常用值之后,相比通讯录的bean大家都心里有数。
主要属性有:

  1. contact_display_name:联系人名称
  2. last_time_contacted:上次通讯时间
  3. number:联系人电话号码
  4. times_contacted:通话次数
  5. up_time:编辑时间
  6. type:通话电话类型
public  class AddressBookBean implements Serializable {
    private String contact_display_name; // 联系人名称
    private String last_time_contacted; // 上次通讯时间(毫秒)
    private String number; // 联系人手机号
    private int times_contacted; // 联系次数
    private String up_time; // 编辑时间(毫秒)
    private String type; // 通话类型

    public AddressBookBean(String contact_display_name, String last_time_contacted, String number, int times_contacted, String up_time,String type) {
        this.contact_display_name = contact_display_name;
        this.last_time_contacted = last_time_contacted;
        this.number = number;
        this.times_contacted = times_contacted;
        this.up_time = up_time;
        this.type = type;
    }
}

三、数据获取

我们采取内容提供器这个安卓存在感不高的组件来实现这个功能,在我完成这个功能前,我对这个组件其实是不太熟悉的,但是在完成一个完整的数据抓取逻辑之后,个人觉得内容提供器其实跟数据库差不多,而且很方便。

  1. 根据通讯录数据库的URL获取结果集
  2. 再根据字段获取相关信息
  3. 比较特殊点:获取手机号码,需要根据Contacts 表的id重新用ContactsContract.CommonDataKinds.Phone.CONTENT_URL获取结果集。
public class AddressBookUtil {
    @SuppressLint("Range")
    public static List<AddressBookBean> getAddressBookBean(Context context) {
        List<AddressBookBean> addressBook = new ArrayList<>();
        ContentResolver cr = context.getContentResolver();
        Cursor crs = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
        while (crs.moveToNext()) {
            // 获得联系人姓名
            int nameColumnIndex = crs.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME);
            String name = crs.getString(nameColumnIndex);
            // 获取联系人手机号码
            int numberColumnIndex = crs.getColumnIndex(ContactsContract.Contacts._ID);
            // 获得当前联系人的ID索引用于查询号码
            String contact_Id = crs.getString(numberColumnIndex);
            // 注意第一个参数和上一个游标crs的参数是不同的。上一个是ContactsContract.Contacts.CONTENT_URI,并且第三个参数是为了得到和前面匹配的电话号码
            Cursor crs_Num = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = "
                    + contact_Id, null, null);
            String number = "";
            while (crs_Num.moveToNext()) {
                int index = crs_Num.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
                number = crs_Num.getString(index);
                if (!number.isEmpty()) break;
            }
            // 编辑时间
            int updateTimeColumnIndex = crs.getColumnIndex(ContactsContract.Contacts.CONTACT_LAST_UPDATED_TIMESTAMP);
            long updateTime = crs.getLong(updateTimeColumnIndex);
            // 上次通讯时间(毫秒)
            int lastTimeColumnIndex = crs.getColumnIndex(ContactsContract.PhoneLookup.LAST_TIME_CONTACTED);
            long lastTime = crs.getLong(lastTimeColumnIndex);
            // 获得联系次数
            int timeColumnIndex = crs.getColumnIndex(ContactsContract.PhoneLookup.TIMES_CONTACTED);
            String type = "";
            switch (crs.getColumnIndex(ContactsContract.PhoneLookup.TYPE)){
                case 1:
                    type = "家庭电话";
                    break;
                case 2:
                    type = "移动电话";
                    break;
                case 3:
                    type = "工作电话";
                    break;
                default:
                    type = "其他";
                    break;
            }
            int times = crs.getInt(timeColumnIndex);
            addressBook.add(new AddressBookBean(name, String.valueOf(lastTime), number, times, String.valueOf(updateTime),type));
        }
        crs.close();
        return addressBook;
    }
}

最后附上相关源码以及我手搓的开源库:
数据抓取:https://github.com/Android5730/DataCapture
如果有帮助到各位,可以给个star,给我一点信心去完善这个开源库

总结

顺利抓取成功,不过因为现代大家都已经是微信党,不要手机号码了,所以在展示图片里,数据很好,无法展示出这个代码是否有问题,我希望大家可以尝试一下,有问题及时反馈给我。
这一次的数据抓取便先到这里了,之后我会将其他常用的数据抓取写成后续博客,如果大家感兴趣的话,可以多多关注。最后我会尝试封装成库供大家方便调用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薪火_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值