Android开发的问题 其实很好狠。今天看到一篇解决android 机型 双卡 管理的问题。看到一篇比较好的文章就转载过来了 = =
转载:http://blog.csdn.net/banketree/article/details/24306493

获取基于ITelephony接口实现phone应用中的“phone服务”,通过TelephonyManager接口获取不同的卡(GSMPhone /CDMAPhone)进行不同的操作(拨号、接通、挂断、保持通话等)。

Android平台是一个多样型的平台,不同的手机获取ITelephony接口不同,用一种方法实现双卡双待管理是不可取的。那怎么办呢?只有针对不同的手机分析出一套管理的方案,该方案实现难度大,因为需要各个厂家的SDK的资料。为了实现该功能,笔者做了大量工作,整合各个厂家的SDK的资料。

实现

为了更好的管理双卡双待的问题,新建一个双卡双待模块静态库,其它项目引用便是,项目如图:

效果如图:

小米手机 测试效果

华为手机测试效果

AbsSim是抽象类,负责实现手机操作的类。不同的厂家继承该类实现各自的接口。AbsSim信息如下:

[cpp] view plaincopy
  1. public abstract class AbsSim implements IDualDetector { //抽象基类
  2. protected final String TAG = getClass().getSimpleName();
  3. protected ArrayList<SimSlot> mSimSlots = new ArrayList<SimSlot>();
  4. protected boolean mIsDualSimPhone = false;
  5. protected String mCallLogExtraField = "";
  6. public abstract String getSimPhoneNumber(int paramInt); // 返回手机号码
  7. public abstract int getDataState(int paramInt);// 返回数据状态
  8. public abstract String getIMSI(int paramInt);// 返回手机标识
  9. public abstract String getIMSI(int paramInt, Context paramContext);// 返回手机标识
  10. public abstract int getPhoneState(int paramInt);// 返回手机状态
  11. public abstract boolean isServiceAvaliable(int paramInt);// 服务是否可用
  12. public abstract boolean isSimStateIsReady(int paramInt);// 卡是否在使用
  13. public abstract int getSimOperator(int paramInt);// 服务商(电信、移动、联通)
  14. protected abstract Object getITelephonyMSim(int paramInt);// 获取操作接口
  15. protected abstract Object getMSimTelephonyManager(int paramInt);// 获取操作接口
  16. @Override
  17. public AbsSim detect() { // 根据手机信息匹配
  18. if ((getITelephonyMSim(0) != null) && (getITelephonyMSim(1) != null)
  19. // && (getmMSimSmsManager(0) != null)
  20. // && (getmMSimSmsManager(1) != null)
  21. // && (detectSms(paramContext, paramBoolean))
  22. // && (detectCallLog(paramContext, paramBoolean))
  23. )
  24. return this;
  25. return null;
  26. }
  27. public boolean directCall(String paramString, int paramInt) { // 拨打电话(根据不同卡拨打电话)
  28. Intent localIntent = new Intent("android.intent.action.CALL",
  29. Uri.fromParts("tel", paramString, null));
  30. localIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  31. try {
  32. getContext().startActivity(localIntent);
  33. return true;
  34. } catch (Throwable localThrowable) {
  35. localThrowable.printStackTrace();
  36. }
  37. return false;
  38. }
  39. protected boolean detectCallLog() { // 通过通话记录信息匹配
  40. return false;
  41. }
  42. protected boolean detectSms() {// 通过短信记录信息匹配
  43. return false;
  44. }
  45. protected Context getContext() { // 返回句柄
  46. return SimManager.getInstance().getContext();
  47. }
  48. protected int getSimSlotNum() { // 返回插槽个数(默认2)
  49. return 2;
  50. }
  51. public void init() { // 初始化
  52. for (int i = 0; i < getSimSlotNum(); i++) {
  53. try {
  54. String imsi = getIMSI(i);
  55. boolean isUsing = isSimStateIsReady(i);
  56. if (imsi != null || isUsing) {
  57. if (imsi == null || hasSimSlotByIMSI(imsi))
  58. continue;
  59. SimSlot simSlot = new SimSlot();
  60. mSimSlots.add(simSlot);
  61. simSlot.setUsing(isUsing);
  62. simSlot.setIMSI(imsi);
  63. simSlot.setSimOperator(getSimOperator(i));
  64. }
  65. } catch (Exception e) {
  66. e.printStackTrace();
  67. }
  68. }
  69. }
  70. public boolean hasSimPhone() {// 是否有sd卡在使用
  71. if (mSimSlots.isEmpty())
  72. return false;
  73. for (SimSlot simslot : mSimSlots) {
  74. if (simslot.isUsing())
  75. return true;
  76. }
  77. return false;
  78. }
  79. public boolean isDualSimPhone() {// 是否为双卡
  80. if (getSimSlots().isEmpty() || getSimSlots().size() < 2)
  81. return false;
  82. for (SimSlot simSlot : getSimSlots()) {
  83. if (!simSlot.isUsing())
  84. return false;
  85. }
  86. return true;
  87. }
  88. public ArrayList<SimSlot> getSimSlots() { // 返回已确认的卡
  89. return mSimSlots;
  90. }
  91. protected boolean delSimSlotByIMSI(String imsi) { // 删除相同的卡的信息
  92. for (SimSlot simSlot : getSimSlots()) {
  93. if (simSlot.getIMSI() != null && simSlot.getIMSI().equals(imsi)) {
  94. getSimSlots().remove(simSlot);
  95. }
  96. }
  97. return false;
  98. }
  99. protected boolean hasSimSlotByIMSI(String imsi) {
  100. for (SimSlot simSlot : getSimSlots()) {
  101. if (simSlot.getIMSI() != null && simSlot.getIMSI().equals(imsi)) {
  102. return true;
  103. }
  104. }
  105. return false;
  106. }
  107. }

