androidkotlincallcalllog

Identify Call logs from Sim1 and Sim2


I'm trying to show call logs from Sim1 and Sim2 separately. I'm getting all call logs, but not able to differentiate it whether it is from Sim1 or Sim2. I have tried below code,

 val managedCursor = activity?.contentResolver?.query(CallLog.Calls.CONTENT_URI, null, null,
        null, null)
    managedCursor?.let {
      val number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER)
      val name = managedCursor.getColumnIndex(CallLog.Calls.CACHED_NAME)
      val type = managedCursor.getColumnIndex(CallLog.Calls.TYPE)
      val date = managedCursor.getColumnIndex(CallLog.Calls.DATE)
      val duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION)
      val simType = managedCursor.getColumnIndex(CallLog.Calls.PHONE_ACCOUNT_ID)
      sb.append("Call Details :")
      while (managedCursor.moveToNext()) {
        val phNumber = managedCursor.getString(number)
        val displayName = managedCursor.getString(name)
        val callType = managedCursor.getString(type)
        val callDate = managedCursor.getString(date)
        val callDayTime = Date(callDate.toLong())
        val callDuration = managedCursor.getString(duration)
        var dir: String = "";
        val dircode = Integer.parseInt(callType)
        val simTypes = managedCursor.getString(simType)
        when (dircode) {
          CallLog.Calls.OUTGOING_TYPE -> dir = "OUTGOING"
          CallLog.Calls.INCOMING_TYPE -> dir = "INCOMING"
          CallLog.Calls.MISSED_TYPE -> dir = "MISSED"
        }
      }
      managedCursor.close()
    }

I have read documents showing PHONE_ACCOUNT_ID may help to identify it. But it's giving different numbers in different phones.

I have also read many SO questions as well, but not able to find any solution.

like: 1) How to get SIM1 or SIM2 from call logs programatically 2) how to get call log for sim1, sim2 seperatly from an android activity?

Any help will be appreciated, thanks.


Solution

  • To start off you mentioned that you are getting different numbers in different phones for the field PHONE_ACCOUNT_ID which is absolutely correct.

    But you don't need to worry about that and it should not bother you.

    So Why there are different values for the PHONE_ACCOUNT_ID?

    Well, subscription_id i.e PHONE_ACCOUNT_ID will be unique for each sim card on your device. To clear suppose say you have two sim cards on your device then scenario will be like this

    Now suppose you remove one sim says Sim 1 and enter a new sim which is never inserted on the device before, let's call it as Sim 3. Then this sim will be having subscription_id as 3, not in 1 or 2

    Similarly when you insert a 4th sim on the device which is not inserted before it's id will be something other than 1,2,3 But if you insert Sim 1 again it will be having subscription_id as 1 just as before

    Note: It's not necessary for subscription_id's to appear in sequential order they can be anything even more than 2 digits

    Now coming to accessing the actual contacts logs related to the sim's present currently on the device is to be done. But the logs can also have the logs related to other sims i.e old sims let's call them old logs. So we need to get the current simid for the current sim's you can do it like this

    Create A Class Called CallHistory

    data class CallHistory(var number:String,
                           var name:String?,
                           var type:Int,
                           var date:Long,
                           var duration: Long,
                           var subscriberId:String) {
    
        val cachedName:String  // Separate property for cachedName
            get() {
          return  if(name==null) number else name as String
        }
    
    }
    

    Then Write this function to get the active sim card info

        /**
         * This Function Will return list of SubscriptionInfo
         */
        private fun getSimCardInfos() : List<SubscriptionInfo>?{
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
                val subscriptionManager: SubscriptionManager = getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager
                if (ActivityCompat.checkSelfPermission(
                        this,
                        Manifest.permission.READ_PHONE_STATE
                    ) != PackageManager.PERMISSION_GRANTED
                ) {
                    throw Exception("Permission Not Granted -> Manifest.permission.READ_PHONE_STATE")
                }
                return subscriptionManager.activeSubscriptionInfoList
            }else{
                return null
            }
        }
    

    Write this function to get all call logs

     // This function will return the all Call History
        fun getAllCallHistory() : MutableList<CallHistory>{
    
            val managedCursor = if (ActivityCompat.checkSelfPermission(
                    this,
                    Manifest.permission.READ_CALL_LOG
                ) != PackageManager.PERMISSION_GRANTED
            ) {
               throw Exception("Permission Not Granted -> Manifest.permission.READ_CALL_LOG")
            }else{
                this.contentResolver?.query(
                    CallLog.Calls.CONTENT_URI, null, null,
                    null, null)
            }
    
            managedCursor?.let {
                val callHistoryList= mutableListOf<CallHistory>()
                while (it.moveToNext())
                {
                    callHistoryList.add(CallHistory(number = it.getString(it.getColumnIndex(CallLog.Calls.NUMBER)),
                        name = it.getString(it.getColumnIndex(CallLog.Calls.CACHED_NAME))?:null,
                        type = it.getString(it.getColumnIndex(CallLog.Calls.TYPE)).toInt(),
                        date = it.getString(it.getColumnIndex(CallLog.Calls.DATE)).toLong(),
                        duration = it.getString(it.getColumnIndex(CallLog.Calls.DURATION)).toLong(),
                        subscriberId = it.getString(it.getColumnIndex(CallLog.Calls.PHONE_ACCOUNT_ID)))
                    )
    
                 }
                it.close()
                return callHistoryList
            }
    
            return mutableListOf<CallHistory>()
    
        }
    

    Now we need to separate call logs based on the subscription_id's i.e PHONE_ACCOUNT_ID but there is a problem with this i.e some device store sim ICCID [ It's a 19-20 digit code which is unique for each sim] in PHONE_ACCOUNT_ID but some devices store The actual subscription id which is 1 or 2 digit only. So we need to check whether the subscription_id is equal to original sim subscription_id or it is equal to iccid

    Write this function to get Call Logs of only selected sim

    fun getCallHistoryOfSim(simInfo:SubscriptionInfo?, allCallList:MutableList<CallHistory> ) : MutableList<CallHistory> {
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1){
           return allCallList.filter { it.subscriberId==simInfo?.subscriptionId.toString() || it.subscriberId.contains(simInfo?.iccId?:"_")}.toMutableList()
        }else{
            throw Exception("This Feature Is Not Available On This Device")
        }
    
    }
    

    So the above function gives logs of the selected sim only

    you can call the functions the above functions and get the list. An example call is like this

           for(log in getCallHistoryOfSim( getSimCardInfos()?.get(0),getAllCallHistory()) )
            {
                Log.d("Sim1LogDetails", "$log\n____________________________________")
            }
    
            for(log in getCallHistoryOfSim( getSimCardInfos()?.get(1),getAllCallHistory()) )
            {
                Log.d("Sim2LogDetails", "$log\n____________________________________")
    
            }
    

    In order to get this code get work you need to specify 2 permissions

    <uses-permission android:name="android.permission.READ_CALL_LOG" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    And App Should Target API level 22

    It's Quite a long answer hope you got what It does. If any doubts let me know