这是实现后的效果图,懒得去找图片,能看就行了
实现思路
1,通过内容提供者扫描手机的通话记录,并按照手机号进行排序,升序或降序都可以,再按照通话日期排序
Cursor cursor = cr.query(CallLog.Calls.CONTENT_URI,
null, null, null, CallLog.Calls.NUMBER + "," + CallLog.Calls.DATE + " DESC");
这里说明一下,按照手机号排序的原因是,为了方便整合同一个手机号的通话记录,日期排序是为了方便记录最后通话日期
这是我的bean
public class CallLogBean {
/**
* 通话类型 0为,未接,1为 拨出,2,为 拨入
*/
private int type;
/**
* 备注名称
*/
private String remarkName;
/**
* 通话日期
*/
private String dates;
/**
* 通话时间
*/
private String duration;
public void setDuration(String duration) {
this.duration = duration;
}
public String getDuration() {
return duration;
}
/**
* 通话类型 0为,未接,1为 拨出,2,为 拨入
*/
public int getType() {
return type;
}
/**
* 通话类型 0为,未接,1为 拨出,2,为 拨入
*/
public void setType(int type) {
this.type = type;
}
public String getRemarkName() {
return remarkName;
}
public void setRemarkName(String remarkName) {
this.remarkName = remarkName;
}
public String getDates() {
return dates;
}
public void setDates(String dates) {
this.dates = dates;
}
@Override
public String toString() {
return "CallLogBean{" +
"type=" + type +
", remarkName='" + remarkName + '\'' +
", dates=" + dates +
'}';
}
}
扫描之后就开始拿数据了,我这里存数据的类是用TreeMap<String,ArrayList<CallLogBean>>
然后再定义一个变量记录每次拿到的号码,用来判断这次的号码是否和上次拿到的号码一样,如果一样就用put
具体实现
if(number.equals(lastPhone)){
ArrayList<CallLogBean> callLogBeens = callLogs.get(number);
callLogBeens.add(callLogBean);
}else{
ArrayList<CallLogBean> callLogBeens = new ArrayList<>();
callLogBeens.add(callLogBean);
callLogs.put(number,callLogBeens);
}
lastPhone = number;
接下来就是把拿到的数据存起来,剩下的没什么代码了,所以直接贴全部代码
private TreeMap<String, ArrayList<CallLogBean>> getCallLogs() {
TreeMap<String, ArrayList<CallLogBean>> callLogs = new TreeMap<>();
String lastPhone = "";
//用于记录每个号码的最后通话日期
ContentResolver cr = getActivity().getContentResolver();
try (
Cursor cursor = cr.query(CallLog.Calls.CONTENT_URI, // 查询通话记录的URI
null, null, null, CallLog.Calls.NUMBER + "," + CallLog.Calls.DATE + " DESC");
) {
if (cursor == null) {
return callLogs;
}
while (cursor.moveToNext()) {
CallLogBean callLogBean = new CallLogBean();
//备注名称
callLogBean.setRemarkName(cursor.getString(cursor.getColumnIndex(CallLog.Calls.CACHED_NAME)));
//通话类型
int type = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.TYPE));
switch (type) {
case CallLog.Calls.INCOMING_TYPE:
callLogBean.setType(2);
break;
case CallLog.Calls.OUTGOING_TYPE:
callLogBean.setType(1);
break;
case CallLog.Calls.MISSED_TYPE:
callLogBean.setType(0);
break;
}
//通话日期
String date = cursor.getString(cursor.getColumnIndexOrThrow(CallLog.Calls.DATE));
callLogBean.setDates(date);
//通话时间
callLogBean.setDuration(cursor.getString(cursor.getColumnIndexOrThrow(CallLog.Calls.DURATION)));
//通话号码
String number = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
LogUtils.v("PhoneFragmentmsg",number + " " + callLogBean);
//如果号码存在就继续存通话记录
if(number.equals(lastPhone)){
ArrayList<CallLogBean> callLogBeens = callLogs.get(number);
callLogBeens.add(callLogBean);
}else{
ArrayList<CallLogBean> callLogBeens = new ArrayList<>();
callLogBeens.add(callLogBean);
callLogs.put(number,callLogBeens);
}
lastPhone = number;
}
}
return callLogs;
}
那个备注名是为了方便,所以存了很多次
通过这些代码就拿到全部的通话记录,并将同一个号码的通话记录都整合起来
剩下的就是如何把最后的通话类型,通话时间,电话号码等信息显示到listView上
这里再创建一个bean,用来存储要显示的数据
public class CallLogNeedAllBean implements Comparable<CallLogNeedAllBean>,Serializable{
/**
* 电话号码
*/
private String number;
/**
* 备注名称
*/
private String remarkName;
/**
* 通话次数
*/
private int count;
/**
* 通话类型 0,未接 1.拨出 2,拨入
*/
private int type;
/**
* 归属地
*/
private String location;
/**
* 最后通话日期
*/
private String lastDate;
/**
* 最后通话日期的Long值
*/
private Long lastDateLong;
private final long noLoseAccuracy = 14000000000L;
public void setLastDateLong(Long lastDateLong) {
this.lastDateLong = lastDateLong;
}
public Long getLastDateLong() {
return lastDateLong;
}
public void setLastDate(String lastDate) {
this.lastDate = lastDate;
}
public String getLastDate() {
return lastDate;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getRemarkName() {
return remarkName;
}
public void setRemarkName(String remarkName) {
this.remarkName = remarkName;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
@Override
public String toString() {
return "CallLogNeedAllBean{" +
"number='" + number + '\'' +
", remarkName='" + remarkName + '\'' +
", count=" + count +
", type=" + type +
", location='" + location + '\'' +
'}';
}
@Override
public int compareTo(CallLogNeedAllBean callLogNeedAllBean) {
return callLogNeedAllBean.lastDateLong.compareTo(lastDateLong);
}
}
由于通话记录是按照日期降序排序的,所以这里用最后通话进行降序排序
最后再把拿到的数据封装成Tree<CallLogNeedAll,Tree<Long,CallLogDurationType>>
第1层的key为要显示的数据,value的key为通话日期,value为每次的通话时间和类型
我刚开始这样封装的目的是为了让通话日期逆序排序,但等我做完后才发现,其实也可以这样封装
TreeMap<CallLogNeedAll,XxxBean> XxxBean为,通话日期,通话时间,通话类型,因为这些数据在拿到的时候就已经排好序了,这样做有点多此一举
这是封装的代码
private void initListItem(TreeMap<String, ArrayList<CallLogBean>> simpleCallLogs, ArrayList<CallLogNeedAllBean> showItem) {
Set<Map.Entry<String, ArrayList<CallLogBean>>> entry = simpleCallLogs.entrySet();
for (Map.Entry<String, ArrayList<CallLogBean>> date : entry) {
//电话号码
String number = date.getKey();
//备注名称
String remarkName = date.getValue().get(0).getRemarkName();
//最后通话日期
Long lastDate = Long.valueOf(date.getValue().get(0).getDates());
LogUtils.v("PhoneFragmentBkmsg","LastDate " + lastDate);
//最后通话类型
int lastType = date.getValue().get(0).getType();//因为已经排好序了,所以直接拿第一个就可以拿到最后通话类型
//通话次数
int count = date.getValue().size();
CallLogNeedAllBean callLogNeedAllBean = new CallLogNeedAllBean();
callLogNeedAllBean.setNumber(number);
callLogNeedAllBean.setType(lastType);
callLogNeedAllBean.setRemarkName(remarkName);
callLogNeedAllBean.setCount(count);
callLogNeedAllBean.setLastDateLong(lastDate);
//最后通话日期,把他变成date对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date1 = new Date(lastDate);
String strDate = sdf.format(date1);
callLogNeedAllBean.setLastDate(strDate);
callLogNeedAllBean.setLocation(LocationDao.getLocation(getActivity(),number));
//到这里Map的key就完成了
//这是要存储的value,按照通话日期进行排序
TreeMap<Long,CallLogDurationTypeBean> sortForDate = new TreeMap<>(new Comparator<Long>() {
@Override
public int compare(Long aLong, Long t1) {
return (int)(t1 - aLong);
}
});//这个应该看得懂吧
for(CallLogBean callLogBean : date.getValue()){
CallLogDurationTypeBean callLogDurationTypeBean = new CallLogDurationTypeBean();
callLogDurationTypeBean.setType(callLogBean.getType());
callLogDurationTypeBean.setDuration(callLogBean.getDuration());
sortForDate.put(Long.valueOf(callLogBean.getDates()),callLogDurationTypeBean);
}
mAllCallLogMap.put(callLogNeedAllBean,sortForDate);
}//单独写一个ArrayList,这样要做ListView显示就方便多了
Set<Map.Entry<CallLogNeedAllBean,TreeMap<Long,CallLogDurationTypeBean>>> set = mAllCallLogMap.entrySet();
for(Map.Entry<CallLogNeedAllBean,TreeMap<Long,CallLogDurationTypeBean>> s : set){
showItem.add(s.getKey());
}
}
因为我的代码才写到这里,所以没有单个人的通话记录的代码,不过所有需要的数据都拿到了,所以剩下的应该都不是什么问题吧
大概的实现代码就这样,剩下的都比较简单,就不把代码贴出来了.