现在列举一款实现MTK方案:

[cpp] view plaincopy
  1. public class MTKDualSim extends AbsSim {// 采用MTK方案的类(根据厂家SDK实现不同的接口)
  2. private Object mMSimTelephonyManager = null;
  3. private Object mTelephonyMSim = null;
  4. public MTKDualSim() {
  5. mCallLogExtraField = "simid";
  6. String str1 = SimManager.getModel();
  7. String str2 = SimManager.getManufaturer();
  8. if ((str1 != null) && (str2 != null)) {
  9. String str3 = str1.toLowerCase();
  10. String str4 = str2.toLowerCase();
  11. if ((str4.indexOf("huawei") > -1) && (str3.indexOf("h30-t00") > -1))
  12. mCallLogExtraField = "subscription";
  13. if ((str4.indexOf("hisense") > -1)
  14. && (str3.indexOf("hs-u970") > -1)) {
  15. mCallLogExtraField = "subtype";
  16. }
  17. }
  18. }
  19. @Override
  20. public boolean directCall(String paramString, int paramInt) {
  21. if (SimManager.isSDKVersionMore4_1()) {
  22. Intent localIntent1 = new Intent("android.intent.action.CALL",
  23. Uri.fromParts("tel", paramString, null));
  24. localIntent1.putExtra("simId", paramInt);
  25. localIntent1.putExtra("com.android.phone.extra.slot", paramInt);
  26. localIntent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  27. try {
  28. getContext().startActivity(localIntent1);
  29. return true;
  30. } catch (Throwable localThrowable1) {
  31. localThrowable1.printStackTrace();
  32. }
  33. } else if (SimManager.isSDKVersionMore4_0()) {
  34. Intent localIntent2 = new Intent(
  35. "com.android.phone.OutgoingCallReceiver");
  36. localIntent2.putExtra("com.android.phone.extra.slot", paramInt);
  37. localIntent2.putExtra("simId", paramInt);
  38. localIntent2.putExtra("com.android.phone.force.slot", true);
  39. localIntent2.setClassName("com.android.phone",
  40. "com.android.phone.OutgoingCallReceiver");
  41. localIntent2.setData(Uri.fromParts("tel", paramString, null));
  42. try {
  43. getContext().sendBroadcast(localIntent2);
  44. return true;
  45. } catch (Throwable localThrowable2) {
  46. localThrowable2.printStackTrace();
  47. }
  48. }
  49. try {
  50. Intent localIntent3 = new Intent();
  51. localIntent3.setAction("out_going_call_to_phone_app");
  52. localIntent3.putExtra("number", paramString);
  53. localIntent3.putExtra("simId", paramInt);
  54. localIntent3.putExtra("com.android.phone.extra.slot", paramInt);
  55. localIntent3.putExtra("launch_from_dialer", 1);
  56. localIntent3.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  57. getContext().sendBroadcast(localIntent3);
  58. return true;
  59. } catch (Throwable localThrowable3) {
  60. localThrowable3.printStackTrace();
  61. }
  62. return false;
  63. }
  64. @Override
  65. public AbsSim detect() {
  66. String imsi = getIMSI(0);
  67. if (imsi != null && !TextUtils.isEmpty(imsi)) {
  68. return this;
  69. }
  70. return super.detect();
  71. }
  72. @Override
  73. public String getSimPhoneNumber(int paramInt) {
  74. Object[] arrayOfObject2 = new Object[1];
  75. try {
  76. Object localObject = getMSimTelephonyManager(paramInt);
  77. arrayOfObject2[0] = Integer.valueOf(paramInt);
  78. String result = (String) ReflecterHelper.invokeMethod(localObject,
  79. "getLine1NumberGemini", arrayOfObject2);
  80. arrayOfObject2 = null;
  81. return result;
  82. } catch (Throwable localThrowable) {
  83. localThrowable.printStackTrace();
  84. }
  85. return "";
  86. }
  87. @Override
  88. public int getDataState(int paramInt) {
  89. Object[] arrayOfObject2 = new Object[1];
  90. try {
  91. Object localObject = getMSimTelephonyManager(paramInt);
  92. arrayOfObject2[0] = Integer.valueOf(paramInt);
  93. int result = ((Integer) ReflecterHelper.invokeMethod(localObject,
  94. "getDataStateGemini", arrayOfObject2)).intValue();
  95. arrayOfObject2 = null;
  96. return result;
  97. } catch (Throwable localThrowable) {
  98. localThrowable.printStackTrace();
  99. }
  100. arrayOfObject2 = null;
  101. return -1;
  102. }
  103. @Override
  104. public String getIMSI(int paramInt) {
  105. return getIMSI(paramInt, null);
  106. }
  107. @Override
  108. public String getIMSI(int paramInt, Context paramContext) {
  109. Object localObject = getMSimTelephonyManager(paramInt);
  110. Object[] arrayOfObject2 = new Object[1];
  111. try {
  112. arrayOfObject2[0] = Integer.valueOf(paramInt);
  113. String result = (String) ReflecterHelper.invokeMethod(localObject,
  114. "getSubscriberIdGemini", arrayOfObject2);
  115. arrayOfObject2 = null;
  116. return result;
  117. } catch (Throwable localThrowable) {
  118. localThrowable.printStackTrace();
  119. }
  120. arrayOfObject2 = null;
  121. return null;
  122. }
  123. @Override
  124. public int getPhoneState(int paramInt) {
  125. Object localObject = getMSimTelephonyManager(paramInt);
  126. Object[] arrayOfObject2 = new Object[1];
  127. try {
  128. arrayOfObject2[0] = Integer.valueOf(paramInt);
  129. int result = ((Integer) ReflecterHelper.invokeMethod(localObject,
  130. "getCallStateGemini", arrayOfObject2)).intValue();
  131. arrayOfObject2 = null;
  132. return result;
  133. } catch (Throwable localThrowable) {
  134. localThrowable.printStackTrace();
  135. }
  136. arrayOfObject2 = null;
  137. return 0;
  138. }
  139. @Override
  140. public boolean isServiceAvaliable(int paramInt) {
  141. Object localObject = getITelephonyMSim(paramInt);
  142. if (localObject == null)
  143. return false;
  144. Object[] arrayOfObject2 = new Object[1];
  145. try {
  146. arrayOfObject2[0] = Integer.valueOf(paramInt);
  147. boolean result = ((Boolean) ReflecterHelper.invokeMethod(
  148. localObject, "isRadioOnGemini", arrayOfObject2))
  149. .booleanValue();
  150. arrayOfObject2 = null;
  151. return result;
  152. } catch (Throwable localThrowable) {
  153. localThrowable.printStackTrace();
  154. }
  155. arrayOfObject2 = null;
  156. return false;
  157. }
  158. @Override
  159. public boolean isSimStateIsReady(int paramInt) {
  160. Object localObject = getMSimTelephonyManager(paramInt);
  161. if (localObject != null) {
  162. Object[] arrayOfObject2 = new Object[1];
  163. try {
  164. arrayOfObject2[0] = Integer.valueOf(paramInt);
  165. int result = ((Integer) ReflecterHelper.invokeMethod(
  166. localObject, "getSimStateGemini", arrayOfObject2))
  167. .intValue();
  168. arrayOfObject2 = null;
  169. return result == 5;
  170. } catch (Throwable localThrowable) {
  171. localThrowable.printStackTrace();
  172. }
  173. arrayOfObject2 = null;
  174. }
  175. return false;
  176. }
  177. @Override
  178. public int getSimOperator(int paramInt) { // 注意
  179. Object localObject = getMSimTelephonyManager(paramInt);
  180. Object[] arrayOfObject2 = new Object[1];
  181. try {
  182. arrayOfObject2[0] = Integer.valueOf(paramInt);
  183. String result = ((String) ReflecterHelper.invokeMethod(localObject,
  184. "getSimOperatorGemini", arrayOfObject2));
  185. arrayOfObject2 = null;
  186. return Integer.valueOf(result);
  187. } catch (Throwable localThrowable) {
  188. localThrowable.printStackTrace();
  189. }
  190. arrayOfObject2 = null;
  191. return 0;
  192. }
  193. @Override
  194. protected Object getITelephonyMSim(int paramInt) {
  195. if (mTelephonyMSim == null)
  196. mTelephonyMSim = ITelephony.Stub.asInterface(ServiceManager
  197. .getService("phone"));
  198. return mTelephonyMSim;
  199. }
  200. @Override
  201. protected Object getMSimTelephonyManager(int paramInt) {
  202. if (mMSimTelephonyManager != null)
  203. return mMSimTelephonyManager;
  204. Object[] arrayOfObject3 = new Object[1];
  205. try {
  206. mMSimTelephonyManager = SimManager.getInstance()
  207. .getTelephonyManagerByPhone();
  208. try {
  209. Object localObject = mMSimTelephonyManager;
  210. arrayOfObject3[0] = Integer.valueOf(0);
  211. ReflecterHelper.invokeMethod(localObject,
  212. "getSubscriberIdGemini", arrayOfObject3);
  213. arrayOfObject3 = null;
  214. return mMSimTelephonyManager;
  215. } catch (Throwable localThrowable2) {
  216. localThrowable2.printStackTrace();
  217. }
  218. } catch (Throwable localThrowable1) {
  219. localThrowable1.printStackTrace();
  220. }
  221. arrayOfObject3 = null;
  222. return null;
  223. }
  224. }

