How to figure out which SIM received SMS in Dual SIM Android Device
I'm working on a project to sync sms received in a Android phone to a online database. I can get sender's number by calling getOriginatingAddress()
method. But I can't find any solution to figure out which SIM in my device received the sms.
I searched the web about it, but couldn't find a way to figure this out. Is there any way to get SMS receiver's number?
Solution 1:
I had some really hard time with this problem and finally I found a solution, although i tested it only above api level 22.
You have to take a look at the extra information in the received intent. In my case there are two keys in the extra Bundle of the intent which are useful: "slot" and "subscription".
Here is the example:
public class IncomingSms extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
// Retrieves a map of extended data from the intent.
Bundle bundle = intent.getExtras();
int slot = bundle.getInt("slot", -1);
int sub = bundle.getInt("subscription", -1);
/*
Handle the sim info
*/
}
}
I did not find documentation about the keys in the Bundle so this could be device/manufacturer dependent, i can imagine that the keys are different or something like that. You can verify this by dumping the key set of the bundle:
Set<string> keyset = bundle.keySet();
EDIT:
The information about the phone number of the SIM card may not be available at all since if it is not stored on the SIM card it is likely cannot be queried, but all other information will be available through the SubscriptionManager:
SubscriptionManager manager = SubscriptionManager.from(appContext);
SubscriptionInfo = manager.getActiveSubscriptionInfo(sub);
or
SubscriptionInfo = manager.getActiveSubscriptionInfoForSimSlotIndex(slot);
And there are some useful info in the SubscriptionInfo such as the phone number which one is not guaranteed to be available as I explained above.
I also forgot to mention that the Dual-SIM support in stock android was added from api level 22.
Solution 2:
I used Levente Püsök 's answer with a little change. But I did not test on all devices.
try {
Bundle bundle = intent.getExtras();
int slot = -1;
if (bundle != null) {
Set<String> keySet = bundle.keySet();
for(String key:keySet){
switch (key){
case "slot":slot = bundle.getInt("slot", -1);
break;
case "simId":slot = bundle.getInt("simId", -1);
break;
case "simSlot":slot = bundle.getInt("simSlot", -1);
break;
case "slot_id":slot = bundle.getInt("slot_id", -1);
break;
case "simnum":slot = bundle.getInt("simnum", -1);
break;
case "slotId":slot = bundle.getInt("slotId", -1);
break;
case "slotIdx":slot = bundle.getInt("slotIdx", -1);
break;
default:
if(key.toLowerCase().contains("slot")|key.toLowerCase().contains("sim")){
String value = bundle.getString(key, "-1");
if(value.equals("0")|value.equals("1")|value.equals("2")){
slot = bundle.getInt(key, -1);
}
}
}
}
Log.d("slot", "slot=>"+slot);
}
}catch (Exception e){
Log.d(TAG, "Exception=>"+e);
}
Solution 3:
I achieved a very good result by combining the answers and updating
private String detectSim(Bundle bundle) {
int slot = -1;
Set<String> keySet = bundle.keySet();
for (String key : keySet)
{
switch (key) {
case "phone":
slot = bundle.getInt("phone", -1);
break;
case "slot":
slot = bundle.getInt("slot", -1);
break;
case "simId":
slot = bundle.getInt("simId", -1);
break;
case "simSlot":
slot = bundle.getInt("simSlot", -1);
break;
case "slot_id":
slot = bundle.getInt("slot_id", -1);
break;
case "simnum":
slot = bundle.getInt("simnum", -1);
break;
case "slotId":
slot = bundle.getInt("slotId", -1);
break;
case "slotIdx":
slot = bundle.getInt("slotIdx", -1);
break;
default:
if (key.toLowerCase().contains("slot") | key.toLowerCase().contains("sim")) {
String value = bundle.getString(key, "-1");
if (value.equals("0") | value.equals("1") | value.equals("2")) {
slot = bundle.getInt(key, -1);
}
}
}
}
Log.d("KKK",String.valueOf(slot));
if (slot==0)
{
return "sim1";
}
else if (slot==1)
{
return "sim2";
}
else
{
return "undetected";
}
}