Reputation: 1348
I am using below code to get last call details from call log.
public static CallDetails getLastCallDetails(Context context) {
CallDetails callDetails = new CallDetails();
Uri contacts = CallLog.Calls.CONTENT_URI;
try {
Cursor managedCursor = context.getContentResolver().query(contacts, null, null, null, android.provider.CallLog.Calls.DATE + " DESC limit 1;");
int number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER);
int duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION);
int date = managedCursor.getColumnIndex(CallLog.Calls.DATE);
int incomingtype = managedCursor.getColumnIndex(String.valueOf(CallLog.Calls.INCOMING_TYPE));
while (managedCursor.moveToNext()) {
String callType;
String phNumber = managedCursor.getString(number);
String callerName = getContactName(context, phNumber);
if(incomingtype == -1){
callType = "incoming";
}
else {
callType = "outgoing";
}
String callDate = managedCursor.getString(date);
String callDayTime = new Date(Long.valueOf(callDate)).toString();
String callDuration = managedCursor.getString(duration);
callDetails.setCallerName(callerName);
callDetails.setCallerNumber(phNumber);
callDetails.setCallDuration(callDuration);
callDetails.setCallType(callType);
callDetails.setCallTimeStamp(callDayTime);
}
managedCursor.close();
} catch (SecurityException e) {
Log.e("Security Exception", "User denied call log permission");
}
return callDetails;
}
The problem is that it returns the last second call and not the last call. I need to return the last call. I googled it but I am not able to get the perfect solution. Please help. Thanks in advance.
Upvotes: 6
Views: 10856
Reputation: 126
I faced the same issue with my code-
check this situation - suppose I call client 1 and the duration is 50 seconds and it fetched correctly now I call client 2 its duration is 2 minutes which also fetched successfully now when I again call client 1 he doesn't pick up the call and duration is fetched here wrong 50 seconds which is the last second call duration and not the last call which is 0 -
@SuppressLint("Range")
private suspend fun lastCallDetail(): String {
val delayDuration = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU) 3000L else 2000L
delay(delayDuration)
var callDuration = "0"
try {
val cur: Cursor? = contentResolver.query(
CallLog.Calls.CONTENT_URI,
null, null, null, CallLog.Calls.DATE + " DESC limit 1;"
)
if (cur != null) {
while (cur.moveToNext()) {
callDuration = cur.getString(cur.getColumnIndex(CallLog.Calls.DURATION))
break
}
cur.close()
}
} catch (e : Exception) {
e.printStackTrace()
}
return callDuration
}
private suspend fun lastCallIncoming(): String {
delay(3000)
var callDuration = "00:00:00"
try {
val cur = applicationContext.contentResolver.query(
CallLog.Calls.CONTENT_URI,
null,
null,
null,
CallLog.Calls.DATE + " DESC"
)
val duration = cur!!.getColumnIndex(CallLog.Calls.DURATION)
while (cur.moveToNext()) {
callDuration = cur.getString(duration)
Log.d("callTracking", callDuration)
break
}
cur.close()
val timeSec = callDuration.toInt() // Json output
callDuration = timeSec.toString() //hh:mm:ss formatted string
Log.d("callTracking", callDuration)
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
return callDuration
}
private fun secToTime(second: Int): String {
var sec = second
val hours = sec / 3600
val minutes = sec % 3600/ 60
sec %= 60
return String.format("%02d:%02d:%02d", hours, minutes, sec)
}
I also try this solution that returns the last-second call duration and not the last call but in some devices, it works fine where the devices have ToptoBottom call records. -
@SuppressLint("Range")
private suspend fun lastCallDetail(): String {
val delayDuration = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU) 3000L else 2000L
delay(delayDuration)
var callDuration = "0"
try {
val callLogCursor: Cursor? = contentResolver.query(
CallLog.Calls.CONTENT_URI,
null, null, null, CallLog.Calls.DATE + " DESC limit 1;"
)
if (callLogCursor != null) {
// Check the order of the call logs
val isOrderTopToBottom = determineCallLogOrder(callLogCursor)
// Move accoreding to the determined order
callLogCursor.moveToFirst()
val durationIndex = callLogCursor.getColumnIndex(CallLog.Calls.DURATION)
if (durationIndex != -1) {
if (isOrderTopToBottom) {
callDuration = callLogCursor.getString(durationIndex)
} else {
callLogCursor.moveToLast()
callDuration = callLogCursor.getString(durationIndex)
}
}
callLogCursor.close()
}
} catch (e: Exception) {
e.printStackTrace()
}
return callDuration
}
@SuppressLint("Range")
private suspend fun lastCallIncoming(): String {
delay(3000)
var callDuration = "00:00:00"
try {
val callLogCursor = applicationContext.contentResolver.query(
CallLog.Calls.CONTENT_URI,
null,
null,
null,
CallLog.Calls.DATE + " DESC"
)
if (callLogCursor != null) {
// Check the order of the call logs
val isOrderTopToBottom = determineCallLogOrder(callLogCursor)
callLogCursor.moveToFirst()
val durationIndex = callLogCursor.getColumnIndex(CallLog.Calls.DURATION)
// Move according to the determined order
if (durationIndex != -1) {
if (isOrderTopToBottom) {
callDuration = callLogCursor.getString(durationIndex)
} else {
callLogCursor.moveToLast()
callDuration = callLogCursor.getString(durationIndex)
}
val timeSec = callDuration.toInt()
callDuration = secToTime(timeSec)
Log.d("callTracking", callDuration)
}
callLogCursor.close()
}
} catch (e: Exception) {
e.printStackTrace()
}
return callDuration
}
private fun determineCallLogOrder(cursor: Cursor): Boolean {
var isOrderTopToBottom = true
if (cursor.moveToFirst()) {
val dateColumnIndex = cursor.getColumnIndex(CallLog.Calls.DATE)
if (dateColumnIndex != -1) {
val firstTimestamp = cursor.getLong(dateColumnIndex)
if (cursor.moveToNext()) {
val secondTimestamp = cursor.getLong(dateColumnIndex)
isOrderTopToBottom = firstTimestamp > secondTimestamp
}
}
}
return isOrderTopToBottom
}
private fun secToTime(second: Int): String {
var sec = second
val hours = sec / 3600
val minutes = sec % 3600/ 60
sec %= 60
return String.format("%02d:%02d:%02d", hours, minutes, sec)
}
Upvotes: 0
Reputation: 2179
Add this line managedCursor.moveToFirst()
public static CallDetails getLastCallDetails(Context context) {
CallDetails callDetails = new CallDetails();
Uri contacts = CallLog.Calls.CONTENT_URI;
try {
Cursor managedCursor = context.getContentResolver().query(contacts, null, null, null, android.provider.CallLog.Calls.DATE + " DESC limit 1;");
int number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER);
int duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION);
int date = managedCursor.getColumnIndex(CallLog.Calls.DATE);
int incomingtype = managedCursor.getColumnIndex(String.valueOf(CallLog.Calls.INCOMING_TYPE));
if(managedCursor.moveToFirst()){ // added line
while (managedCursor.moveToNext()) {
String callType;
String phNumber = managedCursor.getString(number);
String callerName = getContactName(context, phNumber);
if(incomingtype == -1){
callType = "incoming";
}
else {
callType = "outgoing";
}
String callDate = managedCursor.getString(date);
String callDayTime = new Date(Long.valueOf(callDate)).toString();
String callDuration = managedCursor.getString(duration);
callDetails.setCallerName(callerName);
callDetails.setCallerNumber(phNumber);
callDetails.setCallDuration(callDuration);
callDetails.setCallType(callType);
callDetails.setCallTimeStamp(callDayTime);
}
}
managedCursor.close();
} catch (SecurityException e) {
Log.e("Security Exception", "User denied call log permission");
}
return callDetails;
}
Upvotes: 7