1、权限声明,需要在Manifest.xml文件中声明权限(读取通话记录权限):
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
2、代码实现,下面在Activity里面实现功能,实现代码如下:
@TargetApi(21)
private void queryCallLog() {
// 权限检查
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CALL_LOG)
!= PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode,
// String[] permissions,int[] grantResults)
// to handle the case where the user grants the permission.
// See the documentation
// for ActivityCompat#requestPermissions for more details.
Log.w(TAG, "permission is request");
/**
* 动态申请权限
* 这里没有在
* onRequestPermissionsResult(int requestCode,
* String[] permissions,int[] grantResults)方法里面处理
*
*/
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_CALL_LOG}, 100);
return;
}
ContentResolver resolver = getContentResolver();
Log.i(TAG, "query call log " + resolver);
//获取cursor对象
Cursor cursor = resolver.query(CallLog.Calls.CONTENT_URI, new String[]{
CallLog.Calls.CACHED_FORMATTED_NUMBER,
CallLog.Calls.CACHED_MATCHED_NUMBER,
CallLog.Calls.CACHED_NAME,
CallLog.Calls.TYPE,
CallLog.Calls.DATE,
CallLog.Calls.DURATION,
CallLog.Calls.GEOCODED_LOCATION,
}, null, null, "date DESC limit 2");
/**
* "date DESC limit 2"
* 按时间排序查询2条记录
*/
if (cursor != null) {
Log.i(TAG, "cursor length is " + cursor.getCount());
try {
while (cursor.moveToNext()) {
CallRecord record = new CallRecord();
record.formatted_number = cursor.getString(0);
record.matched_number = cursor.getString(1);
record.name = cursor.getString(2);
record.type = getCallType(cursor.getInt(3));
record.date = cursor.getLong(4);
record.duration = cursor.getLong(5);
record.location = cursor.getString(6);
Log.i(TAG, record.toString());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
cursor.close(); //关闭cursor,避免内存泄露
}
}
}
@TargetApi(21) 权限说明,由于开发版本使用minSdkVersion = 14,如果去掉@TargetApi(21) AndroidStudio 出现下面的警告提示:
Manifest.permission.READ_CALL_LOG
Field requires API level 16 (current min is 14): android.Manifest.permission#READ_CALL_LOG
Manifest.permission.READ_CALL_LOG权限版本要求 minSdkVersion = 16
CallLog.Calls.CACHED_FORMATTED_NUMBER
Field requires API level 21 (current min is 14): android.provider.CallLog.Calls
#CACHED_FORMATTED_NUMBER
CallLog.Calls.CACHED_MATCHED_NUMBER
Field requires API level 21 (current min is 14): android.provider.CallLog.Calls
#CACHED_MATCHED_NUMBER
CallLog.Calls.GEOCODED_LOCATION
Field requires API level 21 (current min is 14): android.provider.CallLog.Calls
#GEOCODED_LOCATION
上面三个权限版本要求 minSdkVersion = 21
属性说明:
CallLog.Calls.CACHED_FORMATTED_NUMBER 通话记录格式化号码
CallLog.Calls.CACHED_MATCHED_NUMBER 通话记录为格式化号码
CallLog.Calls.CACHED_NAME 联系人名称
CallLog.Calls.TYPE 通话类型
CallLog.Calls.DATE 通话时间(long型)
CallLog.Calls.DURATION 通话时长(秒为单位)
CallLog.Calls.GEOCODED_LOCATION 运营商地址(如:浙江杭州)
通话类型
CallLog.Calls.INCOMING_TYPE 呼入
CallLog.Calls.OUTGOING_TYPE 呼出
CallLog.Calls.MISSED_TYPE 未接
通话类型转话代码:
private String getCallType(int anInt) {
switch (anInt) {
case CallLog.Calls.INCOMING_TYPE:
return "呼入";
case CallLog.Calls.OUTGOING_TYPE:
return "呼出";
case CallLog.Calls.MISSED_TYPE:
return "未接";
default:
break;
}
return null;
}
时间格式化代码:
public String formatDate(long time) {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.getDefault());
return format.format(new Date(time));
}
通话时长格式化代码:
public String formatDuration(long time) {
long s = time % 60;
long m = time / 60;
long h = time / 60 / 60;
StringBuilder sb = new StringBuilder();
if (h > 0) {
sb.append(h).append("小时");
}
if (m > 0) {
sb.append(m).append("分");
}
sb.append(s).append("秒");
return sb.toString();
}
最后给出CallRecord代码:
class CallRecord {
long date;
String formatted_number;
String matched_number;
String name;
String type;
String location;
long duration;
@Override
public String toString() {
return "CallRecord{" +
"date=" + formatDate(date) +
", formatted_number='" + formatted_number + '\'' +
", matched_number='" + matched_number + '\'' +
", name='" + name + '\'' +
", type=" + type +
", location='" + location + '\'' +
", duration=" + formatDuration(duration) +
'}';
}
}
1、权限声明,需要在Manifest.xml文件中声明权限(读取通话记录权限):
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
2、代码实现,下面在Activity中实现代码:
@TargetApi(21)
private void queryMessageLog() {
//动态申请权限
if (ActivityCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_CONTACTS}, 101);
return;
}
//动态申请权限
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_SMS)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_SMS}, 101);
return;
}
ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(Telephony.Sms.CONTENT_URI, new String[]{
Telephony.Sms.ADDRESS, //
Telephony.Sms.BODY,
Telephony.Sms.DATE,
Telephony.Sms.READ,
Telephony.Sms.STATUS,
Telephony.Sms.TYPE,
}, null, null, "date DESC limit 2");
if (cursor != null) {
while (cursor.moveToNext()) {
SMSMessage message = new SMSMessage();
message.address = cursor.getString(0);
message.body = cursor.getString(1);
message.date = cursor.getLong(2);
message.read = getMessageRead(cursor.getInt(3));
message.status = getMessageStatus(cursor.getInt(4));
message.type = getMessageType(cursor.getInt(5));
message.person = getPerson(message.address);
Log.i(TAG, "message : " + message.toString());
}
cursor.close();
}
}
权限如同上述说明,需要动态申请以及API版本的要求
属性说明:
Telephony.Sms.ADDRESS 发件人地址,即手机号
Telephony.Sms.BODY 短信具体内容
Telephony.Sms.DATE 日期,long型
Telephony.Sms.READ 是否阅读0未读,1已读
Telephony.Sms.STATUS 短信状态-1 接收,0 complete,64 pending,128 failed
Telephony.Sms.TYPE 短信类型1是接收到的,2是已发出
短信阅读状态代码:
private String getMessageRead(int anInt) {
if (1 == anInt) {
return "已读";
}
if (0 == anInt) {
return "未读";
}
return null;
}
短信类型区分代码:
private String getMessageType(int anInt) {
if (1 == anInt) {
return "收到的";
}
if (2 == anInt) {
return "已发出";
}
return null;
}
短信接收状态代码:
private String getMessageStatus(int anInt) {
switch (anInt) {
case -1:
return "接收";
case 0:
return "complete";
case 64:
return "pending";
case 128:
return "failed";
default:
break;
}
return null;
}
短信发件人代码,发件人,如果发件人在通讯录中则为具体姓名,陌生人为null:
private String getPerson(String address) {
try {
ContentResolver resolver = getContentResolver();
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, address);
Cursor cursor;
cursor = resolver.query(uri, new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME}, null, null, null);
if (cursor != null) {
try {
if (cursor.getCount() != 0) {
cursor.moveToFirst();
String name = cursor.getString(0);
return name;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
cursor.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
最后给出SMSMessage代码:
class SMSMessage {
long date;
String address;
String body;
String person;
String read;
String status;
String type;
@Override
public String toString() {
return "SMSMessage{" +
"date=" + formatDate(date) +
", address='" + address + '\'' +
", body='" + body + '\'' +
", person='" + person + '\'' +
", read='" + read + '\'' +
", status='" + status + '\'' +
", type='" + type + '\'' +
'}';
}
}
以上就是获取通话记录和短信内容的全部代码。