web-dev-qa-db-ja.com

プログラムでSim1またはSim2を使用してSMSを送信するオプション

私はAndroid電話を使用しており、Sim1またはSim2を使用してSMSを送信したいと考えています。デフォルトでは、メッセージはSim1から送信されます。ただし、Sim2からSMSを送信したいのですが、可能ですか? Sim1またはSim2を使用してSMSを送信するように設定するには?

Sim1またはSim2を使用してSMSを送信する設定オプションがあると便利です。これはデュアルSIMに便利ですAndroid電話。SMSアプリケーションを作成しましたAndroid =アプリケーションをスムーズに送信することができましたが、SIM 1によって送信されたデフォルトのSMSですが、sim1またはsim2でSMSを送信するように設定して、プログラムでSMSを送信しますか?

18
Jebasuthan

このコードを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"/>
13
Anjal Saneen
SmsManager.getSmsManagerForSubscriptionId(int subscriptionId).sendTextMessage(String destinationAddress, String scAddress, String text,PendingIntent sentIntent, PendingIntent deliveryIntent);

これは、5.1 Lollipop version.beforeより多くを表示する必要がある前に機能します。答えが出たら更新します。

7
Thiyagesh waran

あなたはタスカーをチェックアウトする必要があります、それを使用してそのためのトグルウィジェットを構築することができます。

1
Ajster1989

完全なサンプルは次のとおりです。1つを選択する方法を示し、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" />-->

build.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 ""
        }
    }
}


0

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"/>を保証する必要があります