Як отримати доступ до журналу викликів для Android?


95

Я хотів би отримати журнал дзвінків. Наприклад, кількість дзвінків, здійснених користувачем, кількість хвилин дзвінків тощо.

Як мені досягти цього в android?


можливо це рішення для розробника
U.android.com/reference/android/database/…

Я пам’ятаю, що це вирішувач вмісту, проте я не маю уявлення, як запустити цю справу.
хрест

Відповіді:


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
Не забудьте ввімкнути цей дозвіл: <koristi-дозвіл android: name = "android.permission.READ_CALL_LOG" /> це спосіб отримання журналу викликів:
Азіз

Я цього не знаю, але теоретично можу сказати, що всі повідомлення зберігаються в одній базі даних. Так так, він може отримати доступ до всіх повідомлень пристрою, незалежно від подвійної або одиночної. Перевірте цей код і повідомте мене, якщо він не працює з dual sim. Я проведу деякі дослідження та розробки та надам вам код для цього.
Абхінав Сінгх Маурія

1
get name завжди повертатиме нуль, будьте обережні
vuhung3990 02

@Abhinav Singh Maurya, чи можете ви допомогти мені отримати журнал викликів photo_uri з журналів дзвінків, оскільки я не можу отримати photo_uri з журналу викликів
Сагар

1
застаріле управлінняQuery () використовує замість цього Курсор 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();

    }

результат виглядає

введіть тут опис зображення


Я отримую помилку в ManagQuery (CallLog.Calls.CONTENT_URI, null, null, null, null);
Суніл Пармар

5
Я використовував contentResolver.query (CallLog.Calls.CONTENT_URI, null, null, null, null);
Суніл Пармар

@Dwivedi Ji - Це трохи стара публікація - Ваш метод працює, але завантаження всіх моїх журналів дзвінків займає щонайменше 10 секунд.
TheDevMan

@TheDevMan, вибачте за ваші незручності. Так, ви маєте рацію, незабаром я оновлю свою відповідь,
Dwivedi Ji

Дякую, я дочекаюсь вашої відповіді!
TheDevMan

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
Оскільки ManagQuery зараз застарілий, тому ця відповідь є найбільш актуальною.
abhi

16

Ця публікація трохи стара, але ось ще одне просте рішення для отримання даних, пов’язаних із Callпостачальником вмісту журналів в Android:

Використовуйте цю бібліотеку: https://github.com/EverythingMe/easy-content-providers

Отримати всі дзвінки:

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

Кожен дзвінок має всі поля, тому ви можете отримати будь-яку інформацію, яка вам потрібна:
дата виклику, тривалість, номер, тип (ВХІД, ВИХІД, ПРОПУСК), isRead, ...

Він працює з Listабо, Cursorі є зразок програми, щоб побачити, як це виглядає та працює.

Насправді є підтримка для всіх постачальників вмісту Android, таких як: Контакти, SMS, Календар, ... Повний документ із усіма опціями: https://github.com/EverythingMe/easy-content-providers/wiki/Android-providers

Сподіваюся, це також допомогло :)


Гей, я перевірив ваше рішення, це добре. Єдина проблема, з якою я стикаюся, полягає в тому, як додати залежність у своєму проекті затемнення?
Арадна,

@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

Щоб отримати лише історію вхідних дзвінків, під кодом допоможе u :)

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 Market: https://support.google.com/googleplay/android-developer/answer/9047303 ? hl = uk

Ці дозволи дуже чутливі, і вам доведеться довести, що вони потрібні вашій програмі. Але навіть якщо вони їм дійсно потрібні, команда підтримки Google Play може легко відхилити ваш запит без відповідних пояснень.

Це сталося зі мною. Після надання всієї необхідної інформації разом із демонстраційним відео моєї заявки було відхилено з поясненням, що мій "акаунт не уповноважений надавати певне рішення щодо використання в моїй заявці" (перелік випадків використання, які вони можуть розглядати як виняток вказано на цій сторінці політики). Не було посилання на жодну заяву про політику, щоб пояснити, що це все означає. В основному вони просто оцінили мій додаток як такий, що не йде без належних пояснень.

Бажаю вам удачі у справі з вашими заявками, хлопці, але будьте обережні.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.