转载请注明出处:https://blog.csdn.net/turtlejj/article/details/83898624,谢谢~
以前遇到过用户报市场问题,手机的通知中心一直显示用户当前Sim卡设置了无条件呼叫转移,但其实呼入的电话可以正常接到,进入电话设置页面查看,发现呼叫转移的SwitchButton也处于关闭状态。最后通过log发现,用户的Sim卡被设置了serviceClass为"SERVICE_CLASS_DATA_SYNC"的无条件呼叫转移。电话设置页面仅仅过滤出serviceClass为"SERVICE_CLASS_VOICE"的呼叫转移,因此SwitchButton处于关闭状态;但通知中心并没有对serviceClass进行过滤,所以显示用户设置了无条件呼叫转移。
对通知中心的代码添加过滤很容易,但用户的问题没办法通过通常的UI操作来解决,因为我们的手机在常规的操作下,serviceClass默认都是"SERVICE_CLASS_VOICE"。为此,我特地去研究了一下如何通过MMI Code来帮助用户取消这个不正常的呼叫转移状态。
用于解析补充业务(Supplementary Service) MMI Code的核心代码都在frameworks/opt/telephony仓库下的GsmMmiCode.java文件中。
首先,我们要知道手机是如何识别MMI码的。这里涉及了正则表达式的知识。
// See TS 22.030 6.5.2 "Structure of the MMI"
static Pattern sPatternSuppService = Pattern.compile(
"((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#)(.*)");
/* 1 2 3 4 5 6 7 8 9 10 11 12
1 = Full string up to and including #
2 = action (activation/interrogation/registration/erasure)
3 = service code
5 = SIA
7 = SIB
9 = SIC
10 = dialing number
*/
没学过正则表达式的同学估计要看懵了,这是什么鬼东西,感觉像是胡乱按键盘打出来的。但其实,正则表达式是按照一定规范编写出来,用来匹配一定格式的字符串用的,下面我们就来看看它是怎么工作的。
关于Java中使用正则表达式的方法,我们这里不多说,不清楚的同学可以参考《Java 正则表达式》,里面详细介绍了正则表达式的匹配方法。
回到代码中,我们一步一步分解来看。
首先,使用"(\\*|#|\\*#|\\*\\*|##)",匹配以"*" "#" "*#" "**" 或 "##" 开头的字符串(其中,"\"为转义字符,"|"代表"或")。
第二步,使用"(\\d{2,3})",匹配一个2位或者3位的数字(其中,"\d"用来匹配数字,{2,3}表示最少匹配2次,至多匹配3次)。
第三步,使用(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#,匹配最多连续四组以*开头,其余部分为除了*或#以外的字符串。这一部分的结尾匹配一个"#"。
这里有一点儿不太容易看明白,但其实,可以观察到,这里其实是由好几个"\\*([^*#]*)"嵌套在一起组成的,拆分来说明一下:
"\\*",不用多说,用来匹配一个"*"字符。
([^*#]*),其中前半部分的"[^*#]"用来匹配除了*或#以外的任意单个字符;最后面的"*"表示,对前面的[^*#]匹配零次或多次