再列举一款单卡的方案:

[cpp] view plaincopy
  1. public class SingleSim extends AbsSim implements IDualDetector {// 单卡方案
  2. private final String TAG = getClass().getSimpleName();
  3. private HashMap<String, Byte> mCallLogExtraFields = new SingleSim$1(this);
  4. @Override
  5. public boolean hasSimPhone() {
  6. return false;
  7. }
  8. @Override
  9. public AbsSim detect() {// 根据某些字段判是否为双卡(有可能误判)
  10. if (mIsDualSimPhone)
  11. return null;
  12. Cursor localSafeCursor = null;
  13. String[] arrayOfString;
  14. try {
  15. localSafeCursor = SimManager
  16. .getInstance()
  17. .getContext()
  18. .getContentResolver()
  19. .query(CallLog.Calls.CONTENT_URI, null, null, null,
  20. "_id limit 0,1");
  21. if (localSafeCursor != null && localSafeCursor.moveToFirst()) {
  22. arrayOfString = localSafeCursor.getColumnNames();
  23. for (int i = 0; i < arrayOfString.length; i++) {
  24. String str = arrayOfString[i];
  25. if (mCallLogExtraFields.containsKey(str.toLowerCase())) {
  26. mIsDualSimPhone = true;
  27. mCallLogExtraField = str;
  28. }
  29. }
  30. }
  31. } catch (Exception e) {
  32. e.printStackTrace();
  33. }
  34. return this;
  35. }
  36. @Override
  37. public boolean isDualSimPhone() {
  38. return mIsDualSimPhone;
  39. }
  40. @Override
  41. public int getSimSlotNum() {
  42. return 1;
  43. }
  44. @Override
  45. public String getSimPhoneNumber(int paramInt) {
  46. return ((TelephonyManager) getMSimTelephonyManager(0)).getLine1Number();
  47. }
  48. @Override
  49. public int getDataState(int paramInt) {
  50. return ((TelephonyManager) getMSimTelephonyManager(0)).getDataState();
  51. }
  52. @Override
  53. public String getIMSI(int paramInt) {
  54. return ((TelephonyManager) getMSimTelephonyManager(0)).getDeviceId();
  55. }
  56. @Override
  57. public String getIMSI(int paramInt, Context paramContext) {
  58. return ((TelephonyManager) getMSimTelephonyManager(0))
  59. .getSubscriberId();
  60. }
  61. @Override
  62. public int getPhoneState(int paramInt) {
  63. return ((TelephonyManager) getMSimTelephonyManager(0)).getCallState();
  64. }
  65. @Override
  66. public boolean isServiceAvaliable(int paramInt) {
  67. ITelephony localITelephony = (ITelephony) getITelephonyMSim(0);
  68. if (localITelephony == null)
  69. return false;
  70. try {
  71. boolean bool = localITelephony.isRadioOn();
  72. return bool;
  73. } catch (Throwable localThrowable) {
  74. localThrowable.printStackTrace();
  75. }
  76. return false;
  77. }
  78. @Override
  79. public boolean isSimStateIsReady(int paramInt) {
  80. return ((TelephonyManager) getMSimTelephonyManager(0)).getSimState() == 5;
  81. }
  82. @Override
  83. public int getSimOperator(int paramInt) {
  84. TelephonyManager localTelephonyManager = (TelephonyManager) getMSimTelephonyManager(paramInt);
  85. return Integer.parseInt(localTelephonyManager.getSimOperator());
  86. }
  87. @Override
  88. protected Object getITelephonyMSim(int paramInt) {
  89. return SimManager.getInstance().getITelephonyByPhone();
  90. }
  91. @Override
  92. protected Object getMSimTelephonyManager(int paramInt) {
  93. return SimManager.getInstance().getTelephonyManagerByPhone();
  94. }
  95. }
