最近开发中遇到了双卡的问题,关于双卡查看了好多文章,但是没有一个能解决问题的,要么就是定制的或者有厂商提供支持的,我这里是基于Android5.1.1实现的双卡发送短信,这里需要用的反射,下面直接上代码,供大家参考:

一、首先实例化相关类

 
   
 
   
 
 
1. TelephonyManager mTelephonyManager = (TelephonyManager) mContext  
2.                 .getSystemService(Context.TELEPHONY_SERVICE);  
3. Class<TelephonyManager> clz = (Class<TelephonyManager>) mTelephonyManager.getClass();



二、调用相关方法

1、获取sim的状态,参数对应sim卡的序号,分别为0(卡1)和1(卡2):

1. public int getSimState(int slotID) {  
2. int status = 0;  
3. try {  
4. "getSimState", int.class);  
5. true);  
6.             status = (Integer) mtd.invoke(mTelephonyManager, slotID);  
7. catch (NoSuchMethodException e) {  
8.             e.printStackTrace();  
9. catch (IllegalAccessException e) {  
10.             e.printStackTrace();  
11. catch (IllegalArgumentException e) {  
12.             e.printStackTrace();  
13. catch (InvocationTargetException e) {  
14.             e.printStackTrace();  
15.         }  
16. return status;  
17. }



返回的值是sim卡的状态码,对应值:

1. TelephonyManager.SIM_STATE_READY  
2. TelephonyManager.IM_STATE_ABSENT  
3. TelephonyManager.SIM_STATE_NETWORK_LOCKED  
4. TelephonyManager.SIM_STATE_PIN_REQUIRED  
5. TelephonyManager.SIM_STATE_READY  
6. TelephonyManager.SIM_STATE_UNKNOWN



如果返回的是

1. TelephonyManager.SIM_STATE_READY

那就是可用状态;

2、发送短信

1. private void sendSms(final int which) {  
2. null;  
3.   
4. final SubscriptionManager sManager = (SubscriptionManager) mActivity  
5.                 .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);  
6.   
7.         List<SubscriptionInfo> list = sManager.getActiveSubscriptionInfoList();

1.         if (list.size() == 2) {// double card  
2.             sInfo = list.get(which);  
3. else {//single card  
4. 0);  
5.         }  
6.   
7. if (sInfo != null) {  
8. <span style="white-space:pre">            </span>//provider是对应10086、10010、10000

1. <span style="white-space:pre">            </span>//这个需要根据sik卡的Mcc和Mnc自己判断,这里就不贴出来了  
2. "0"  
3.                     + String.valueOf(sInfo.getMnc()));  
4. int subId = sInfo.getSubscriptionId();  
5. " select provider = " + provider + ", subid = "  
6.                     + subId);  
7.   
8.             SmsManager manager = SmsManager  
9.                     .getSmsManagerForSubscriptionId(subId);  
10.   
11. if (!TextUtils.isEmpty(provider)) {  
12. null, "YE", null, null);  
13. "信息正在发送,请稍候", Toast.LENGTH_SHORT)  
14.                         .show();  
15. else {  
16. "无法正确的获取SIM卡信息,请稍候重试",  
17.                         Toast.LENGTH_SHORT).show();  
18.             }  
19.         }  
20.     }


开发最佳实践与兼容性建议(适配常见问题)

MIUI是基于Android深度定制的操作系统,和Android保持100%兼容,我们准备了一些在Android开发过程中哦给你可能遇到的问题,也许对您有所帮助。

如果在基于MIUI进行开发、测试的过程中遇到问题,我们会竭尽所能协助开发者解决。在和开发者沟通的过程中,我们发现,很多应用遇到的问题,并非因MIUI导致,而是对Android本身。

1.尽量用Android标准的接口,最好不要很“聪明”的读取较为底层的数据

每个手机的底层都有可能有自己独特的实现,这种特殊性,其实是对开发者屏蔽的,开发者直接利用,有时会得不到期望的效果。

比如之前我们发现一款app,会直接读取底层frame buffer,然后以录像的方式显示当前屏幕,但是由于我们frame buffer的特殊性,结果它读出来的就是两三段断开的屏幕。

再比如,有些游戏会直接从底层的读取motion event,然后自己再根据这些事件做些相应操作,但这些事件未经过android处理,结果就有可能有问题。

2.要和Android版本保持一致

Android随着版本的升级,会有些向后兼容性不好。常见现象是,本来在较低版本上正常运行的app,在较高版本上运行失败。

一个常见的问题是权限相关,比如WRITE_APN_SETTINGS这个权限是在某个版本上加进去的,若app不申请此权限,在之前Android版本可正常运行,但是一旦Android升级,app就会因为缺乏权限而FC。

