如何找出哪个SIM卡收到短信在双卡Android设备

64jmpszr  于 2022-11-03  发布在  Android
关注(0)|答案(8)|浏览(327)

我正在做一个项目,将Android手机收到的短信同步到在线数据库。我可以通过调用getOriginatingAddress()方法获得发送者的号码。但我找不到任何解决方案来找出我设备中的哪张SIM卡收到了短信。
我在网上搜索了一下,但是没有找到一个方法来解决这个问题。有没有办法得到短信接收者的号码?

d6kp6zgx

d6kp6zgx1#

我有一些真的很难与这个问题,最后我找到了一个解决方案,虽然我测试它只高于api级22。
您必须查看接收到的Intent中的额外信息。在我的例子中,Intent的额外Bundle中有两个键非常有用:“插槽”和“订阅”。
下面是一个示例:

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
                */
            }
}

我没有找到关于捆绑包中密钥的文档,因此这可能与设备/制造商有关,我可以想象密钥是不同的或类似的。您可以通过转储捆绑包的密钥集来验证这一点:

Set<string> keyset = bundle.keySet();

编辑:

有关SIM卡电话号码的信息可能根本不可用,因为如果它没有存储在SIM卡上,则很可能无法查询,但所有其他信息将通过SubscriptionManager提供:

SubscriptionManager manager = SubscriptionManager.from(appContext);
SubscriptionInfo = manager.getActiveSubscriptionInfo(sub);

SubscriptionInfo = manager.getActiveSubscriptionInfoForSimSlotIndex(slot);

而且在SubscriptionInfo中有一些有用的信息,比如电话号码,正如我上面解释的,哪一个不能保证可用。
我还忘了提一下,股票Android中的双SIM卡支持是从API级别22添加的。

ckocjqey

ckocjqey2#

我使用了Levente Püsök的答案,做了一点改动。但是我没有在所有设备上测试。

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);
 }
zysjyyx4

zysjyyx43#

通过将答案和更新相结合,我取得了非常好的结果

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";
    }
}
ccgok5k5

ccgok5k54#

这个对我很好用,试试可能会对你有帮助

if (bundle != null) {
            int slot = -1;
            Set<String> keySet = bundle.keySet();
            for(String key:keySet){
                if(key.equals("phone")){slot = bundle.getInt("phone", -1);}//in api 29
                else if(key.equals("slot")){slot = bundle.getInt("slot", -1);}
                else if(key.equals("slotId")){slot = bundle.getInt("slotId", -1);}
                else if(key.equals("slot_id")){slot = bundle.getInt("slot_id", -1);}
                else if(key.equals("slotIdx")){slot = bundle.getInt("slotIdx", -1);}
                else if(key.equals("simId")){slot = bundle.getInt("simId", -1);}
                else if(key.equals("simSlot")){slot = bundle.getInt("simSlot", -1);}
                else if(key.equals("simnum")){slot = bundle.getInt("simnum", -1);}
            }
            System.out.println("  The sim no is >>>  "+slot);

            //or get subscription and do next

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
                int sub = bundle.getInt("subscription", -1);
                SubscriptionManager manager = SubscriptionManager.from(context);
                SubscriptionInfo subnfo = manager.getActiveSubscriptionInfo(sub);//this requires READ_PHONE_STATE permission
                System.out.println(
                        "\n The sim no is >>>  "+subnfo.getSimSlotIndex()
                        //or subnfo.getCardId()
                        +"\n The sim no is >>>  "+subnfo.getCardId()//this requires api 29 and +++
                        //some infos may you need it
                        +"\n Phone No is >>>  "+subnfo.getNumber()//not guaranteed to be available
                        +"\n carrier Name is >>>  "+subnfo.getCarrierName()//the operator name
                        +"\n carrier display Name is >>>  "+subnfo.getDisplayName()//that you typed in dual sim settings
                );
            }

        }
tktrz96b

tktrz96b5#

在Kotlin中,使用SubscriptionManager额外字符串:

private var simSlotIndexLastSms = -100

private val subscriptionManager by lazy { getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager }

private val smsReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        intent ?: return

        try {
            val slotIndex: Int = when {
                isAndroid11Plus() -> {
                    intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX, -100)
                }
                else -> {
                    val subscriptionId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, -100)
                    if (!hasPhonePermission()) {
                        -100
                    } else {
                        subscriptionManager
                            .activeSubscriptionInfoList
                            ?.find { it.subscriptionId == subscriptionId }
                            ?.simSlotIndex ?: -100
                    }
                }
            }

            simSlotIndexLastSms = if (slotIndex != -100) slotIndex.plus(1) else slotIndex // make it 1-index instead of 0-indexed so corresponds with physical slots 1 and 2

        } catch (e: Exception) {
            Timber.e(e, "Error while getting SIM slot index for incoming SMS")
        }
    }
}

private fun registerSmsReceiver() {
    val intentFilter = IntentFilter().apply {
        addAction(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)
        priority = 500
    }

    registerReceiver(smsReceiver, intentFilter)
}

要调用smsReceiver,您需要向用户请求运行时“android.permission.RECEIVE_SMS”权限。要访问订阅列表,还需要READ_PHONE_STATE和READ_PHONE_NUMBERS(仅适用于Android 12及更高版本)。
在Android 10、11和12(三星、Pixel和小米设备)上进行了测试。

fjaof16o

fjaof16o6#

mahmood-karimizade解决方案非常好,它对我很有帮助。但是我发现了一些额外的密钥,它们也可以包含sim卡插槽值,这是在我的Google Pixel 4a上(Android 13)所以我认为它会成为主流。键android.telephony.extra.SLOT_INDEX也包含sim插槽索引。另一件事是sim插槽索引似乎总是int值,因此我还更新了switch表达式中的default条件,以使用bundle.getInt函数而不是bundle.getString

private int 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;
            case "android.telephony.extra.SLOT_INDEX": 
                // Present on Pixel 4a with physical sim + eSIM configuration
                slot = bundle.getInt("android.telephony.extra.SLOT_INDEX", -1);
                break;
            default:
                try {
                    if (key.toLowerCase().contains("slot") || key.toLowerCase().contains("sim")) {
                        int value = bundle.getInt(key, -1);
                        if (value == 0 || value == 1) {
                            slot = value;
                        }
                    }
                } catch(Error e) {}
        }
    }

    return slot;
}
pcrecxhr

pcrecxhr7#

Kotlin溶液

此代码不显示任何警告

private fun detectSim(bundle: Bundle): Int {
    var slot = -1
    try {
        val keySet = bundle.keySet()
        for (key in keySet) {
            when (key) {
                "slot" -> slot = bundle.getInt("slot", -1)
                "simId" -> slot = bundle.getInt("simId", -1)
                "simSlot" -> slot = bundle.getInt("simSlot", -1)
                "slot_id" -> slot = bundle.getInt("slot_id", -1)
                "simnum" -> slot = bundle.getInt("simnum", -1)
                "slotId" -> slot = bundle.getInt("slotId", -1)
                "slotIdx" -> slot = bundle.getInt("slotIdx", -1)
                else -> if (key.lowercase(Locale.getDefault())
                        .contains("slot") or key.lowercase(
                        Locale.getDefault()
                    ).contains("sim")
                ) {
                    val value = bundle.get(key).toString()
                    if ((value == "0") or (value == "1") or (value == "2")) {
                        slot = bundle.getInt(key, -1)
                    }
                }
            }
        }
        Log.d("slot", "slot=>$slot")
    } catch (e: java.lang.Exception) {
        Log.d(TAG, "Exception=>$e")
    }
    return slot
}
7eumitmz

7eumitmz8#

SMS具有thread_id字段,可能对于参与者集合是唯一的。可能对于同一发送者和两个西姆斯是不同的,并且至少有助于区分。

相关问题