总结

利用java 反射机制操作Android隐藏的类,很好的解决了双卡双待的问题。
Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。

项目下载

解决 Android 双卡双待识别相关推荐

  1. Android 双卡双待识别

    简介 Android双卡双待已经越来越普及了,解决双卡双待管理是广大手机开发人员必须得面对的问题,为实现Android平台的双卡双待操作,笔者研究了Android 应用层操作双卡双待的机制. 机制 获 ...

  2. android 双卡识别,Android 双卡双待识别

    简介 Android双卡双待已经越来越普及了,解决双卡双待管理是广大手机开发人员必须得面对的问题,为实现Android平台的双卡双待操作,笔者研究了Android 应用层操作双卡双待的机制. 机制 获 ...

  3. 解决Android图库不识别.nomedia的问题

    解决Android图库不识别.nomedia的问题 参考文章: (1)解决Android图库不识别.nomedia的问题 (2)https://www.cnblogs.com/TianFang/arc ...

  4. 【问题解决】解决eclipse不识别Android手机的问题

    [问题&解决]解决eclipse不识别Android手机的问题 参考文章: (1)[问题&解决]解决eclipse不识别Android手机的问题 (2)https://www.cnbl ...

  5. 华为DUA-AL00真机android studio识别不出

    华为DUA-AL00真机android studio识别不出 当时花了1000元买的真机,直到现在都感觉华为的这个型号的时候是真的难用,显示日志需要特殊的配置,甚至连接计算机调试都比别的手机麻烦. 这 ...

  6. android指纹识别源码

    随着科技的进步,不仅是软件方面,安卓系统在硬件发展上也有了日新月异的发展.2015年下半年出的安卓手机基本上都带指纹识别功能,不管是炒得很热的360奇酷手机.魅族手机,还是"中华酷联&quo ...

  7. android canvas 保存图片,ionic3 html5 video 抓图保存到手机相册,解决Android手机不支持Canvas drawImage问题...

    当然百度出上W条答案 上代码,相信下面代码和小伙伴大同吧 相信好多做webview app的小伙伴们都有同样的问题,在pc上能轻松实现video 抓图.但是在android手机大多是不支持canvas ...

  8. Android 人脸识别

    Android人脸识别技术,可以参考下面的网站. http://www.faceplusplus.com.cn/ 本项目使用的就是该网站的api. 项目具体使用的技术代码 /*** 用来压缩图片的方法 ...

  9. 解决android客户端上传图片到服务端时,图片损坏的问题

    解决android客户端上传图片到服务端时,图片损坏的问题 参考文章: (1)解决android客户端上传图片到服务端时,图片损坏的问题 (2)https://www.cnblogs.com/cnbl ...