3. NDK版本

有些app可能是用NDK开发的,对于这样的app,一定要在对应的NDK版本下编译测试,否则极有可能出现莫名其妙的问题。

比如,我们之前和某播放器应用联调过一个问题:该播放器在MIUI上播放一段时间后,立即卡死,当时我们调试了好久,怀疑SurfaceFlinger,怀疑播放器本身,等等,各种调试,无果。

最终,还是发现是由于该播放器编译时,NDK版本不对。

4. 一定要释放资源

一些资源,比如WakeLock,WifiLock,File descriptor,Cursor等一定要释放,这些资源甚至会影响到全局。比如WakeLock和WifiLock会影响屏幕和Wifi的休眠,从而导致耗电。

而Cursor,尤其是一些较为常用的Provider获得的Cursor,长期不关闭,有可能会导致该Provider无法工作。

5. 耗电操作

慎用某些对耗电敏感的操作,比如Alarm,比如频繁扫描Wifi,一定要考虑这些操作的极端最坏情况。比如,之前我们手机上某NetworkProvider导致手机空置状态下,比以前成倍的耗电。原因就是,Alarm不断唤醒手机,每次唤醒又不断的扫描Wifi。

对于有后台Service的,确保该service只在必要情况下运行,而不会一直运行,可以用strace查看下app的活动状态

6. 在MIUI上出现问题后,排查的手段
  • 首先看原生系统上有无问题找对应的Nexus 4或者Galaxy Nexus等,看看是否有相同问题,若有,基本确定是app自身问题,否则有可能和MIUI有关
  • MIUI对权限控制较为严格: 若出现问题,可先看看授权管理,打开相应权限
  • 若确定为MIUI问题,可以和我们联系,我们会竭尽全力帮助您解决问题之前我们曾协助啪啪、暴风影音、唱吧以及其它个人开发者或者终端用户调研过遇到的问题,均得到较好的解决方法。

常见问题

1、为什么在Manifest声明了android.permission.INTERNET还是无法访问网络?

安全中心-网络助手里为用户提供了网络控制功能,如果把A应用的移动网络权限或者WIFI网络权限禁用了,那么在调用网络请求的时候会抛出异常:Java.NET.ConnectException: socket failed: EACCES (Permission denied)

2、为什么无法访问环回地址(127.0.0.1)?

安全中心-网络助手里为用户提供了网络控制功能,如果把A应用的移动网络权限禁用,则该应用访问环回地址失败。

3、为什么我的应用在开启骚扰拦截之后收不到验证短信?

骚扰拦截有智能引擎的判断,在开启智能拦截后我们会识别某些带有骚扰短信特征的短信。如果您认为您的短信被误判,可以联系我们。strong text####4、为什么我的应用发起的回拨电话会被拦截?回拨电话有两种:一种是空号码,骚扰拦截有空号码拦截,在用户手动设置之后会拦截空号码。一种是正常号码,骚扰拦截有标记拦截的功能,在开启标记拦截且该号码被多次标记拉黑则会被拦截。

5、为什么我的应用申请使用su命令会失败?

一、MIUI的稳定版没有root权限。二、开发版有root权限,但是受手机端App安全中心控制。如果您需要您的应用开启某项权限,可以引导用户跳转应用权限管理页面由用户手动开启。Intent intent = new Intent();intent.setAction("miui.intent.action.ROOT_MANAGER");intent.addCategory(Intent.CATEGORY_DEFAULT);三、一些应用在获取root权限后,会修改系统的su等文件,导致其他应用的root不可用。

6、为什么我在Manifest声明了权限,依然不能控制Wifi,Gps,显示悬浮窗等?

安全中心会控制权限的使用,如果需要开放某个权限,可以在安全中心-授权管理-应用权限管理内修改。我们会根据应用的主要功能开放权限,如果您的应用有权限控制方面的问题,请联系我们。

7、如何获取某项权限是否开启?

暂时没有这个查询接口,如果您需要您的应用开启某项权限,可以引导用户跳转应用权限管理页面由用户手动开启。Intent intent = new Intent();intent.setAction("miui.intent.action.APP_PERM_EDITOR");intent.addCategory(Intent.CATEGORY_DEFAULT);intent.putExtra("extra_pkgname", "应用包名");

8、为什么我的Alarm不太精确?

Google和MIUI都启用了对齐唤醒功能,会把一小段时间内的Alarm对齐到某个Alarm的时间点一起执行,达到省电的目的。

9、我的应用为什么不能自启动?

