Android 용 통화 기록에 어떻게 액세스하나요?


95

통화 기록을 받고 싶습니다. 예를 들어 사용자의 통화 수, 통화 시간 (분) 등이 있습니다.

Android에서 어떻게 이것을 달성합니까?


수 있습니다이 U에 대한 솔루션입니다 developer.android.com/reference/android/database/...은
Nikunj 파텔

나는 그것이 콘텐츠 해결 자라는 것을 기억하지만 어떻게 시작 해야할지 모르겠습니다.
3cross

답변:


69

이것은 전화 통화 내역에 액세스하기위한 것입니다.

Jellybean (4.1)부터 다음 권한이 필요합니다.
<uses-permission android:name="android.permission.READ_CALL_LOG" />

암호:

 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.

11
이 권한을 활성화하는 것을 잊지 마십시오 : <uses-permission android : name = "android.permission.READ_CALL_LOG"/> 이것은 통화 기록을 가져 오는 방법입니다.
Aziz

모르겠지만 이론적으로는 모든 메시지가 동일한 데이터베이스에 저장되어 있다고 말할 수 있습니다. 예, 듀얼 시뮬레이션 또는 단일 시뮬레이션에 관계없이 장치의 모든 메시지에 액세스 할 수 있습니다. 이 코드를 확인하고 듀얼 시뮬레이션에서 작동하지 않는지 알려주십시오. R & D를 수행하고 이에 대한 코드를 제공하겠습니다.
Abhinav Singh Maurya 2015

1
이름은 항상 조심, 널 (null)을 반환 할 것이다 얻을
vuhung3990

@Abhinav Singh Maurya는 통화 기록에서 photo_uri를 가져올 수 없기 때문에 통화 기록에서 photo_uri 통화 기록을 가져 오도록 도와 줄 수 있습니다
Sagar

1
managedQuery ()는 더 이상 사용되지 않습니다. 대신 이것을 사용합니다. Cursor cursor = context.getContentResolver (). query (CallLog.Calls.CONTENT_URI, null, null, null, CallLog.Calls.DATE + "DESC");
Sai Gopi Me

67

통화 기록을 가져 오는 데 사용되는 방법입니다. 이 메소드를 수업에 넣고 통화 기록 목록을 얻으십시오.

이것을 확인하십시오

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();

    }

출력이 보인다

여기에 이미지 설명 입력


managedQuery (CallLog.Calls.CONTENT_URI, null, null, null, null); 오류가 발생합니다.
Sunil Parmar

5
contentResolver.query (CallLog.Calls.CONTENT_URI, null, null, null, null);
Sunil Parmar 2013 년

@Dwivedi Ji-약간 오래된 게시물입니다-귀하의 방법은 작동하지만 모든 통화 기록을로드하는 데 최소 10 초가 걸립니다.
TheDevMan 2013

@TheDevMan, 죄송합니다 귀하의 불편을 네, 당신이 좋아, 곧 내 대답을 업데이트하는
Dwivedi 지에게

감사합니다. 답장을 기다리겠습니다!
TheDevMan 2013

48

컨텍스트가있는 모든 곳에서이 방법을 사용하십시오.

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();
}

7
managedQuery는 이제 더 이상 사용되지 않으므로이 답변이 가장 적합합니다.
abhi

16

이 게시물은 조금 오래되었지만 CallAndroid에서 로그 콘텐츠 제공 업체 와 관련된 데이터를 가져 오는 또 다른 쉬운 솔루션입니다 .

이 lib 사용 : https://github.com/EverythingMe/easy-content-providers

모든 전화 받기 :

CallsProvider callsProvider = new CallsProvider(context);
List<Call> calls = callsProvider.getCalls().getList();

Call 에는 모든 필드가 있으므로 callDate, duration, number, type (INCOMING, OUTGOING, MISSED), isRead 등 필요한 정보를 얻을 수 있습니다
.

그것은 작동 List또는 Cursor그것을보고 어떻게 작동하는지 볼 수있는 샘플 애플리케이션이있다.

실제로 연락처, SMS, 캘린더 등 모든 Android 콘텐츠 제공 업체에 대한 지원이 있습니다. 모든 옵션이 포함 된 전체 문서 : https://github.com/EverythingMe/easy-content-providers/wiki/Android-providers

도움이 되었기를 바랍니다. :)


헤이, 당신의 해결책을 확인했습니다. 내가 직면 한 유일한 문제는 내 이클립스 프로젝트에 종속성을 추가하는 방법입니다.
Aradhna 2015 년

@aradhna 라이브러리는 gradle을 사용하고 있으며 Android Studio에서 빌드되었습니다. Eclipse에서 실행되도록 약간 수정해야한다고 생각합니다.
sromku

9

내 프로젝트에서 오류 int htc device.now이 코드가 보편적입니다. 나는 이것이 당신을위한 도움이라고 생각합니다.

    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();
    }

}

2

수신 통화 내역 만 가져 오려면 아래 코드가 도움이 될 것입니다.

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();
} 

2

수신, 발신 및 부재 중 전화 기록을 얻으려면이 코드가 도움이되기를 바랍니다.)

백그라운드 스레드에서이 코드를 호출하십시오.

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----------------------------------");

1

아래 코드를 사용하십시오.

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));




    }

0

Kotlin을 사용하면 더 짧습니다. 콜 로그 제공에 응답하는 클래스의 예 :

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))
}

커서를지도로 변환 할 수도 있습니다.

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
}

0

통화 기록 읽기 또는 SMS 읽기 권한을 애플리케이션의 일부로 만들기 전에 Google Play 마켓의이 정책을 살펴볼 것을 적극 권장합니다. https://support.google.com/googleplay/android-developer/answer/9047303 ? hl = en

이러한 권한은 매우 민감하므로 응용 프로그램에 필요함을 증명해야합니다. 그러나 실제로 필요한 경우에도 Google Play 지원팀은 적절한 설명없이 요청을 쉽게 거부 할 수 있습니다.

이것은 나에게 일어난 일입니다. 내 애플리케이션의 데모 비디오와 함께 필요한 모든 정보를 제공 한 후 내 "계정이 내 애플리케이션에서 특정 사용 사례 솔루션을 제공 할 권한이 없습니다" 라는 설명과 함께 거부되었습니다 (예외로 간주 할 수있는 사용 사례 목록). 해당 정책 페이지에 나열되어 있습니다). 이것이 의미하는 바를 설명하기 위해 정책 설명에 대한 링크가 제공되지 않았습니다. 기본적으로 그들은 내 앱이 적절한 설명 없이는 가지 않는 것으로 판단했습니다.

나는 당신의 응용 프로그램들과 함께 행운을 빕니다. 그러나 조심하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.