系列文章目录
总篇:数据抓取:抓取手机设备各种数据
分篇(一):【数据抓取(一)】手机通讯录数据获取
分篇(二):数据抓取(二)&定位方案:地址信息的获取
分篇(二):数据抓取(三):免权限获取所有安装的应用程序信息(系统和非系统)
效果展示:
前言
很多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大家都心里有数。
主要属性有:
- contact_display_name:联系人名称
- last_time_contacted:上次通讯时间
- number:联系人电话号码
- times_contacted:通话次数
- up_time:编辑时间
- 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;
}
}
三、数据获取
我们采取内容提供器这个安卓存在感不高的组件来实现这个功能,在我完成这个功能前,我对这个组件其实是不太熟悉的,但是在完成一个完整的数据抓取逻辑之后,个人觉得内容提供器其实跟数据库差不多,而且很方便。
- 根据通讯录数据库的URL获取结果集
- 再根据字段获取相关信息
- 比较特殊点:获取手机号码,需要根据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,给我一点信心去完善这个开源库
总结
顺利抓取成功,不过因为现代大家都已经是微信党,不要手机号码了,所以在展示图片里,数据很好,无法展示出这个代码是否有问题,我希望大家可以尝试一下,有问题及时反馈给我。
这一次的数据抓取便先到这里了,之后我会将其他常用的数据抓取写成后续博客,如果大家感兴趣的话,可以多多关注。最后我会尝试封装成库供大家方便调用。