基于android N MTK 平台
本文主要记录从 dialer 的 dialpad 输入特殊的字符串启动工厂模式的流程。
整体流程图
部分方法介绍
DialpadFragment.afterTextChanged
因为 DialpadFragment 实现了 TextWatcher 接口,并实现了 afterTextChanged 方法,当dialpad里面edittext 控件中内容改变时会回调这个方:
@Override
public void afterTextChanged(Editable input) {
/// M: avoid NPE if this callback is called after activity finished @{
if (getActivity() == null) {
return;
}
/// @}
// When DTMF dialpad buttons are being pressed, we delay SpecialCharSequenceMgr sequence,
// since some of SpecialCharSequenceMgr's behavior is too abrupt for the "touch-down"
// behavior.
if (!mDigitsFilledByIntent &&
SpecialCharSequenceMgr.handleChars(getActivity(), input.toString(), mDigits)) { //对特殊字符串处理
// A special sequence was entered, clear the digits
mDigits.getText().clear(); //处理完后清空内容
}
if (isDigitsEmpty()) {
mDigitsFilledByIntent = false;
mDigits.setCursorVisible(false);
}
if (mDialpadQueryListener != null) {
mDialpadQueryListener.onDialpadQueryChanged(mDigits.getText().toString());
}
updateDeleteButtonEnabledState();
}
SpecialCharSequenceMgr.handleSecretCode
SpecialCharSequenceMgr 这个类是dialer 专门处理特殊字符串的。
/**
* Handles secret codes to launch arbitrary activities in the form of *#*#<code>#*#*.
* If a secret code is encountered an Intent is started with the android_secret_code://<code>
* URI.
*
* @param context the context to use
* @param input the text to check for a secret code in
* @return true if a secret code was encountered
*/
static boolean handleSecretCode(Context context, String input) {
// Secret codes are in the form *#*#<code>#*#*
/// M: for plug-in @{
input = ExtensionManager.getInstance().getDialPadExtension().handleSecretCode(input);//根据不同的运营商可以对输入的特殊字符串再做一次处理,运营商客制化可以在这里整
/// @}
int len = input.length();
if (len > 8 && input.startsWith("*#*#") && input.endsWith("#*#*")) {//判断是不是*#*#<code>#*#*这种格式的输入
final Intent intent = new Intent(SECRET_CODE_ACTION,//private static final String SECRET_CODE_ACTION = "android.provider.Telephony.SECRET_CODE";
Uri.parse("android_secret_code://" + input.substring(4, len - 4)));//code
context.sendBroadcast(intent);//通过广播的形式发出
return true;
}
return false;
}
EngineerModeReceiver.onReceive
EngineerModeReceiver MMI的一个广播接受者,负者启动主界面。
<receiver
android:name=".EngineerModeReceiver"
android:exported="true" >
<intent-filter>
<action android:name="android.provider.Telephony.SECRET_CODE" />
<data
android:host="13646633"
android:scheme="android_secret_code" />
</intent-filter>
</receiver>
private static final String TAG = "EM/SECRET_CODE";
private static final String SECRET_CODE_ACTION = "android.provider.Telephony.SECRET_CODE";
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == null) {
Log.i("@M_" + TAG, "Null action");
return;
}
if (intent.getAction().equals(SECRET_CODE_ACTION)) {
Uri uri = intent.getData();
Log.i("@M_" + TAG, "getIntent success in if");
if (uri.equals(mEmUri)) {//在这里设置过滤的特殊code,满足要求就启动界面
Intent intentEm = new Intent(context, EngineerMode.class);//启动界面
intentEm.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Log.i("@M_" + TAG, "Before start EM activity");
context.startActivity(intentEm);
} else if (uri.equals(mEmbmsEnableUri)) {
Toast.makeText(context,
"eMBMS is enabled. Please reboot", Toast.LENGTH_LONG).show();
SystemProperties.set(EMBMS_SYTEM_PROPERTIES, "1");
} else if (uri.equals(mEmbmsDisableUri)) {
Toast.makeText(context,
"eMBMS is disabled. Please reboot", Toast.LENGTH_LONG).show();
SystemProperties.set(EMBMS_SYTEM_PROPERTIES, "0");
} else {
Log.i("@M_" + TAG, "No matched URI!");
}
} else {
Log.i("@M_" + TAG, "Not SECRET_CODE_ACTION!");
}
}