Android拨号盘特殊字符串(例如*#06#显示IMEI或者MEID)处理的类是:
packages/apps/Dialer/src/com/android/dialer/SpecialCharSequenceMgr.java,入口是handleChars,这个方法在拨号盘EditText字符有变化的时候会调用:
public static boolean handleChars(Context context, String input, EditText textField) {
//get rid of the separators so that the string gets parsed correctly
String dialString = PhoneNumberUtils.stripSeparators(input);
if (ZteEngineerCode.handleZteEngineerCode(context, dialString)
|| handleDeviceIdDisplay(context, dialString)
|| handleRegulatoryInfoDisplay(context, dialString)
|| handlePinEntry(context, dialString)
|| handleAdnEntry(context, dialString, textField)
|| ZteEngineerCode.handleZteEngineerCode(context, dialString)
|| handleSecretCode(context, dialString)
/// M: for plug-in @{
|| ExtensionManager.getInstance().getDialPadExtension().handleChars(context,
dialString)
/// @}
) {
return true;
}
return false;
}
一个有多个处理函数组成的if判断语句作为主体,只有有一个方法返回true就返回。
static boolean handleDeviceIdDisplay(Context context, String input) {
TelephonyManager telephonyManager =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if (telephonyManager != null && input.equals(MMI_IMEI_DISPLAY)) {
int labelResId = (telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) ?
R.string.imei : R.string.meid;
List deviceIds = new ArrayList();
for (int slot = 0; slot < telephonyManager.getPhoneCount(); slot++) {
String deviceId = telephonyManager.getDeviceId(slot);
if (!TextUtils.isEmpty(deviceId)) {
deviceIds.add(deviceId);
}
}
/// M: Add single IMEI plugin. @{
deviceIds = ExtensionManager.getInstance().getDialPadExtension().getSingleIMEI(
deviceIds);
/// @}
AlertDialog alert = new AlertDialog.Builder(context)
.setTitle(labelResId)
.setItems(deviceIds.toArray(new String[deviceIds.size()]), null)
.setPositiveButton(android.R.string.ok, null)
.setCancelable(false)
.show();
return true;
}
return false;
}拿*#06#举例,使用TelephonyManager获取相应信息后弹出AlertDialog显示。
ZteEngineerCode是mtk相关的暗码处理类,流程类似handleChars,单独类分离出去不和原生代码掺杂在一起
handleRegulatoryInfoDisplay处理*#07#,发送了个Intent出去,处理该intent的是设置中的代码:
android:label="@string/regulatory_information"
android:taskAffinity=""
android:enabled="@bool/config_show_regulatory_info">
android:value="true" />
显示手机相关的一些信息,不过我看源码中这个相关字符串是空的,实际手机验证啥也没弹出来,activity收到intent后会马上关闭。handlePinEntry处理一些Mmi码,详细见MMI SS USSD扫盲贴:
static boolean handlePinEntry(final Context context, final String input) {
if ((input.startsWith("**04") || input.startsWith("**05")) && input.endsWith("#")) {
...
return TelecomUtil.handleMmi(context, input, null);
...
}
**04和**05开头的mmi码都是设置pin的,所以该方法有pin这个字眼,很少人知道有个东西吧。
handleAdnEntry,adn就是卡联系人,输入数字(1~4位)加#结束,拨号盘会自动加载sim卡对应index卡联系人的号码(如果有的话)
handleSecretCode发送一个广播,*#*#开头和#*#*结尾的字符串都会看成是secretcode:
static boolean handleSecretCode(Context context, String input) {
// Secret codes are in the form *#*##*#*
...
int len = input.length();
if (len > 8 && input.startsWith("*#*#") && input.endsWith("#*#*")) {
final Intent intent = new Intent(SECRET_CODE_ACTION,
Uri.parse("android_secret_code://" + input.substring(4, len - 4)));
context.sendBroadcast(intent);
return true;
}
return false;
}还是设置中的例子,*#*#4636#*#*可以开启一个activity,显示手机很多信息,如注册的网络信息,电池信息,wifi信息等。
如果需要加入暗码需求统一使用广播模式是最好的,不用更改代码其它应用就可以有暗码入口,不过可惜运营商定制机器有很多强制要实现的暗码。