Eu gostaria de receber o registro de chamadas. Por exemplo, o número de chamadas feitas pelo usuário, número de minutos chamados, etc.
Como faço para fazer isso no Android?
Eu gostaria de receber o registro de chamadas. Por exemplo, o número de chamadas feitas pelo usuário, número de minutos chamados, etc.
Como faço para fazer isso no Android?
Respostas:
Isso é para acessar o histórico de chamadas:
A partir do Jellybean (4.1), você precisa da seguinte permissão:
<uses-permission android:name="android.permission.READ_CALL_LOG" />
Código:
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.
Este é o método usado para obter o registro de chamadas. Basta colocar este método em sua classe e obter a Lista do Registro de Chamadas.
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();
}
a saída parece

use este método de qualquer lugar com um contexto
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();
}
Esta postagem é um pouco antiga, mas aqui está outra solução fácil para obter dados relacionados ao Callprovedor de conteúdo de registros no Android:
Use esta biblioteca: https://github.com/EverythingMe/easy-content-providers
Receba todas as ligações:
CallsProvider callsProvider = new CallsProvider(context);
List<Call> calls = callsProvider.getCalls().getList();
Cada chamada tem todos os campos, para que você possa obter qualquer informação de que precisar: data da
chamada, duração, número, tipo (ENTRADA, SAÍDA, PERDIDA), isRead, ...
Funciona com Listou Cursore há um aplicativo de amostra para ver como fica e funciona.
Na verdade, há suporte para todos os provedores de conteúdo Android, como: Contatos, SMS, Agenda, ... Documento completo com todas as opções: https://github.com/EverythingMe/easy-content-providers/wiki/Android-providers
Espero que também tenha ajudado :)
no meu projeto estou recebendo o erro int htc device.now this code is universal. Eu acho que isso é uma ajuda para você.
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();
}
}
Para obter apenas o histórico de chamadas recebidas, o código abaixo o ajudará :)
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();
}
Para obter o histórico de chamadas recebidas, efetuadas e perdidas, espero que este código o ajude :)
Chame este código em seu thread de segundo plano.
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----------------------------------");
Use o código abaixo:
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));
}
Se usarmos Kotlin, é mais curto. Exemplo de classe que responde para fornecer registros de chamadas:
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))
}
Também podemos converter o cursor em mapa:
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
}
Antes de considerar tornar as permissões Ler registro de chamadas ou Ler SMS parte de seu aplicativo, recomendo fortemente que você dê uma olhada nesta política do Google Play Market: https://support.google.com/googleplay/android-developer/answer/9047303 ? hl = en
Essas permissões são muito confidenciais e você terá que provar que seu aplicativo precisa delas. Mas mesmo que realmente precise deles, a equipe de suporte do Google Play pode facilmente rejeitar sua solicitação sem as devidas explicações.
Isto é o que aconteceu comigo. Depois de fornecer todas as informações necessárias junto com o vídeo de demonstração de meu aplicativo, ele foi rejeitado com a explicação de que minha "conta não está autorizada a fornecer uma determinada solução de caso de uso em meu aplicativo" (a lista de casos de uso que eles podem considerar uma exceção está listado nessa página de política). Nenhum link para qualquer declaração de política foi fornecido para explicar o que tudo isso significa. Basicamente, eles julgaram que meu aplicativo não fica sem uma explicação adequada.
Desejo a vocês boa sorte de causa com seus aplicativos, pessoal, mas tenham cuidado.