Comment accéder au journal des appels pour Android?

95

Je souhaite recevoir le journal des appels. Par exemple, le nombre d'appels effectués par l'utilisateur, le nombre de minutes appelées, etc.

Comment puis-je y parvenir sous Android?

3cross
la source
peut-être que c'est une solution pour U developer.android.com/reference/android/database/…
Nikunj Patel
Je me souviens que c'était un résolveur de contenu, mais je ne sais pas comment démarrer la chose.
3cross

Réponses:

69

Ceci est pour accéder à l'historique des appels téléphoniques:

Depuis Jellybean (4.1), vous avez besoin de l'autorisation suivante:
<uses-permission android:name="android.permission.READ_CALL_LOG" />

Code:

 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.
Abhinav Singh Maurya
la source
11
N'oubliez pas d'activer cette autorisation: <uses-permission android: name = "android.permission.READ_CALL_LOG" /> voici la méthode pour obtenir le journal des appels:
Aziz
Je ne sais pas cela mais théoriquement je peux dire que tous les messages sont stockés dans la même base de données. Alors oui, il peut accéder à tous les messages de l'appareil indépendamment du dual sim ou single sim. Vérifiez ce code et faites-moi savoir s'il ne fonctionne pas avec la double sim. Je vais faire de la R&D et vous fournir un code pour cela.
Abhinav Singh Maurya
1
get name retournera toujours null, soyez prudent
vuhung3990
@Abhinav Singh Maurya pouvez-vous m'aider à obtenir le journal des appels photo_uri à partir des journaux d'appels car je ne parviens pas à obtenir photo_uri à partir du journal des appels
Sagar
1
managedQuery () obsolète utiliser à la place Cursor cursor = context.getContentResolver (). query (CallLog.Calls.CONTENT_URI, null, null, null, CallLog.Calls.DATE + "DESC");
Sai Gopi Me
67

C'est la méthode utilisée pour obtenir le journal des appels. Mettez simplement cette méthode dans votre classe et obtenez la liste du journal des appels.

Regarde ça

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

    }

la sortie ressemble

entrez la description de l'image ici

Dwivedi Ji
la source
J'obtiens une erreur à managedQuery (CallLog.Calls.CONTENT_URI, null, null, null, null);
Sunil Parmar
5
J'ai utilisé contentResolver.query (CallLog.Calls.CONTENT_URI, null, null, null, null);
Sunil Parmar
@Dwivedi Ji - C'est un peu un vieux post - Votre méthode fonctionne mais cela prend au moins 10 secondes pour charger tous mes journaux d'appels.
TheDevMan
@TheDevMan, désolé pour votre gêne, Oui vous avez raison, je mettrai à jour ma réponse bientôt,
Dwivedi Ji
Merci j'attendrai votre réponse!
TheDevMan
48

utilisez cette méthode de partout avec un contexte

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();
}
ingyesid
la source
7
Étant donné que managedQuery est désormais obsolète, cette réponse est la plus pertinente.
abhi
16

Cet article est un peu vieux, mais voici une autre solution simple pour obtenir des données liées au Callfournisseur de contenu de journaux dans Android:

Utilisez cette bibliothèque: https://github.com/EverythingMe/easy-content-providers

Recevez tous les appels:

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

Chaque appel a tous les champs, vous pouvez donc obtenir toutes les informations dont vous avez besoin: date de l'
appel, durée, numéro, type (ENTRANT, SORTANT, MANQUÉ), isRead, ...

Il fonctionne avec Listou Cursoret il existe un exemple d'application pour voir à quoi il ressemble et fonctionne.

En fait, il existe un support pour tous les fournisseurs de contenu Android tels que: Contacts, SMS, Calendrier, ... Doc complet avec toutes les options: https://github.com/EverythingMe/easy-content-providers/wiki/Android-providers

J'espère que cela a également aidé :)

sromku
la source
Hé, j'ai vérifié votre solution, c'est bien. Le seul problème auquel je suis confronté est de savoir comment ajouter la dépendance dans mon projet eclipse?
Aradhna
@aradhna la bibliothèque utilise gradle et a été créée à partir d'Android Studio. Je pense que vous devrez le modifier un peu pour le faire fonctionner sur Eclipse
sromku
9

dans mon projet, j'obtiens une erreur int htc device.now ce code est universel. Je pense que cela vous aide.

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

}
Harshid
la source
2

Pour obtenir uniquement l'historique des appels entrants, le code ci-dessous vous aidera :)

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();
} 
Agilanbu
la source
2

Pour obtenir l'historique des appels entrants, sortants et manqués, espérons que ce code vous aidera :)

Appelez ce code sur votre fil d'arrière-plan.

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----------------------------------");
Saurabh Gaddelpalliwar
la source
1

Utilisez le code ci-dessous:

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




    }
Rohan Lodhi
la source
0

Si nous utilisons Kotlin, il est plus court. Exemple de classe qui répond pour fournir des journaux d'appels:

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

Nous pouvons également convertir le curseur en carte:

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
}
Artem Botnev
la source
0

Avant d'envisager d'intégrer les autorisations Lire le journal des appels ou Lire les SMS dans votre application, je vous conseille vivement de consulter cette politique de Google Play Market: https://support.google.com/googleplay/android-developer/answer/9047303 ? hl = fr

Ces autorisations sont très sensibles et vous devrez prouver que votre application en a besoin. Mais même si elle en a vraiment besoin, l'équipe d'assistance Google Play peut facilement rejeter votre demande sans explications appropriées.

Voilà ce qui m'est arrivé. Après avoir fourni toutes les informations nécessaires avec la vidéo de démonstration de mon application, elle a été rejetée avec l'explication que mon "compte n'est pas autorisé à fournir une certaine solution de cas d'utilisation dans mon application" (la liste des cas d'utilisation qu'ils peuvent considérer comme une exception est répertorié sur cette page de politique). Aucun lien vers un énoncé de politique n'a été fourni pour expliquer ce que tout cela signifie. En gros, ils ont juste jugé mon application comme ne pas aller sans explication appropriée.

Je vous souhaite bonne chance de cause avec vos applications les gars mais soyez prudent.

dpetruha
la source