20

我有一部带有 2 张 SIM 卡的 Android 手机,我想使用 Sim1 或 Sim2 发送短信。默认情况下,消息是从 sim1 发送的。但我想从 sim2 发送短信。是否可以设置使用 Sim1 或 Sim2 发送短信?

如果有使用 Sim1 或 Sim2 发送短信的设置选项,那就太好了。这对双 SIM 安卓手机很有用。我创建了短信应用程序 android 我已经能够顺利发送短信应用程序,但默认短信由 SIM 1 发送。但我想通过设置通过 sim1 或 sim2 发送短信以编程方式发送短信?

4

6 回答 6

17

如果您可以将此代码用于 API 级别 22+。

private void sendDirectSMS() {

    private static String SENT = "SMS_SENT", DELIVERED = "SMS_DELIVERED";

    PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, new Intent(
        SENT), 0);

    PendingIntent deliveredPI = PendingIntent.getBroadcast(this, 0,
        new Intent(DELIVERED), 0);

    // SEND BroadcastReceiver
    BroadcastReceiver sendSMS = new BroadcastReceiver() {
        @Override
        public void onReceive(Context arg0, Intent arg1) {
            switch (getResultCode()) {
                case Activity.RESULT_OK:
                    showSnackBar(getString(R.string.sms_sent));
                    Analytics.track(AnalyticsEvents.SEND_REMINDER_SMS_APP_SUCCESS);
                    break;
                case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
                    showSnackBar(getString(R.string.sms_send_failed_try_again));
                    Analytics.track(AnalyticsEvents.SEND_REMINDER_SMS_APP_FAILED);
                    break;
                case SmsManager.RESULT_ERROR_NO_SERVICE:
                    showSnackBar(getString(R.string.no_service_sms_failed));
                    Analytics.track(AnalyticsEvents.SEND_REMINDER_SMS_APP_FAILED);
                    break;
                case SmsManager.RESULT_ERROR_NULL_PDU:
                    showSnackBar(getString(R.string.no_service_sms_failed));
                    Analytics.track(AnalyticsEvents.SEND_REMINDER_SMS_APP_FAILED);
                    break;
                case SmsManager.RESULT_ERROR_RADIO_OFF:
                    showSnackBar(getString(R.string.no_service_sms_failed));
                    Analytics.track(AnalyticsEvents.SEND_REMINDER_SMS_APP_FAILED);
                    break;
            }
        }
    };

    // DELIVERY BroadcastReceiver
    BroadcastReceiver deliverSMS = new BroadcastReceiver() {
        @Override
        public void onReceive(Context arg0, Intent arg1) {
            switch (getResultCode()) {
                case Activity.RESULT_OK:
                    Toast.makeText(getBaseContext(), R.string.sms_delivered,
                        Toast.LENGTH_SHORT).show();
                    break;
                case Activity.RESULT_CANCELED:
                    Toast.makeText(getBaseContext(), R.string.sms_not_delivered,
                        Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    };

    registerReceiver(sendSMS, new IntentFilter(SENT));
    registerReceiver(deliverSMS, new IntentFilter(DELIVERED));
    String smsText = getSmsText();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
        SubscriptionManager localSubscriptionManager = SubscriptionManager.from(context);
        if (localSubscriptionManager.getActiveSubscriptionInfoCount() > 1) {
            List localList = localSubscriptionManager.getActiveSubscriptionInfoList();

            SubscriptionInfo simInfo1 = (SubscriptionInfo) localList.get(0);
            SubscriptionInfo simInfo2 = (SubscriptionInfo) localList.get(1);

            //SendSMS From SIM One
            SmsManager.getSmsManagerForSubscriptionId(simInfo1.getSubscriptionId()).sendTextMessage(customer.getMobile(), null, smsText, sentPI, deliveredPI);

            //SendSMS From SIM Two
            SmsManager.getSmsManagerForSubscriptionId(simInfo2.getSubscriptionId()).sendTextMessage(customer.getMobile(), null, smsText, sentPI, deliveredPI);
        }
    } else {
        SmsManager.getDefault().sendTextMessage(customer.getMobile(), null, smsText, sentPI, deliveredPI);
        Toast.makeText(getBaseContext(), R.string.sms_sending, Toast.LENGTH_SHORT).show();
    }
}

还要添加权限。

<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
于 2018-07-17T11:30:24.820 回答
8
SmsManager.getSmsManagerForSubscriptionId(int subscriptionId).sendTextMessage(String destinationAddress, String scAddress, String text,PendingIntent sentIntent, PendingIntent deliveryIntent);

这可以在 5.1 Lollipop 版本之后工作。在此之前我们需要看到更多。一旦我得到答案,我会更新。

于 2017-08-01T10:29:43.900 回答
0

您应该查看 tasker,您将能够使用它来为此构建一个切换小部件。

于 2014-05-09T05:15:27.843 回答
0

这是一个完整的示例,展示了如何选择一个,并在带有 2 个 sim 卡的真实设备 (OnePlus 2) 上进行了测试。请注意,您应该处理权限(在使用代码之前授予它们):

显现

    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!--    <uses-permission android:name="android.permission.READ_SMS" />-->
<!--    <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />-->

构建.gradle

        minSdkVersion 21
        targetSdkVersion 29
...
    implementation "com.google.android.gms:play-services-auth:17.0.0"

activity_main.xml

<Button xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    tools:text="send sms" />

MainActivity.kt


import android.annotation.SuppressLint
import android.app.Activity
import android.app.PendingIntent
import android.content.*
import android.os.Build
import android.os.Bundle
import android.telephony.SmsManager
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import android.util.Log
import android.util.LongSparseArray
import android.view.View
import android.view.autofill.AutofillManager
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.gms.auth.api.Auth
import com.google.android.gms.auth.api.credentials.Credential
import com.google.android.gms.auth.api.credentials.HintRequest
import com.google.android.gms.common.api.GoogleApiClient
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
    private lateinit var googleApiClient: GoogleApiClient
    private val partialSmsIdToSmsReceiverMap = LongSparseArray<SmsBroadcastReceiver>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        button.visibility = View.GONE
        tryGetCurrentUserPhoneNumber(this)
        googleApiClient = GoogleApiClient.Builder(this).addApi(Auth.CREDENTIALS_API).build()
        if (phoneNumberToSendTo.isEmpty()) {
            val hintRequest = HintRequest.Builder().setPhoneNumberIdentifierSupported(true).build()
            val intent = Auth.CredentialsApi.getHintPickerIntent(googleApiClient, hintRequest)
            try {
                startIntentSenderForResult(intent.intentSender, REQUEST_PHONE_NUMBER, null, 0, 0, 0);
            } catch (e: IntentSender.SendIntentException) {
                Toast.makeText(this, "failed to show phone picker", Toast.LENGTH_SHORT).show()
            }
        } else
            onGotPhoneNumberToSendTo(phoneNumberToSendTo)

    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_PHONE_NUMBER) {
            if (resultCode == Activity.RESULT_OK) {
                val cred: Credential? = data?.getParcelableExtra(Credential.EXTRA_KEY)
                phoneNumberToSendTo = cred?.id ?: ""
                if (phoneNumberToSendTo.isEmpty())
                    Toast.makeText(this, "failed to get phone number", Toast.LENGTH_SHORT).show()
                else
                    onGotPhoneNumberToSendTo(phoneNumberToSendTo)
            }
        }
    }

    private fun onGotPhoneNumberToSendTo(normalizedPhoneNumberToSendSmsTo: String) {
        button.visibility = View.VISIBLE
        button.text = "send SMS to $normalizedPhoneNumberToSendSmsTo"
        button.setOnClickListener {
            val smsManager = SmsManager.getDefault()
            val messageToSend = "Hello there"
            val parts = smsManager.divideMessage(messageToSend)
            val sentIntents = ArrayList<PendingIntent>(parts.size)
            val fullSmsMessageId = fullSmsIdCounter++
            Log.d("AppLog", " sendSmsMessage sending sms #$fullSmsMessageId parts count:${parts.size} messageToSend:\n$messageToSend")
            val pendingPartialSmsIds = HashSet<Long>()
            for (i in 0 until parts.size) {
                val partialSmsId = partialSmsIdCounter++
                Log.d("AppLog", " sendSmsMessage sending sms #$fullSmsMessageId part id:${partialSmsId}")
                val action = "$ACTION_SMS_SENT_FORMAT$partialSmsId"
                sentIntents.add(PendingIntent.getBroadcast(applicationContext, 0, Intent(action), 0))
                val smsSentBroadcastReceiver = SmsBroadcastReceiver(fullSmsMessageId, partialSmsId)
                partialSmsIdToSmsReceiverMap.put(partialSmsId, smsSentBroadcastReceiver)
                applicationContext.registerReceiver(smsSentBroadcastReceiver, IntentFilter(action))
                pendingPartialSmsIds.add(partialSmsId)
            }
            sendSmsUsingDefaultSimCard(applicationContext, normalizedPhoneNumberToSendSmsTo, parts, sentIntents)
        }
    }

    @SuppressLint("NewApi", "MissingPermission")
    fun sendSmsUsingDefaultSimCard(applicationContext: Context, destinationAddress: String, parts: ArrayList<String>,
                                   sentIntents: ArrayList<PendingIntent>? = null, deliveryIntents: ArrayList<PendingIntent>? = null) {
        val defaultSmsManager = SmsManager.getDefault()
        val phoneNumber = if (destinationAddress.startsWith("+")) destinationAddress else "+$destinationAddress"
        //check if we have multi-SIM and don't have a default one to work with, so that we will choose it ourselves
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
            defaultSmsManager.sendMultipartTextMessage(phoneNumber, null, parts, sentIntents, deliveryIntents)
            return
        }
        val subscriptionManager = applicationContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager
        val defaultSubscriptionId = SmsManager.getDefaultSmsSubscriptionId()
        val smsManager = SmsManager.getSmsManagerForSubscriptionId(defaultSubscriptionId)
        if (smsManager != null) {
            smsManager.sendMultipartTextMessage(phoneNumber, null, parts, sentIntents, deliveryIntents)
            return
        }
        val activeSubscriptionInfoList: MutableList<SubscriptionInfo>? = subscriptionManager.activeSubscriptionInfoList
        val subscriptionInfoId = activeSubscriptionInfoList?.getOrNull(0)?.subscriptionId
        if (subscriptionInfoId != null)
            SmsManager.getSmsManagerForSubscriptionId(subscriptionInfoId).sendMultipartTextMessage(phoneNumber, null, parts, sentIntents, deliveryIntents)
        else
            defaultSmsManager.sendMultipartTextMessage(phoneNumber, null, parts, sentIntents, deliveryIntents)
    }

    private inner class SmsBroadcastReceiver(val fullSmsId: Long, val partialSmsId: Long) : BroadcastReceiver() {
        override fun onReceive(someContext: Context, intent: Intent) {
            Log.d("AppLog", " SmsBroadcastReceiver onReceive")
            applicationContext.unregisterReceiver(this)
            partialSmsIdToSmsReceiverMap.remove(partialSmsId)
            val smsError: String? = when (resultCode) {
                -1, 0 /*SmsManager.RESULT_ERROR_NONE*/ -> null
                SmsManager.RESULT_ERROR_GENERIC_FAILURE -> "RESULT_ERROR_GENERIC_FAILURE"
                SmsManager.RESULT_ERROR_RADIO_OFF -> "RESULT_ERROR_RADIO_OFF"
                SmsManager.RESULT_ERROR_NULL_PDU -> "RESULT_ERROR_NULL_PDU"
                SmsManager.RESULT_ERROR_NO_SERVICE -> "RESULT_ERROR_NO_SERVICE"
                SmsManager.RESULT_ERROR_LIMIT_EXCEEDED -> "RESULT_ERROR_LIMIT_EXCEEDED"
                SmsManager.RESULT_ERROR_SHORT_CODE_NOT_ALLOWED -> "RESULT_ERROR_SHORT_CODE_NOT_ALLOWED"
                SmsManager.RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED -> "RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED"
                /**SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE*/
                6 -> "RESULT_ERROR_FDN_CHECK_FAILURE"
//                16 /*SmsManager.RESULT_MODEM_ERROR*/ -> "RESULT_MODEM_ERROR"
//                111 /*SmsManager.RESULT_RIL_MODEM_ERR*/ -> "RESULT_RIL_MODEM_ERR"
                else -> "Unknown error"
            }
            Log.d("AppLog", "SmsBroadcastReceiver sms #$fullSmsId part #$partialSmsId send-state updated. sent fine?${smsError == null} (error:$smsError) errorCode:$resultCode")
        }
    }

    companion object {
        private const val REQUEST_PHONE_NUMBER = 1
        private var partialSmsIdCounter = 0L
        private var fullSmsIdCounter = 0L
        private const val ACTION_SMS_SENT_FORMAT = "_ACTION_SENT_"
        private var phoneNumberToSendTo = ""

        @SuppressLint("MissingPermission", "HardwareIds")
        private fun tryGetCurrentUserPhoneNumber(context: Context): String {
            if (phoneNumberToSendTo.isNotEmpty())
                return phoneNumberToSendTo
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                val subscriptionManager = context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager
                try {
                    subscriptionManager.activeSubscriptionInfoList?.forEach {
                        val number: String? = it.number
                        if (!number.isNullOrBlank()) {
                            phoneNumberToSendTo = number
                            return number
                        }
                    }
                } catch (ignored: Exception) {
                }
            }
            try {
                val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
                val number = telephonyManager.line1Number ?: ""
                if (!number.isBlank()) {
                    phoneNumberToSendTo = number
                    return number
                }
            } catch (e: Exception) {
            }
            return ""
        }
    }
}


于 2020-02-26T09:45:33.477 回答
-1

没有 android.permission.READ_PHONE_STATE 的解决方案

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
        SubscriptionManager subs = (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
        if (subs != null) {
            Log.d("sim_spalsh", "num sims = " + subs.getActiveSubscriptionInfoCountMax());

            if (subs.getActiveSubscriptionInfoCountMax() > 1) {

                //SendSMS From SIM One
                SmsManager.getSmsManagerForSubscriptionId(0)
                        .sendTextMessage(phonenumber, null, "sim1", null, null);

                //SendSMS From SIM Two
                SmsManager.getSmsManagerForSubscriptionId(1)
                        .sendTextMessage(phonenumber, null, "sim2", null, null);

            }
        }
    }

您必须保证<uses-permission android:name="android.permission.SEND_SMS"/>

于 2020-01-31T17:26:49.253 回答
-4

该选项在 Android 设置中可用 - 导航至设置>>无线和网络>>SIM 管理>>默认设置>>消息>>并选择“总是询问”。

于 2014-11-24T09:34:23.883 回答