在MIUI上应用的自启动由用户进行控制,默认不开放自启动权限,其中自启动包含开机自启动和接收系统广播等方式启动,但是由A应用启动B应用则不受限制。如果您需要您的应用自启动,可以引导用户跳转自启动管理页面由用户手动开启。Intent intent = new Intent();intent.setAction("miui.intent.action.OP_AUTO_START");intent.addCategory(Intent.CATEGORY_DEFAULT);

10、如何在快捷方式图标上显示未读消息的数字?

请参看:Android系统 小米/三星/索尼快键图标BadgeNumber数字提醒

11、如何将我的音乐播放器控件集成到MIUI自带的通知栏音乐控制中心去?

请参看:MIUI系统音乐控件标准化方案,第三方APP接入指南

12、我的应用在小米应用商店审核失败怎么办?

关于应用审核问题、认领问题、开发者邮箱认证问题,以及其它关于小米应用商店的运营问题(除开发中遇到的问题),请联系小米应用商店开发者支持邮箱:developer@xiaomi.com

13、添加了MIUI提供的沉浸式代码后发现软件盘是否弹出的状态获取不到以及android:windowSoftInputMode="adjustResize" 的设置无作用,该怎么解决?

这个问题是android原生的问题,我们的MIUISDK已经解决。如果使用MIUISDK则不会出现此问题。如果是在原生系统上开发,可以通过如下参考办法绕过adjustResize无效,参考办法:输入法原来沉浸的方法继续加上,然后在布局view上面设置setFitSystemWindow属性为true,这样 resize属性会生效。但是view的顶部会预留出来状态栏的高度。 再重写界面根view(应用xml布局的顶层view)的fitSystemWindow函数, 将顶部的padding去掉。 有点绕,但是效果出来是对的。

14、据说双卡双待的功能不是安卓原生的功能,现在我需要调用系统拨打电话但没有办法控制使用那个卡来拨打,我该怎么解决?

原生android在5.1之前本身是没有双卡方案,所以5.1之前的所有双卡方案都是随着平台的不同而不同的。建议就按正常的单卡呼叫方案进行,理论上会给用户提示选择用哪个卡进行呼叫。而在原生android5.1及以后,android原生支持了双卡,这个将是业界标准接口,按google方案即可。MIUI在开发的时候有一个原则是,原生的所有对外基本接口,绝对不会修改。

15、如何调用小米4的红外控制接口发送红外数据?

请参看:https://developer.android.com/reference/android/hardware/ConsumerIrManager.html

16、MIUI 中的蓝牙2.0和android 原生中的蓝牙2.0有什么兼容性问题吗?

请参看:http://developer.android.com/guide/topics/connectivity/bluetooth.html

17、在SSL协议握手过程中出现的exception,该怎么解决?

可以通过如下方法排查:1. 模拟器里网络设置的是否正常,是否能上其他https的网站。2. 换个时间点试试,有可能是服务器端的问题3. 更新下/system/lib/libssl.so文件

18、如何调用MIUI 6沉浸式状态栏?

请参看:MIUI 6 沉浸式状态栏调用方法

19、如何解决app在浅色背景的主题通知栏看不清通知的问题?如何解决默认系统通知栏处部分app字体颜色显示不明显问题?

在MIUI系统中,通知栏的每一条通知的字体颜色(包括标题、主次要文字、时间等)均使用原生Android规范,并未系统定义,故,建议各app参照原生Android规范来写字体,保证当主题修改原生Android字体颜色时,各app的通知颜色可随之调整。

如下内容请转达给相应开发处理。

要想文字跟随主题变化,TextView需要用android原生的style比如标题的Textview可以加上android:textAppearance="@android:style/TextAppearance.StatusBar.EventContent.Title"

如果以上信息没有对您有帮助的信息请您使用公司域名邮箱务必按照如下模板填写您反馈的问题,

发送到第三方应用开发者反馈邮箱 miui-appfeedback@xiaomi.com

第三方应用开发者问题反馈模板


开发最佳实践与兼容性建议(适配常见问题)

MIUI是基于Android深度定制的操作系统,和Android保持100%兼容,我们准备了一些在Android开发过程中哦给你可能遇到的问题,也许对您有所帮助。

如果在基于MIUI进行开发、测试的过程中遇到问题,我们会竭尽所能协助开发者解决。在和开发者沟通的过程中,我们发现,很多应用遇到的问题,并非因MIUI导致,而是对Android本身。

1.尽量用Android标准的接口,最好不要很“聪明”的读取较为底层的数据

每个手机的底层都有可能有自己独特的实现,这种特殊性,其实是对开发者屏蔽的,开发者直接利用,有时会得不到期望的效果。

