Android 双卡双待发送短信
来源:互联网 发布:java自学书籍推荐书目 编辑:程序博客网 时间:2024/06/05 02:16
I use this way to manage which sim to use for sending SMS even long message .. Its working on my dual sim phone Lenovo A319 (4.4.3), no need for root. its built on reflection.
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; }}
Add permission:
<uses-permission android:name="android.permission.SEND_SMS"/>
then just call that (bloody) static method like this :)
To use SIM1:
SimUtil.sendSMS(this,0,"00970XXXXXXXXX",null,"Hi Stackoverflow! its me Maher. Sent by sim1",null,null);
To use SIM2:
SimUtil.sendSMS(this,1,"00970XXXXXXXXX",null,"Hi Stackoverflow! its me Maher. Sent by sim2",null,null);
But wait...that won't work if message is longer than 160 characters.. so better way:
String textSMS;//short <160// textSMS = "Hi Stackoverflow! its me Maher.";//long >160textSMS = "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_2ArrayList<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);}
so you can safely pass message body without worrying about length.
------------------ Extra ------------------
I have seen that Android 22 supports multi sim cards from Android 5.1 and here is how to use it .. unfortunately I don't have device with that version for testing, so please for feedback:
SmsManager.getSmsManagerForSubscriptionId(int subscriptionId).sendTextMessage(String destinationAddress, String scAddress, String text,PendingIntent sentIntent, PendingIntent deliveryIntent);
How to get subscriptionId? to review all available subscriptionID that belong to sim card:
SubscriptionManager subscriptionManager = SubscriptionManager.from(getApplicationContext()); List<SubscriptionInfo> subscriptionInfoList = subscriptionManager.getActiveSubscriptionInfoList(); for (SubscriptionInfo subscriptionInfo : subscriptionInfoList) { int subscriptionId = subscriptionInfo.getSubscriptionId(); Log.d("apipas","subscriptionId:"+subscriptionId); }
** Please note that this code is working on 5.1. if you try to run it on older version you'd get an exception that method doesn't exist.
------------UPDATE 19.8.2015----------
Information on SIMs, are located in DB: telephony.db (by default: /data/data/com.android.providers.telephony/databases/telephony.db ) in table siminfo. See screenshot on table siminfo in DB on real device.
Fortunately there is a content provider for that:
"content://telephony/siminfo/"
So basically just query data from that table.Its important to mention that slot 0 represents SIM1, and 1 represents SIM2, and slot -1 from old/removed/replaced SIMs.
This applies on Lenovo A319 . I guess that may work on other devices. Here is the util method I use:
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; }
and here is the entity class 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 + '}'; }}
Good luck,'.
I use this way to manage which sim to use for sending SMS even long message .. Its working on my dual sim phone Lenovo A319 (4.4.3), no need for root. its built on reflection.
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; }}
Add permission:
<uses-permission android:name="android.permission.SEND_SMS"/>
then just call that (bloody) static method like this :)
To use SIM1:
SimUtil.sendSMS(this,0,"00970XXXXXXXXX",null,"Hi Stackoverflow! its me Maher. Sent by sim1",null,null);
To use SIM2:
SimUtil.sendSMS(this,1,"00970XXXXXXXXX",null,"Hi Stackoverflow! its me Maher. Sent by sim2",null,null);
But wait...that won't work if message is longer than 160 characters.. so better way:
String textSMS;//short <160// textSMS = "Hi Stackoverflow! its me Maher.";//long >160textSMS = "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_2ArrayList<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);}
so you can safely pass message body without worrying about length.
------------------ Extra ------------------
I have seen that Android 22 supports multi sim cards from Android 5.1 and here is how to use it .. unfortunately I don't have device with that version for testing, so please for feedback:
SmsManager.getSmsManagerForSubscriptionId(int subscriptionId).sendTextMessage(String destinationAddress, String scAddress, String text,PendingIntent sentIntent, PendingIntent deliveryIntent);
How to get subscriptionId? to review all available subscriptionID that belong to sim card:
SubscriptionManager subscriptionManager = SubscriptionManager.from(getApplicationContext()); List<SubscriptionInfo> subscriptionInfoList = subscriptionManager.getActiveSubscriptionInfoList(); for (SubscriptionInfo subscriptionInfo : subscriptionInfoList) { int subscriptionId = subscriptionInfo.getSubscriptionId(); Log.d("apipas","subscriptionId:"+subscriptionId); }
** Please note that this code is working on 5.1. if you try to run it on older version you'd get an exception that method doesn't exist.
------------UPDATE 19.8.2015----------
Information on SIMs, are located in DB: telephony.db (by default: /data/data/com.android.providers.telephony/databases/telephony.db ) in table siminfo. See screenshot on table siminfo in DB on real device.
Fortunately there is a content provider for that:
"content://telephony/siminfo/"
So basically just query data from that table.Its important to mention that slot 0 represents SIM1, and 1 represents SIM2, and slot -1 from old/removed/replaced SIMs.
This applies on Lenovo A319 . I guess that may work on other devices. Here is the util method I use:
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; }
and here is the entity class 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 + '}'; }}
Good luck,'.
- android 双卡双待 发送短信
- android 双卡双待 发送短信
- Android 双卡双待发送短信
- android 中发送短信
- android中发送短信
- android发送短信
- Android 发送短信
- Android自动发送短信
- Android发送短信
- android 发送短信sms
- android 发送短信
- android发送短信
- Android短信发送器
- android 之短信发送
- Android自动发送短信
- android短信发送
- Android发送短信
- android 发送短信问题
- 这个题目也是经典的BFS算法,题目的链接如下: http://poj.org/problem?id=1915
- go语言之 panic, recover ——如何在go语言中优雅的处理错误
- System.nanoTime与System.currentTimeMillis的区别
- C++中文件路径的使用方法
- hibernate多对一,一对一,多对多配置
- Android 双卡双待发送短信
- Java 异常
- Jedis初识
- 程序员简历优化之道
- java学习之路 之 反射机制综合练习题、动态代理实例
- BGRABitmap图像操作8:彩色纹理
- 【opencv练习19 - 图像添加边界】
- Counting Bits——Difficulty:Medium
- 地址传递用法