最新文章

  1. 科研文献|了解多个含水层中微生物砷的迁移:DNA 和 RNA 分析的见解
  2. android 应用程序分析之settings,Android 应用程序分析之Settings
  3. 在Win7中使用Python的MySQLdb模块
  4. 分布式锁的几种实现原理
  5. 理解云计算备份与灾难恢复
  6. Samsung Galaxy S III GT-I9300详细刷机教程
  7. silverlight动态添加xaml物件
  8. 全球首发!计算机视觉Polygon Mesh Processing总结10——DEFORMATION
  9. Struts中s:checkboxlist的用法
  10. js创建对象的多种方式及优缺点
  11. 学习EXT第八天:EXT的布局(Layout)Part 1
  12. Atitit springboot helloword 最简化 attilax总结
  13. html远程连接mysql_mysql允许远程连接
  14. ERP财务管理系统有哪些特点
  15. 自然语言14_Stemming words with NLTK
  16. 《MySQL数据库进阶实战》读后感(SQL 小虚竹)
  17. 1688店铺所有商品API接口(整店商品查询API接口)
  18. VCC 能否解决跨境支付的问题?
  19. 天啦撸~ChatGPT通过国际软件测试工程师(ISTQB)认证了~
  20. 嵌入式主板有哪些特点?

热门文章

  1. RDLC报表设置A4纸,页间距,行间距,段落间距
  2. IOS面试题(经典)
  3. 【数学建模绘图系列教程】二、折线图的绘制与优化
  4. git commit 时报错:✖ stylelint --syntax less found some errors. Please fix them and try committing again
  5. PoPo数据可视化周刊第6期
  6. 微服务集成Sentine--服务雪崩效应以及常见的容错方案
  7. 芯片+ GPU +CPU 简单理解
  8. CRC32校验原理及实现
  9. excel中的常用技巧_在Excel中控制技巧
  10. java string 字符串比较_Java字符串比较