Reputation: 5604
I have an Android phone with 2 SIM card and I want to send sms using Sim1 or Sim2.By default the message is sent from sim1. But i want to send sms from sim2. Is it possible to setting to send sms using Sim1 or Sim2?
It would be great if there is an setting options to send sms using Sim1 or Sim2.. this is useful for dual SIM android phones. I created sms application android I've been able to sms application smoothly but default sms sent by SIM 1.But I want to send the sms programmatically by setting to send the sms by sim1 or sim2?
Upvotes: 22
Views: 28765
Reputation: 3219
You can use this code for API level 22+ (Android 5.0) LOLLIPOP_MR1
.
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();
}
}
Don't forget to add permission in your AndoridManifest.xml
.
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
Upvotes: 23
Reputation: 116382
Here's a full sample, showing how to choose one, and tested on real device (OnePlus 2) with 2 sim cards. Note that you should handle permissions (grant them before using the code) :
manifest
<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 ""
}
}
}
Upvotes: 0
Reputation: 103
SOLUTION WITHOUT 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);
}
}
}
Your have to guarantee the <uses-permission android:name="android.permission.SEND_SMS"/>
Upvotes: -1
Reputation: 89
SmsManager.getSmsManagerForSubscriptionId(int subscriptionId).sendTextMessage(String destinationAddress, String scAddress, String text,PendingIntent sentIntent, PendingIntent deliveryIntent);
this can be working after 5.1 Lollipop version.before that we need to see more. once i got the answer i will update.
Upvotes: 9
Reputation: 31
The option is available in Android Settings- navigate to Settings>>Wireless & Networks>>SIM Management>>Default Settings>>Messages>> and select 'Always Ask".
Upvotes: -4
Reputation: 317
You should check out tasker, you would be able to user it to build a toggle widget for that.
Upvotes: 0