Tôi muốn nhận nhật ký cuộc gọi. Ví dụ: số lượng cuộc gọi của người dùng, số phút đã gọi, v.v.
Làm cách nào để đạt được điều này trong Android?
Tôi muốn nhận nhật ký cuộc gọi. Ví dụ: số lượng cuộc gọi của người dùng, số phút đã gọi, v.v.
Làm cách nào để đạt được điều này trong Android?
Câu trả lời:
Điều này là để truy cập lịch sử cuộc gọi điện thoại:
Kể từ Jellybean (4.1), bạn cần có quyền sau:
<uses-permission android:name="android.permission.READ_CALL_LOG" />
Mã:
Uri allCalls = Uri.parse("content://call_log/calls");
Cursor c = managedQuery(allCalls, null, null, null, null);
String num= c.getString(c.getColumnIndex(CallLog.Calls.NUMBER));// for number
String name= c.getString(c.getColumnIndex(CallLog.Calls.CACHED_NAME));// for name
String duration = c.getString(c.getColumnIndex(CallLog.Calls.DURATION));// for duration
int type = Integer.parseInt(c.getString(c.getColumnIndex(CallLog.Calls.TYPE)));// for call type, Incoming or out going.
Đây là phương pháp được sử dụng để lấy Nhật ký cuộc gọi. Chỉ cần đặt phương thức này trong lớp của bạn và nhận Danh sách Nhật ký cuộc gọi.
private String getCallDetails() {
StringBuffer sb = new StringBuffer();
Cursor managedCursor = managedQuery(CallLog.Calls.CONTENT_URI, null,
null, null, null);
int number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER);
int type = managedCursor.getColumnIndex(CallLog.Calls.TYPE);
int date = managedCursor.getColumnIndex(CallLog.Calls.DATE);
int duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION);
sb.append("Call Details :");
while (managedCursor.moveToNext()) {
String phNumber = managedCursor.getString(number);
String callType = managedCursor.getString(type);
String callDate = managedCursor.getString(date);
Date callDayTime = new Date(Long.valueOf(callDate));
String callDuration = managedCursor.getString(duration);
String dir = null;
int dircode = Integer.parseInt(callType);
switch (dircode) {
case CallLog.Calls.OUTGOING_TYPE:
dir = "OUTGOING";
break;
case CallLog.Calls.INCOMING_TYPE:
dir = "INCOMING";
break;
case CallLog.Calls.MISSED_TYPE:
dir = "MISSED";
break;
}
sb.append("\nPhone Number:--- " + phNumber + " \nCall Type:--- "
+ dir + " \nCall Date:--- " + callDayTime
+ " \nCall duration in sec :--- " + callDuration);
sb.append("\n----------------------------------");
}
managedCursor.close();
return sb.toString();
}
đầu ra trông