比如之前我们发现一款app,会直接读取底层frame buffer,然后以录像的方式显示当前屏幕,但是由于我们frame buffer的特殊性,结果它读出来的就是两三段断开的屏幕。

再比如,有些游戏会直接从底层的读取motion event,然后自己再根据这些事件做些相应操作,但这些事件未经过android处理,结果就有可能有问题。

2.要和Android版本保持一致

Android随着版本的升级,会有些向后兼容性不好。常见现象是,本来在较低版本上正常运行的app,在较高版本上运行失败。

一个常见的问题是权限相关,比如WRITE_APN_SETTINGS这个权限是在某个版本上加进去的,若app不申请此权限,在之前Android版本可正常运行,但是一旦Android升级,app就会因为缺乏权限而FC。

3. NDK版本

有些app可能是用NDK开发的,对于这样的app,一定要在对应的NDK版本下编译测试,否则极有可能出现莫名其妙的问题。

比如,我们之前和某播放器应用联调过一个问题:该播放器在MIUI上播放一段时间后,立即卡死,当时我们调试了好久,怀疑SurfaceFlinger,怀疑播放器本身,等等,各种调试,无果。

最终,还是发现是由于该播放器编译时,NDK版本不对。

4. 一定要释放资源

一些资源,比如WakeLock,WifiLock,File descriptor,Cursor等一定要释放,这些资源甚至会影响到全局。比如WakeLock和WifiLock会影响屏幕和Wifi的休眠,从而导致耗电。

而Cursor,尤其是一些较为常用的Provider获得的Cursor,长期不关闭,有可能会导致该Provider无法工作。

5. 耗电操作

慎用某些对耗电敏感的操作,比如Alarm,比如频繁扫描Wifi,一定要考虑这些操作的极端最坏情况。比如,之前我们手机上某NetworkProvider导致手机空置状态下,比以前成倍的耗电。原因就是,Alarm不断唤醒手机,每次唤醒又不断的扫描Wifi。

对于有后台Service的,确保该service只在必要情况下运行,而不会一直运行,可以用strace查看下app的活动状态

6. 在MIUI上出现问题后,排查的手段
  • 首先看原生系统上有无问题找对应的Nexus 4或者Galaxy Nexus等,看看是否有相同问题,若有,基本确定是app自身问题,否则有可能和MIUI有关
  • MIUI对权限控制较为严格: 若出现问题,可先看看授权管理,打开相应权限
  • 若确定为MIUI问题,可以和我们联系,我们会竭尽全力帮助您解决问题之前我们曾协助啪啪、暴风影音、唱吧以及其它个人开发者或者终端用户调研过遇到的问题,均得到较好的解决方法。

常见问题

1、为什么在Manifest声明了android.permission.INTERNET还是无法访问网络?

安全中心-网络助手里为用户提供了网络控制功能,如果把A应用的移动网络权限或者WIFI网络权限禁用了,那么在调用网络请求的时候会抛出异常:Java.NET.ConnectException: socket failed: EACCES (Permission denied)

2、为什么无法访问环回地址(127.0.0.1)?

安全中心-网络助手里为用户提供了网络控制功能,如果把A应用的移动网络权限禁用,则该应用访问环回地址失败。

3、为什么我的应用在开启骚扰拦截之后收不到验证短信?

骚扰拦截有智能引擎的判断,在开启智能拦截后我们会识别某些带有骚扰短信特征的短信。如果您认为您的短信被误判,可以联系我们。strong text####4、为什么我的应用发起的回拨电话会被拦截?回拨电话有两种:一种是空号码,骚扰拦截有空号码拦截,在用户手动设置之后会拦截空号码。一种是正常号码,骚扰拦截有标记拦截的功能,在开启标记拦截且该号码被多次标记拉黑则会被拦截。

5、为什么我的应用申请使用su命令会失败?

一、MIUI的稳定版没有root权限。二、开发版有root权限,但是受手机端App安全中心控制。如果您需要您的应用开启某项权限,可以引导用户跳转应用权限管理页面由用户手动开启。Intent intent = new Intent();intent.setAction("miui.intent.action.ROOT_MANAGER");intent.addCategory(Intent.CATEGORY_DEFAULT);三、一些应用在获取root权限后,会修改系统的su等文件,导致其他应用的root不可用。

6、为什么我在Manifest声明了权限,依然不能控制Wifi,Gps,显示悬浮窗等?

安全中心会控制权限的使用,如果需要开放某个权限,可以在安全中心-授权管理-应用权限管理内修改。我们会根据应用的主要功能开放权限,如果您的应用有权限控制方面的问题,请联系我们。

