如何使用双SIM卡手机中的SMSmanager发送短信?
我正在使用短信管理器发送短信。对于单卡,它的作品完全可以发送短信。但在双卡上,短信不会发送。如果可能,我可以如何选择双卡发送短信哪个SIM卡发送短信。任何人都知道可以帮我解决这个问题。如何使用双SIM卡手机中的SMSmanager发送短信?
单SIM工作守则
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(ph_number, null, body, null,null);
我用这样的方式来管理其SIM用于发送短信,甚至长的消息。它的工作我的双卡双待手机联想A319(4.4.3)上,不需要根。它建立在反思之上。
import android.app.PendingIntent;
import android.content.Context;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Apipas on 6/4/15.
*/
public class SimUtil {
public static boolean sendSMS(Context ctx, int simID, String toNum, String centerNum, String smsText, PendingIntent sentIntent, PendingIntent deliveryIntent) {
String name;
try {
if (simID == 0) {
name = "isms";
// for model : "Philips T939" name = "isms0"
} else if (simID == 1) {
name = "isms2";
} else {
throw new Exception("can not get service which for sim '" + simID + "', only 0,1 accepted as values");
}
Method method = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", String.class);
method.setAccessible(true);
Object param = method.invoke(null, name);
method = Class.forName("com.android.internal.telephony.ISms$Stub").getDeclaredMethod("asInterface", IBinder.class);
method.setAccessible(true);
Object stubObj = method.invoke(null, param);
if (Build.VERSION.SDK_INT < 18) {
method = stubObj.getClass().getMethod("sendText", String.class, String.class, String.class, PendingIntent.class, PendingIntent.class);
method.invoke(stubObj, toNum, centerNum, smsText, sentIntent, deliveryIntent);
} else {
method = stubObj.getClass().getMethod("sendText", String.class, String.class, String.class, String.class, PendingIntent.class, PendingIntent.class);
method.invoke(stubObj, ctx.getPackageName(), toNum, centerNum, smsText, sentIntent, deliveryIntent);
}
return true;
} catch (ClassNotFoundException e) {
Log.e("apipas", "ClassNotFoundException:" + e.getMessage());
} catch (NoSuchMethodException e) {
Log.e("apipas", "NoSuchMethodException:" + e.getMessage());
} catch (InvocationTargetException e) {
Log.e("apipas", "InvocationTargetException:" + e.getMessage());
} catch (IllegalAccessException e) {
Log.e("apipas", "IllegalAccessException:" + e.getMessage());
} catch (Exception e) {
Log.e("apipas", "Exception:" + e.getMessage());
}
return false;
}
public static boolean sendMultipartTextSMS(Context ctx, int simID, String toNum, String centerNum, ArrayList<String> smsTextlist, ArrayList<PendingIntent> sentIntentList, ArrayList<PendingIntent> deliveryIntentList) {
String name;
try {
if (simID == 0) {
name = "isms";
// for model : "Philips T939" name = "isms0"
} else if (simID == 1) {
name = "isms2";
} else {
throw new Exception("can not get service which for sim '" + simID + "', only 0,1 accepted as values");
}
Method method = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", String.class);
method.setAccessible(true);
Object param = method.invoke(null, name);
method = Class.forName("com.android.internal.telephony.ISms$Stub").getDeclaredMethod("asInterface", IBinder.class);
method.setAccessible(true);
Object stubObj = method.invoke(null, param);
if (Build.VERSION.SDK_INT < 18) {
method = stubObj.getClass().getMethod("sendMultipartText", String.class, String.class, List.class, List.class, List.class);
method.invoke(stubObj, toNum, centerNum, smsTextlist, sentIntentList, deliveryIntentList);
} else {
method = stubObj.getClass().getMethod("sendMultipartText", String.class, String.class, String.class, List.class, List.class, List.class);
method.invoke(stubObj, ctx.getPackageName(), toNum, centerNum, smsTextlist, sentIntentList, deliveryIntentList);
}
return true;
} catch (ClassNotFoundException e) {
Log.e("apipas", "ClassNotFoundException:" + e.getMessage());
} catch (NoSuchMethodException e) {
Log.e("apipas", "NoSuchMethodException:" + e.getMessage());
} catch (InvocationTargetException e) {
Log.e("apipas", "InvocationTargetException:" + e.getMessage());
} catch (IllegalAccessException e) {
Log.e("apipas", "IllegalAccessException:" + e.getMessage());
} catch (Exception e) {
Log.e("apipas", "Exception:" + e.getMessage());
}
return false;
}
}
添加权限:
<uses-permission android:name="android.permission.SEND_SMS"/>
然后就这样调用:)
要使用(血腥)静态方法SIM1:
SimUtil.sendSMS(this,0,"00970XXXXXXXXX",null,"Hi Stackoverflow! its me Maher. Sent by sim1",null,null);
要使用SIM2:
SimUtil.sendSMS(this,1,"00970XXXXXXXXX",null,"Hi Stackoverflow! its me Maher. Sent by sim2",null,null);
别急...如果消息是超过160个字符,将无法正常工作..所以更好的办法:
String textSMS;
//short <160
// textSMS = "Hi Stackoverflow! its me Maher.";
//long >160
textSMS = "Hi Jerusalem, hi Cairo, Hi Prague, hi Baghdad, hi Riyadh, hi Jeddah, hi Dammam, hi Aleppo, hi Casablanca, hi Damascus, hi Alexandria, hi Algiers, hi Mosul, hi Basra, hi Arabia, hi Tripoli, hi Amman, hi Kuwait, hi Beirut, hi Abu Dhabi";
int simID = 0;//0:sim_1, 1:sim_2
ArrayList<String> messageList = SmsManager.getDefault().divideMessage(textSMS);
if (messageList.size() > 1) {
SimUtil.sendMultipartTextSMS(this, simID, "00972XXXXXXXXX", null, messageList, null, null);
} else {
SimUtil.sendSMS(this, simID, "00972XXXXXXXXX", null, textSMS, null, null);
}
,所以你可以放心地传递消息体,而不必担心长度。
------------ UPDATE 2016年9月10日----------
要MultipartMessage使用的PendingIntent/DeliveryIntent ..只是创建具有相同内容ArrayList和交上来。这里是创建PendingIntent列表的实现:
final static String sSMSManagerIntentSENT = "package.DeliveryReport.SMS_SENT";
int numParts = parts.size();
ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>();
for (int i = 0; i < numParts; i++) {
Intent pendingIntent = new Intent(sSMSManagerIntentSENT);
//optional if you want to keep info about what action has been done for feedback or analysis later when message is sent
pendingIntent.putExtra("package.DeliveryReport.phoneNumber", phoneNo); // receiver phoneNo
pendingIntent.putExtra("package.DeliveryReport.textSMS", msg);// msg body
pendingIntent.putExtra("SIM", simID); // which sim is sending this message
pendingIntents.add(PendingIntent.getBroadcast(getActivity(), 0, pendingIntent,PendingIntent.FLAG_ONE_SHOT));
}
对于交付,只需使用相同的方法。
------------------额外------------------
我已经看到了Android的22是Android 5.1支持多SIM卡,在这里是如何使用它..不幸的是我没有设备与该版本进行测试,所以请反馈:
SmsManager.getSmsManagerForSubscriptionId(int subscriptionId).sendTextMessage(String destinationAddress, String scAddress, String text,PendingIntent sentIntent, PendingIntent deliveryIntent);
如何获得subscriptionId? 审查属于SIM卡的所有可用subscriptionID:
SubscriptionManager subscriptionManager = SubscriptionManager.from(getApplicationContext());
List<SubscriptionInfo> subscriptionInfoList = subscriptionManager.getActiveSubscriptionInfoList();
for (SubscriptionInfo subscriptionInfo : subscriptionInfoList) {
int subscriptionId = subscriptionInfo.getSubscriptionId();
Log.d("apipas","subscriptionId:"+subscriptionId);
}
**请注意,此代码正在5.1。如果你尝试在旧版本上运行它,你会得到一个该方法不存在的异常。
------------ UPDATE 2015年8月19日----------
SIM卡上的信息,均位于DB:telephony.db(默认情况下: /data/data/com.android.providers.telephony/databases/telephony.db)。 查看真实设备上的数据库表siminfo中的屏幕截图。
幸运的是对于内容提供商:
"content://telephony/siminfo/"
所以基本上只是查询从table.Its重要一提的是插槽0代表SIM1和1代表SIM2的数据,插槽-1从旧/已移除/已更换的SIM卡。
这适用于联想A319。我想这可能适用于其他设备。 这里是util的方法我用:
public static List<SimInfo> getSIMInfo(Context context) {
List<SimInfo> simInfoList = new ArrayList<>();
Uri URI_TELEPHONY = Uri.parse("content://telephony/siminfo/");
Cursor c = context.getContentResolver().query(URI_TELEPHONY, null, null, null, null);
if (c.moveToFirst()) {
do {
int id = c.getInt(c.getColumnIndex("_id"));
int slot = c.getInt(c.getColumnIndex("slot"));
String display_name = c.getString(c.getColumnIndex("display_name"));
String icc_id = c.getString(c.getColumnIndex("icc_id"));
SimInfo simInfo = new SimInfo(id, display_name, icc_id, slot);
Log.d("apipas_sim_info", simInfo.toString());
simInfoList.add(simInfo);
} while (c.moveToNext());
}
c.close();
return simInfoList;
}
,这里是实体类SimInfo:
public class SimInfo {
private int id_;
private String display_name;
private String icc_id;
private int slot;
public SimInfo(int id_, String display_name, String icc_id, int slot) {
this.id_ = id_;
this.display_name = display_name;
this.icc_id = icc_id;
this.slot = slot;
}
public int getId_() {
return id_;
}
public String getDisplay_name() {
return display_name;
}
public String getIcc_id() {
return icc_id;
}
public int getSlot() {
return slot;
}
@Override
public String toString() {
return "SimInfo{" +
"id_=" + id_ +
", display_name='" + display_name + '\'' +
", icc_id='" + icc_id + '\'' +
", slot=" + slot +
'}';
}
}
祝你好运,“。
马赫的基于反射解决方案适用于仿真器的Android SDK 10,17,18,19,20,21和如所提到的基于SubscriptionId解决方案适用于SDK 22 它的实际工作为Micromax的画布4(的Android 4.2)以及。
但对于一些手机品牌,如Lenevo,华硕品牌与Android 5.0它的错误了与
显示java.lang.NullPointerException:试图调用虚拟方法 “java.lang.Class中的java.lang。 Object.GetClass()'上一个空对象 参考 “在代码
”方法= stubObj.getClass()。getMethod(“ sendText”,String.class, String.class,String.class,字符串.class,PendingIntent.class, PendingIntent.class);
这意味着它无法得到正确的stubObj
。
**空指针异常直接与名称相关联。即isms或isms0。**华硕我尝试了isms1,isms2 for sim no 2,但它不起作用。试图找到我们如何通过反思获得正确的价值,如果有人知道请让我知道。 – Vibhav 2015-12-24 17:45:29
我发现的是**服务列表| grep sms会给出电话中有效服务名称**的列表,即isms,isms2。 现在这里是棘手的部分..在华硕双SIM卡手机,我可以看到只有一个短信服务(isms)正在运行,但短信应用程序能够发送来自2个不同的SIM卡消息。想知道如何... 人需要帮助理解。 – Vibhav 2015-12-24 19:31:07
如果双sim与1 isms服务存在,发送短信无缝Android 5.0以下是我的解决方案(与联想和华硕手机测试) - 使用反射和取决于Android 5.0子版本一需要执行 'SmsManager sm = SmsManager.getSmsManagerForSubscriber(SubscriptionManager.getSubId(SimSlotNo))' OR 'SmsManager SM = SmsManager.getSmsManagerForSubscriptionId(SubscriptionManager.getSubId(SimSlotNo))' 得到相应的SIM卡的短信管理器。 然后使用 sm.sendTextMessage(phoneNo,null,msg,sentPI,deliverPI); 通过所需的Sim – Vibhav 2016-01-03 10:15:00
我试着在双SIM卡android手机(API 19及以下版本)中发送短信Mahers Refletion方法。智能手机中的芯片组来自展讯。我遇到Maher的代码异常,首先它是空指针异常,名称= isms2。对我来说,sim1是isms0,sim2是isms1,我在dumpsys中检索了这些信息。由于大部分调试和一些更多的搜索下面的代码为我工作:
public class SimUtil {
public static boolean sendSMS(Context ctx, int simID, String toNum, String centerNum, String smsText, PendingIntent sentIntent, PendingIntent deliveryIntent) {
String name;
try {
if (simID == 0) {
name = "isms0";
} else if (simID == 1) {
name = "isms1";
} else {
throw new Exception("can not get service which for sim '" + simID + "', only 0,1 accepted as values");
}
try
{
Method method = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", new Class[]{String.class});
method.setAccessible(true);
Object param = method.invoke(null, new Object[]{name});
if (param == null)
{
throw new RuntimeException("can not get service which is named '" + name + "'");
}
method = Class.forName("com.android.internal.telephony.ISms$Stub").getDeclaredMethod("asInterface", new Class[]{IBinder.class});
method.setAccessible(true);
Object stubObj = method.invoke(null, new Object[]{param});
method = stubObj.getClass().getMethod("sendText", String.class, String.class, String.class, String.class, PendingIntent.class, PendingIntent.class);
method.invoke(stubObj, ctx.getPackageName(), toNum, centerNum, smsText, sentIntent, deliveryIntent);
} catch (ClassNotFoundException e)
{
throw new RuntimeException(e);
} catch (NoSuchMethodException e)
{
throw new RuntimeException(e);
} catch (InvocationTargetException e)
{
throw new RuntimeException(e);
} catch (IllegalAccessException e)
{
throw new RuntimeException(e);
}
return true;
} catch (ClassNotFoundException e) {
Log.e("Exception", "ClassNotFoundException:" + e.getMessage());
} catch (NoSuchMethodException e) {
Log.e("Exception", "NoSuchMethodException:" + e.getMessage());
} catch (InvocationTargetException e) {
Log.e("Exception", "InvocationTargetException:" + e.getMessage());
} catch (IllegalAccessException e) {
Log.e("Exception", "IllegalAccessException:" + e.getMessage());
} catch (Exception e) {
Log.e("Exception", "Exception:" + e);
}
return false;
}
}
以下链接也许有帮助:
马赫的解决方案几乎正确。
我在摩托罗拉motog 5上试了一下。1个机器人(单卡),但他的伴读表content://telephony/siminfo
解决方案有一个微小的错误:
我的摩托罗拉没有现场slot
但sim_id
这种休息是个好人,是相同的。
这可能是你正在寻找的东西http://stackoverflow.com/questions/24007885/how-can-send-sms-in-android-in-dual-sim-with-set-default-sim – QAMAR 2014-12-08 05:44:55
5月你会在这里找到解决方案。 http://stackoverflow.com/questions/14276328/sms-manager-for-dual-sim-phones – 2014-12-08 05:46:57
@MurtazaHussain我想在编码本身做所有事情。这是可能的。 – Yugesh 2014-12-08 06:00:40