sử dụng phương pháp này từ mọi nơi với một ngữ cảnh
private static String getCallDetails(Context context) {
StringBuffer stringBuffer = new StringBuffer();
Cursor cursor = context.getContentResolver().query(CallLog.Calls.CONTENT_URI,
null, null, null, CallLog.Calls.DATE + " DESC");
int number = cursor.getColumnIndex(CallLog.Calls.NUMBER);
int type = cursor.getColumnIndex(CallLog.Calls.TYPE);
int date = cursor.getColumnIndex(CallLog.Calls.DATE);
int duration = cursor.getColumnIndex(CallLog.Calls.DURATION);
while (cursor.moveToNext()) {
String phNumber = cursor.getString(number);
String callType = cursor.getString(type);
String callDate = cursor.getString(date);
Date callDayTime = new Date(Long.valueOf(callDate));
String callDuration = cursor.getString(duration);
String dir = null;
int dircode = Integer.parseInt(callType);
switch (dircode) {
case CallLog.Calls.OUTGOING_TYPE:
dir = "OUTGOING";
break;
case CallLog.Calls.INCOMING_TYPE:
dir = "INCOMING";
break;
case CallLog.Calls.MISSED_TYPE:
dir = "MISSED";
break;
}
stringBuffer.append("\nPhone Number:--- " + phNumber + " \nCall Type:--- "
+ dir + " \nCall Date:--- " + callDayTime
+ " \nCall duration in sec :--- " + callDuration);
stringBuffer.append("\n----------------------------------");
}
cursor.close();
return stringBuffer.toString();
}
Bài đăng này hơi cũ, nhưng đây là một giải pháp dễ dàng khác để lấy dữ liệu liên quan đến Callnhà cung cấp nội dung nhật ký trong Android:
Sử dụng lib này: https://github.com/EverythingMe/easy-content-providers
Nhận tất cả các cuộc gọi:
CallsProvider callsProvider = new CallsProvider(context);
List<Call> calls = callsProvider.getCalls().getList();
Mỗi Cuộc gọi có tất cả các trường, vì vậy bạn có thể nhận được bất kỳ thông tin nào bạn cần: ngày
gọi, thời lượng, số điện thoại, loại (THU NHẬP, XUẤT XỨ, ĐÃ BỎ LỠ), isRead, ...
Nó hoạt động với Listhoặc Cursorvà có một ứng dụng mẫu để xem nó trông như thế nào và hoạt động như thế nào.
Trên thực tế, có một hỗ trợ cho tất cả các nhà cung cấp nội dung Android như: Danh bạ, SMS, Lịch, ... Tài liệu đầy đủ với tất cả các tùy chọn: https://github.com/EverythingMe/easy-content-providers/wiki/Android-providers
Hy vọng nó cũng giúp ích :)
trong dự án của tôi, tôi gặp lỗi int htc device. biết mã này là phổ biến. Tôi nghĩ rằng đây là sự giúp đỡ cho bạn.
public class CustomContentObserver extends ContentObserver {
public CustomContentObserver(Handler handler) {
super(handler);
System.out.println("Content obser");
}
public void onChange(boolean selfChange) {
super.onChange(selfChange);
String lastCallnumber;
currentDate = sdfcur.format(calender.getTime());
System.out.println("Content obser onChange()");
Log.d("PhoneService", "custom StringsContentObserver.onChange( " + selfChange + ")");
//if(!callFlag){
String[] projection = new String[]{CallLog.Calls.NUMBER,
CallLog.Calls.TYPE,
CallLog.Calls.DURATION,
CallLog.Calls.CACHED_NAME,
CallLog.Calls._ID};
Cursor c;
c=mContext.getContentResolver().query(CallLog.Calls.CONTENT_URI, projection, null, null, CallLog.Calls._ID + " DESC");
if(c.getCount()!=0){
c.moveToFirst();
lastCallnumber = c.getString(0);
String type=c.getString(1);
String duration=c.getString(2);
String name=c.getString(3);
String id=c.getString(4);
System.out.println("CALLLLing:"+lastCallnumber+"Type:"+type);
Database db=new Database(mContext);
Cursor cur =db.getFirstRecord(lastCallnumber);
final String endCall=lastCallnumber;
//checking incoming/outgoing call
if(type.equals("3")){
//missed call
}else if(type.equals("1")){
//incoming call
}else if(type.equals("2")){
//outgoing call
}
}
c.close();
}
}
Để chỉ có lịch sử cuộc gọi đến, mã bên dưới sẽ giúp bạn :)
private void getCallDetailsAgil() {
StringBuffer sb = new StringBuffer();
Cursor managedCursor = managedQuery(CallLog.Calls.CONTENT_URI, null, null, null, null);
int number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER);
int type = managedCursor.getColumnIndex(CallLog.Calls.TYPE);
int date = managedCursor.getColumnIndex(CallLog.Calls.DATE);
int duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION);
sb.append("Call Details :");
while (managedCursor.moveToNext()) {
String phNumber = managedCursor.getString(number);
String callType = managedCursor.getString(type);
String callDate = managedCursor.getString(date);
Date callDayTime = new Date(Long.valueOf(callDate));
String callDuration = managedCursor.getString(duration);
String dir = null;
int dircode = Integer.parseInt(callType);
switch (dircode) {
case CallLog.Calls.OUTGOING_TYPE:
dir = "OUTGOING";
break;
case CallLog.Calls.INCOMING_TYPE:
dir = "INCOMING";
sb.append("\nPhone Number:--- " + phNumber + " \nCall Type:--- " + dir + " \nCall Date:--- " + callDayTime + " \nCall duration in sec :--- " + callDuration);
sb.append("\n----------------------------------");
miss_cal.setText(sb);
break;
case CallLog.Calls.MISSED_TYPE:
dir = "MISSED";
break;
}
}
managedCursor.close();
}
Để nhận lịch sử Cuộc gọi Đến, Đi và Nhỡ, hy vọng mã này sẽ giúp bạn :)
Gọi mã này trên chuỗi nền của bạn.
StringBuffer sb = new StringBuffer();
String[] projection = new String[] {
CallLog.Calls.CACHED_NAME,
CallLog.Calls.NUMBER,
CallLog.Calls.TYPE,
CallLog.Calls.DATE,
CallLog.Calls.DURATION
};
sb.append("Call Details :");
// String strOrder = android.provider.CallLog.Calls.DATE + " DESC";
Cursor managedCursor = getApplicationContext().getContentResolver().query(CallLog.Calls.CONTENT_URI, projection, null, null, null);
while (managedCursor.moveToNext()) {
String name = managedCursor.getString(0); //name
String number = managedCursor.getString(1); // number
String type = managedCursor.getString(2); // type
String date = managedCursor.getString(3); // time
@SuppressLint("SimpleDateFormat")
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm");
String dateString = formatter.format(new Date(Long.parseLong(date)));
String duration = managedCursor.getString(4); // duration
String dir = null;
int dircode = Integer.parseInt(type);
switch (dircode) {
case CallLog.Calls.OUTGOING_TYPE:
dir = "OUTGOING";
break;
case CallLog.Calls.INCOMING_TYPE:
dir = "INCOMING";
break;
case CallLog.Calls.MISSED_TYPE:
dir = "MISSED";
break;
}
sb.append("\nPhone Name :-- "+name+" Number:--- " + number + " \nCall Type:--- " + dir + " \nCall Date:--- " + dateString + " \nCall duration in sec :--- " + duration);
sb.append("\n----------------------------------");
Sử dụng mã dưới đây:
private void getCallDeatils() {
StringBuffer stringBuffer = new StringBuffer();
Cursor managedCursor = getActivity().managedQuery(CallLog.Calls.CONTENT_URI, null, null, null, null);
int number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER);
int type = managedCursor.getColumnIndex(CallLog.Calls.TYPE);
int date = managedCursor.getColumnIndex(CallLog.Calls.DATE);
int duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION);
stringBuffer.append("Call Deatils");
while (managedCursor.moveToNext()) {
String phNumber = managedCursor.getString(number);
String callType = managedCursor.getString(type);
String callDate = managedCursor.getString(date);
Date callDayTime = new Date(Long.valueOf(callDate));
DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
String reportDate = df.format(callDayTime);
String callDuration = managedCursor.getString(duration);
String dir = null;
int dircode = Integer.parseInt(callType);
switch (dircode) {
case CallLog.Calls.OUTGOING_TYPE:
dir = "OUTGOING";
break;
case CallLog.Calls.INCOMING_TYPE:
dir = "INCOMING";
break;
case CallLog.Calls.MISSED_TYPE:
dir = "MISSED";
break;
}
stringBuffer.append("\nPhone Number:--- " + phNumber + " \nCall Type:--- " + dir + " \nCall Date:--- " +callDate + " \nCall duration in sec :--- " + callDuration);
stringBuffer.append("\n----------------------------------");
logs.add(new LogClass(phNumber,dir,reportDate,callDuration));
}
Nếu chúng ta sử dụng Kotlin thì nó ngắn hơn. Ví dụ về lớp phản hồi để cung cấp nhật ký cuộc gọi:
import android.content.Context
import android.database.Cursor
import android.provider.CallLog.Calls.*
class CallsLoader {
fun getCallLogs(context: Context): List<List<String?>> {
val c = context.applicationContext
val projection = arrayOf(CACHED_NAME, NUMBER, TYPE, DATE, DURATION)
val cursor = c.contentResolver.query(
CONTENT_URI,
projection,
null,
null,
null,
null
)
return cursorToMatrix(cursor)
}
private fun cursorToMatrix(cursor: Cursor?): List<List<String?>> {
val matrix = mutableListOf<List<String?>>()
cursor?.use {
while (it.moveToNext()) {
val list = listOf(
it.getStringFromColumn(CACHED_NAME),
it.getStringFromColumn(NUMBER),
it.getStringFromColumn(TYPE),
it.getStringFromColumn(DATE),
it.getStringFromColumn(DURATION)
)
matrix.add(list.toList())
}
}
return matrix
}
private fun Cursor.getStringFromColumn(columnName: String) =
getString(getColumnIndex(columnName))
}
Chúng tôi cũng có thể chuyển đổi con trỏ sang bản đồ:
fun getCallLogs(context: Context): Map<String, Array<String?>> {
val c = context.applicationContext
val projection = arrayOf(CACHED_NAME, NUMBER, TYPE, DATE, DURATION)
val cursor = c.contentResolver.query(
CONTENT_URI,
projection,
null,
null,
null,
null
)
return cursorToMap(cursor)
}
private fun cursorToMap(cursor: Cursor?): Map<String, Array<String?>> {
val arraySize = cursor?.count ?: 0
val map = mapOf(
CACHED_NAME to Array<String?>(arraySize) { "" },
NUMBER to Array<String?>(arraySize) { "" },
TYPE to Array<String?>(arraySize) { "" },
DATE to Array<String?>(arraySize) { "" },
DURATION to Array<String?>(arraySize) { "" }
)
cursor?.use {
for (i in 0 until arraySize) {
it.moveToNext()
map[CACHED_NAME]?.set(i, it.getStringFromColumn(CACHED_NAME))
map[NUMBER]?.set(i, it.getStringFromColumn(NUMBER))
map[TYPE]?.set(i, it.getStringFromColumn(TYPE))
map[DATE]?.set(i, it.getStringFromColumn(DATE))
map[DURATION]?.set(i, it.getStringFromColumn(DURATION))
}
}
return map
}
Trước khi cân nhắc đặt quyền Đọc Nhật ký cuộc gọi hoặc Đọc SMS trở thành một phần trong ứng dụng của bạn, tôi thực sự khuyên bạn nên xem chính sách này của Google Play Market: https://support.google.com/googleplay/android-developer/answer/9047303 ? hl = vi
Những quyền đó rất nhạy cảm và bạn sẽ phải chứng minh rằng ứng dụng của bạn cần chúng. Nhưng ngay cả khi thực sự cần, Nhóm hỗ trợ của Google Play có thể dễ dàng từ chối yêu cầu của bạn mà không có lời giải thích thích hợp.
Đây là những gì xảy ra với tôi. Sau khi cung cấp tất cả các thông tin cần thiết cùng với video Trình diễn về ứng dụng của tôi, ứng dụng của tôi đã bị từ chối với giải thích rằng "tài khoản của tôi không được phép cung cấp giải pháp trường hợp sử dụng nhất định trong ứng dụng của tôi" (danh sách các trường hợp sử dụng mà họ có thể coi là ngoại lệ được liệt kê trên trang Chính sách đó). Không có liên kết đến bất kỳ tuyên bố chính sách nào được cung cấp để giải thích tất cả ý nghĩa của nó. Về cơ bản, họ chỉ đánh giá ứng dụng của tôi là không hoạt động mà không có lời giải thích thích hợp.
Tôi chúc bạn may mắn vì các ứng dụng của bạn, nhưng hãy cẩn thận.