I use a broadcast receiver to intercept calls coming to the phone and send them and then process them. I need to receive calls only from a certain SIM card in a two-key phone. I can try to do it like this
override fun onReceive(context: Context, intent: Intent) {
if (intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
try {
val number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER)
intent.extras
if (number != null) {
val now = Date()
val state = intent.getStringExtra(TelephonyManager.EXTRA_STATE)
Log.d(TAG, "stateName: $state number: $number")
Handler(Looper.getMainLooper()).postDelayed({
val c: Cursor? = context.contentResolver.query(
CallLog.Calls.CONTENT_URI,
null,
null,
null,
CallLog.Calls.DATE + " DESC"
)
var duration: Int? = null
var id: Int? = null
var num: String? = null
var type: Int = -100
var date: Date? = null
var iccId: String = ""
if (c?.columnCount?:0 > 0) {
c?.moveToFirst()
num = c?.getString(c.getColumnIndex(CallLog.Calls.NUMBER))
duration = c?.getInt(c.getColumnIndex(CallLog.Calls.DURATION))
type = (c?.getString(c.getColumnIndex(CallLog.Calls.TYPE)) ?: "-100").toInt()
iccId = c?.getString(c.getColumnIndex(CallLog.Calls.PHONE_ACCOUNT_ID))?:""
id = c?.getInt(c.getColumnIndex(CallLog.Calls._ID))
date = c?.getLong(c.getColumnIndex(CallLog.Calls.DATE))?.let { Date(it) }
}
c?.close()
if (id != null && number.equals(num, true)
&& duration != null && date != null
&& abs(now.time - duration - date.time) < 5_000) {
id = null
date = null
duration = null
iccId = ""
}
if (!SettingsStore(context).findEnabledFilters().contains(iccId)) {
sendToHandlers(context, number, state, duration, id, date)
}
}, 1_500)
}
} catch (e: Exception) {
CrashMonitor.trackWarning(e.message, e.stackTraceToString())
e.printStackTrace()
}
}
}
I'm trying to filter calls by iccId, but I always get in intent from receiver the iccId of the PREVIOUS telephony status. Is there a way to somehow get the current iccID of the call, or perhaps there is another more correct and working way to get information only about calls to a specific SIM card?
I went the other way and started using a custom PhoneStateListener, creating inside broadcast receiver a telephonymanager subscription by the subscription id of the desired SIM card in the desired slot.
Below is a slightly unfinished, but already working implementation example
BroadcastReceiver
class CallReceiver : BroadcastReceiver() {
private val TAG = this::class.java.simpleName
var telephony: TelephonyManager? = null
@SuppressLint("Range", "UnsafeProtectedBroadcastReceiver")
override fun onReceive(context: Context, intent: Intent) {
val number: String?
if (intent.action.equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
try {
number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER)
intent.extras
if (number != null) {
val phoneListener = MyPhoneStateListener(context, number)
telephony = context
.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
val sm =
context.getSystemService(TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.READ_PHONE_STATE
) != PackageManager.PERMISSION_GRANTED
) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
return
}
val mSim0TelephonyManager = telephony!!.createForSubscriptionId(1)
mSim0TelephonyManager!!.listen(
phoneListener,
PhoneStateListener.LISTEN_CALL_STATE
)
}
} catch (e: Exception) {
}
}
}
fun onDestroy() {
telephony!!.listen(null, PhoneStateListener.LISTEN_NONE)
}
}
PhoneStateListener
class MyPhoneStateListener(val context: Context, var number: String?) : PhoneStateListener() {
private var stateName = ""
override fun onCallStateChanged(state: Int, incomingNumber: String) {
when (state) {
TelephonyManager.CALL_STATE_IDLE -> {
Log.d("DEBUG", "IDLE")
phoneRinging = false
stateName = "IDLE"
}
TelephonyManager.CALL_STATE_OFFHOOK -> {
Log.d("DEBUG", "OFFHOOK")
phoneRinging = false
stateName = "OFFHOOK"
}
TelephonyManager.CALL_STATE_RINGING -> {
Log.d("DEBUG", "RINGING")
phoneRinging = true
stateName = "RINGING"
}
}
number?.let { hand(context = context, number = it, duration = 1, id=10, state = stateName ) }
}
companion object {
var phoneRinging = false
}
}