feat: add SIM name handling to call history and display in UI

This commit is contained in:
AlexisDanlos 2025-06-27 15:33:13 +02:00 committed by stcb
parent 10728ad6e0
commit 95f747280a
2 changed files with 119 additions and 6 deletions

View File

@ -10,6 +10,8 @@ import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.provider.CallLog import android.provider.CallLog
import android.telecom.TelecomManager import android.telecom.TelecomManager
import android.telephony.SubscriptionManager
import android.telephony.SubscriptionInfo
import android.util.Log import android.util.Log
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.icing.dialer.KeystoreHelper import com.icing.dialer.KeystoreHelper
@ -321,12 +323,30 @@ class MainActivity : FlutterActivity() {
val type = it.getInt(it.getColumnIndexOrThrow(CallLog.Calls.TYPE)) val type = it.getInt(it.getColumnIndexOrThrow(CallLog.Calls.TYPE))
val date = it.getLong(it.getColumnIndexOrThrow(CallLog.Calls.DATE)) val date = it.getLong(it.getColumnIndexOrThrow(CallLog.Calls.DATE))
val duration = it.getLong(it.getColumnIndexOrThrow(CallLog.Calls.DURATION)) val duration = it.getLong(it.getColumnIndexOrThrow(CallLog.Calls.DURATION))
// Extract subscription ID (SIM card info) if available
var subscriptionId: Int? = null
var simName: String? = null
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
val subIdColumnIndex = it.getColumnIndex("subscription_id")
if (subIdColumnIndex >= 0) {
subscriptionId = it.getInt(subIdColumnIndex)
// Get the actual SIM name
simName = getSimNameFromSubscriptionId(subscriptionId)
}
}
} catch (e: Exception) {
Log.w(TAG, "Failed to get subscription_id: ${e.message}")
}
val map = mutableMapOf<String, Any?>( val map = mutableMapOf<String, Any?>(
"number" to number, "number" to number,
"type" to type, "type" to type,
"date" to date, "date" to date,
"duration" to duration "duration" to duration,
"subscription_id" to subscriptionId,
"sim_name" to simName
) )
logsList.add(map) logsList.add(map)
} }
@ -334,6 +354,35 @@ class MainActivity : FlutterActivity() {
return logsList return logsList
} }
private fun getSimNameFromSubscriptionId(subscriptionId: Int?): String? {
if (subscriptionId == null) return null
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
val subscriptionManager = getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager
val subscriptionInfo: SubscriptionInfo? = subscriptionManager.getActiveSubscriptionInfo(subscriptionId)
return subscriptionInfo?.let { info ->
// Try to get display name first, fallback to carrier name, then generic name
when {
!info.displayName.isNullOrBlank() && info.displayName.toString() != info.subscriptionId.toString() -> {
info.displayName.toString()
}
!info.carrierName.isNullOrBlank() -> {
info.carrierName.toString()
}
else -> "SIM ${info.simSlotIndex + 1}"
}
}
}
} catch (e: Exception) {
Log.w(TAG, "Failed to get SIM name for subscription $subscriptionId: ${e.message}")
}
// Fallback to generic name
return "SIM ${subscriptionId + 1}"
}
private fun handleIncomingCallIntent(intent: Intent?) { private fun handleIncomingCallIntent(intent: Intent?) {
intent?.let { intent?.let {
if (it.getBooleanExtra("isIncomingCall", false)) { if (it.getBooleanExtra("isIncomingCall", false)) {

View File

@ -19,6 +19,7 @@ class History {
final String callType; // 'incoming' or 'outgoing' final String callType; // 'incoming' or 'outgoing'
final String callStatus; // 'missed' or 'answered' final String callStatus; // 'missed' or 'answered'
final int attempts; final int attempts;
final String? simName; // Name of the SIM used for the call
History( History(
this.contact, this.contact,
@ -26,6 +27,7 @@ class History {
this.callType, this.callType,
this.callStatus, this.callStatus,
this.attempts, this.attempts,
this.simName,
); );
} }
@ -158,6 +160,22 @@ class HistoryPageState extends State<HistoryPage>
return null; return null;
} }
/// Helper: Get SIM name from subscription ID
String? _getSimNameFromSubscriptionId(int? subscriptionId) {
if (subscriptionId == null) return null;
// Map subscription IDs to SIM names
// These values might need to be adjusted based on your device
switch (subscriptionId) {
case 0:
return "SIM 1";
case 1:
return "SIM 2";
default:
return "SIM ${subscriptionId + 1}";
}
}
/// Request permission for reading call logs. /// Request permission for reading call logs.
Future<bool> _requestCallLogPermission() async { Future<bool> _requestCallLogPermission() async {
var status = await Permission.phone.status; var status = await Permission.phone.status;
@ -247,8 +265,22 @@ class HistoryPageState extends State<HistoryPage>
); );
} }
// Extract SIM information if available
String? simName;
if (entry.containsKey('sim_name') && entry['sim_name'] != null) {
simName = entry['sim_name'] as String;
print("DEBUG: Found sim_name: $simName for number: $number"); // Debug print
} else if (entry.containsKey('subscription_id')) {
final subId = entry['subscription_id'];
print("DEBUG: Found subscription_id: $subId for number: $number, but no sim_name"); // Debug print
simName = _getSimNameFromSubscriptionId(subId);
print("DEBUG: Mapped to SIM name: $simName"); // Debug print
} else {
print("DEBUG: No SIM info found for number: $number"); // Debug print
}
callHistories callHistories
.add(History(matchedContact, callDate, callType, callStatus, 1)); .add(History(matchedContact, callDate, callType, callStatus, 1, simName));
// Yield every 10 iterations to avoid blocking the UI. // Yield every 10 iterations to avoid blocking the UI.
if (i % 10 == 0) await Future.delayed(Duration(milliseconds: 1)); if (i % 10 == 0) await Future.delayed(Duration(milliseconds: 1));
} }
@ -345,8 +377,22 @@ class HistoryPageState extends State<HistoryPage>
); );
} }
// Extract SIM information if available
String? simName;
if (entry.containsKey('sim_name') && entry['sim_name'] != null) {
simName = entry['sim_name'] as String;
print("DEBUG: Found sim_name: $simName for number: $number"); // Debug print
} else if (entry.containsKey('subscription_id')) {
final subId = entry['subscription_id'];
print("DEBUG: Found subscription_id: $subId for number: $number, but no sim_name"); // Debug print
simName = _getSimNameFromSubscriptionId(subId);
print("DEBUG: Mapped to SIM name: $simName"); // Debug print
} else {
print("DEBUG: No SIM info found for number: $number"); // Debug print
}
callHistories callHistories
.add(History(matchedContact, callDate, callType, callStatus, 1)); .add(History(matchedContact, callDate, callType, callStatus, 1, simName));
// Yield every 10 iterations to avoid blocking the UI. // Yield every 10 iterations to avoid blocking the UI.
if (i % 10 == 0) await Future.delayed(Duration(milliseconds: 1)); if (i % 10 == 0) await Future.delayed(Duration(milliseconds: 1));
} }
@ -559,9 +605,22 @@ class HistoryPageState extends State<HistoryPage>
_obfuscateService.obfuscateData(contact.displayName), _obfuscateService.obfuscateData(contact.displayName),
style: const TextStyle(color: Colors.white), style: const TextStyle(color: Colors.white),
), ),
subtitle: Text( subtitle: Column(
DateFormat('MMM dd, hh:mm a').format(history.date), crossAxisAlignment: CrossAxisAlignment.start,
style: const TextStyle(color: Colors.grey), children: [
Text(
DateFormat('MMM dd, hh:mm a').format(history.date),
style: const TextStyle(color: Colors.grey),
),
if (history.simName != null)
Text(
history.simName!,
style: const TextStyle(
color: Colors.blue,
fontSize: 12,
),
),
],
), ),
trailing: Row( trailing: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@ -771,6 +830,11 @@ class CallDetailsPage extends StatelessWidget {
label: 'Attempts:', label: 'Attempts:',
value: '${history.attempts}', value: '${history.attempts}',
), ),
if (history.simName != null)
DetailRow(
label: 'SIM Used:',
value: history.simName!,
),
const SizedBox(height: 24), const SizedBox(height: 24),
if (contact.phones.isNotEmpty) if (contact.phones.isNotEmpty)
DetailRow( DetailRow(