feat: add SIM name handling to call history and display in UI
Some checks failed
/ mirror (push) Failing after 4s
/ build (push) Successful in 10m32s
/ build-stealth (push) Successful in 10m33s

This commit is contained in:
AlexisDanlos 2025-06-27 15:33:13 +02:00
parent c9ebd7b92f
commit 9d4fefe8ff
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.provider.CallLog
import android.telecom.TelecomManager
import android.telephony.SubscriptionManager
import android.telephony.SubscriptionInfo
import android.util.Log
import androidx.core.content.ContextCompat
import com.icing.dialer.KeystoreHelper
@ -321,12 +323,30 @@ class MainActivity : FlutterActivity() {
val type = it.getInt(it.getColumnIndexOrThrow(CallLog.Calls.TYPE))
val date = it.getLong(it.getColumnIndexOrThrow(CallLog.Calls.DATE))
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?>(
"number" to number,
"type" to type,
"date" to date,
"duration" to duration
"duration" to duration,
"subscription_id" to subscriptionId,
"sim_name" to simName
)
logsList.add(map)
}
@ -334,6 +354,35 @@ class MainActivity : FlutterActivity() {
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?) {
intent?.let {
if (it.getBooleanExtra("isIncomingCall", false)) {

View File

@ -19,6 +19,7 @@ class History {
final String callType; // 'incoming' or 'outgoing'
final String callStatus; // 'missed' or 'answered'
final int attempts;
final String? simName; // Name of the SIM used for the call
History(
this.contact,
@ -26,6 +27,7 @@ class History {
this.callType,
this.callStatus,
this.attempts,
this.simName,
);
}
@ -158,6 +160,22 @@ class HistoryPageState extends State<HistoryPage>
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.
Future<bool> _requestCallLogPermission() async {
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
.add(History(matchedContact, callDate, callType, callStatus, 1));
.add(History(matchedContact, callDate, callType, callStatus, 1, simName));
// Yield every 10 iterations to avoid blocking the UI.
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
.add(History(matchedContact, callDate, callType, callStatus, 1));
.add(History(matchedContact, callDate, callType, callStatus, 1, simName));
// Yield every 10 iterations to avoid blocking the UI.
if (i % 10 == 0) await Future.delayed(Duration(milliseconds: 1));
}
@ -559,9 +605,22 @@ class HistoryPageState extends State<HistoryPage>
_obfuscateService.obfuscateData(contact.displayName),
style: const TextStyle(color: Colors.white),
),
subtitle: Text(
DateFormat('MMM dd, hh:mm a').format(history.date),
style: const TextStyle(color: Colors.grey),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
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(
mainAxisSize: MainAxisSize.min,
@ -771,6 +830,11 @@ class CallDetailsPage extends StatelessWidget {
label: 'Attempts:',
value: '${history.attempts}',
),
if (history.simName != null)
DetailRow(
label: 'SIM Used:',
value: history.simName!,
),
const SizedBox(height: 24),
if (contact.phones.isNotEmpty)
DetailRow(