7、如何获取某项权限是否开启?

暂时没有这个查询接口,如果您需要您的应用开启某项权限,可以引导用户跳转应用权限管理页面由用户手动开启。Intent intent = new Intent();intent.setAction("miui.intent.action.APP_PERM_EDITOR");intent.addCategory(Intent.CATEGORY_DEFAULT);intent.putExtra("extra_pkgname", "应用包名");

8、为什么我的Alarm不太精确?

Google和MIUI都启用了对齐唤醒功能,会把一小段时间内的Alarm对齐到某个Alarm的时间点一起执行,达到省电的目的。

9、我的应用为什么不能自启动?

在MIUI上应用的自启动由用户进行控制,默认不开放自启动权限,其中自启动包含开机自启动和接收系统广播等方式启动,但是由A应用启动B应用则不受限制。如果您需要您的应用自启动,可以引导用户跳转自启动管理页面由用户手动开启。Intent intent = new Intent();intent.setAction("miui.intent.action.OP_AUTO_START");intent.addCategory(Intent.CATEGORY_DEFAULT);

10、如何在快捷方式图标上显示未读消息的数字?

请参看:Android系统 小米/三星/索尼快键图标BadgeNumber数字提醒

11、如何将我的音乐播放器控件集成到MIUI自带的通知栏音乐控制中心去?

请参看:MIUI系统音乐控件标准化方案,第三方APP接入指南

12、我的应用在小米应用商店审核失败怎么办?

关于应用审核问题、认领问题、开发者邮箱认证问题,以及其它关于小米应用商店的运营问题(除开发中遇到的问题),请联系小米应用商店开发者支持邮箱:developer@xiaomi.com

13、添加了MIUI提供的沉浸式代码后发现软件盘是否弹出的状态获取不到以及android:windowSoftInputMode="adjustResize" 的设置无作用,该怎么解决?

这个问题是android原生的问题,我们的MIUISDK已经解决。如果使用MIUISDK则不会出现此问题。如果是在原生系统上开发,可以通过如下参考办法绕过adjustResize无效,参考办法:输入法原来沉浸的方法继续加上,然后在布局view上面设置setFitSystemWindow属性为true,这样 resize属性会生效。但是view的顶部会预留出来状态栏的高度。 再重写界面根view(应用xml布局的顶层view)的fitSystemWindow函数, 将顶部的padding去掉。 有点绕,但是效果出来是对的。

14、据说双卡双待的功能不是安卓原生的功能,现在我需要调用系统拨打电话但没有办法控制使用那个卡来拨打,我该怎么解决?

原生android在5.1之前本身是没有双卡方案,所以5.1之前的所有双卡方案都是随着平台的不同而不同的。建议就按正常的单卡呼叫方案进行,理论上会给用户提示选择用哪个卡进行呼叫。而在原生android5.1及以后,android原生支持了双卡,这个将是业界标准接口,按google方案即可。MIUI在开发的时候有一个原则是,原生的所有对外基本接口,绝对不会修改。

15、如何调用小米4的红外控制接口发送红外数据?

请参看:https://developer.android.com/reference/android/hardware/ConsumerIrManager.html

16、MIUI 中的蓝牙2.0和android 原生中的蓝牙2.0有什么兼容性问题吗?

请参看:http://developer.android.com/guide/topics/connectivity/bluetooth.html

17、在SSL协议握手过程中出现的exception,该怎么解决?

可以通过如下方法排查:1. 模拟器里网络设置的是否正常,是否能上其他https的网站。2. 换个时间点试试,有可能是服务器端的问题3. 更新下/system/lib/libssl.so文件

18、如何调用MIUI 6沉浸式状态栏?

请参看:MIUI 6 沉浸式状态栏调用方法

19、如何解决app在浅色背景的主题通知栏看不清通知的问题?如何解决默认系统通知栏处部分app字体颜色显示不明显问题?

在MIUI系统中,通知栏的每一条通知的字体颜色(包括标题、主次要文字、时间等)均使用原生Android规范,并未系统定义,故,建议各app参照原生Android规范来写字体,保证当主题修改原生Android字体颜色时,各app的通知颜色可随之调整。

如下内容请转达给相应开发处理。

要想文字跟随主题变化,TextView需要用android原生的style比如标题的Textview可以加上android:textAppearance="@android:style/TextAppearance.StatusBar.EventContent.Title"

如果以上信息没有对您有帮助的信息请您使用公司域名邮箱务必按照如下模板填写您反馈的问题,

发送到第三方应用开发者反馈邮箱 miui-appfeedback@xiaomi.com

第三方应用开发者问题反馈模板