Android 系统(125)---Android通过Dialer实现暗码启动
16lz
2021-01-23
Android通过Dialer实现暗码启动
目前接触比较多的就是通过dialer应用来启动/触发暗码。
本文以Dialer为例,
1.经过调试定位,发现拨号盘接对应的Activity为DialtactsActivity。
2.DialtactsActivity中有个showDialpadFragment方法,用来加载显示拨号盘,因为有可能此时拨号盘正处于收缩/隐藏状态。
[java] view plain copy- /**
- * Initiates a fragment transaction to show the dialpad fragment. Animations and other visual
- * updates are handled by a callback which is invoked after the dialpad fragment is shown.
- * @see #onDialpadShown
- */
- private void showDialpadFragment(boolean animate) {
- if (mIsDialpadShown || mStateSaved) {
- return;
- }
- mIsDialpadShown = true;
- mListsFragment.setUserVisibleHint(false);
- final FragmentTransaction ft = getFragmentManager().beginTransaction();
- if (mDialpadFragment == null) {
- mDialpadFragment = new DialpadFragment();
- ft.add(R.id.dialtacts_container, mDialpadFragment, TAG_DIALPAD_FRAGMENT);
- } else {
- ft.show(mDialpadFragment);
- }
- //mDialpadFragment.setAnimate(animate);
- AnalyticsUtil.sendScreenView(mDialpadFragment);
- ft.commit();
- maybeEnterSearchUi();
- if (animate) {
- mFloatingActionButtonController.scaleOut();
- } else {
- mFloatingActionButtonController.setVisible(false);
- }
- mActionBarController.onDialpadUp();
- mListsFragment.getView().animate().alpha(0).withLayer();
- }
3.接下来重点处理实现就在DialpapFragment中,首先来看类的声明/继承。
import com.android.dialer.dialpad.DialpadFragment;
- /**
- * Fragment that displays a twelve-key phone dialpad.
- */
- public class DialpadFragment extends Fragment
- implements View.OnClickListener,
- View.OnLongClickListener, View.OnKeyListener,
- AdapterView.OnItemClickListener, TextWatcher,
- PopupMenu.OnMenuItemClickListener,
- DialpadKeyButton.OnPressedListener,
- /// M: add for plug-in @{
- DialpadExtensionAction {
从以上类实现/继承中可以发现,其继承了TextWatcher类,也正是这个类使之能够监听实现输入变化。
TextWatcher有3个重要方法,分别为:beforeTextChanged,onTextChanged和afterTextChanged。分别看下面那份源码。
onTextChanged
其中最重点的是afterTextChanged方法,其调用了SpecialCharSequenceMgr辅助工具类的handleChars方法。
4.handleChars方法中,会对各种特殊的secret code进行匹配处理。
[java] view plain copy- 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 (handleDeviceIdDisplay(context, dialString) //*#06#
- || handleRegulatoryInfoDisplay(context, dialString)
- || handlePinEntry(context, dialString)
- || handleAdnEntry(context, dialString, textField)
- || handleSecretCode(context, dialString) //for the form of *#*#
#*#*.
- /// @}
- /// M: for plug-in @{
- || ExtensionManager.getInstance().getDialPadExtension().handleChars(context,
- dialString)
- /// @}
- ) {
- return true;
- }
- return false;
- }
5.1 )*#*#
#*#* [java] view plain copy - /**
- * Handles secret codes to launch arbitrary activities in the form of *#*#
#*#*.
- * If a secret code is encountered an Intent is started with the android_secret_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 *#*#
#*#*
-
- /// M: for plug-in @{
- input = ExtensionManager.getInstance().getDialPadExtension().handleSecretCode(input);
- /// @}
-
- 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)));///"font-family:Arial, Helvetica, sans-serif;">android_secret_code://287
- context.sendBroadcast(intent);
- return true;
- }
-
- return false;
- }
有以上代码可知,最终是通过broadcast发送出去的,并往intent里面加载了2种数据:Uri和Action。 Action:
private static final String SECRET_CODE_ACTION = "android.provider.Telephony.SECRET_CODE";
接受端的注册方式,Action 和 data必须和发送的broadcast相匹配才行: /vendor/mediatek/proprietary/packages/apps/EngineerMode/AndroidManifest.xml
[html] view plain copy - <receiver
- android:name=".EngineerModeReceiver"
- android:exported="true" >
- <intent-filter>
- <action android:name="android.provider.Telephony.SECRET_CODE" />
- <data
- android:host="3646633"
- android:scheme="android_secret_code" />
- intent-filter>
- receiver>
/vendor/mediatek/proprietary/packages/apps/EngineerMode/src/com/mediatek/engineermode/EngineerModeReceiver.java
由上面代码可知,这就对应上了,在Receiver接受到广播后,启动对应的应用/Activity来处理接下来的工作。
5.2 )*#06# 直接在Context中弹出对话框,显示IMEI信息
/packages/apps/Dialer/src/com/android/dialer/SpecialCharSequenceMgr.java
[java] view plain copy - // TODO: Use TelephonyCapabilities.getDeviceIdLabel() to get the device id label instead of a
- // hard-coded string.
- 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(); - if (TelephonyManagerCompat.getPhoneCount(telephonyManager) > 1 &&
- CompatUtils.isMethodAvailable(TelephonyManagerCompat.TELEPHONY_MANAGER_CLASS,
- "getDeviceId", Integer.TYPE)) {
- for (int slot = 0; slot < telephonyManager.getPhoneCount(); slot++) {
- String deviceId = telephonyManager.getDeviceId(slot);
- if (!TextUtils.isEmpty(deviceId)) {
- deviceIds.add(deviceId);
- }
- }
- } else {
- deviceIds.add(telephonyManager.getDeviceId());
- }
-
- 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();///直接在Context中弹出对话框,显示IMEI信息
- return true;
- }
- return false;
- }
*#07# 直接通过隐式intent启动相关应用 [java] view plain copy - private static boolean handleRegulatoryInfoDisplay(Context context, String input) {
- if (input.equals(MMI_REGULATORY_INFO_DISPLAY)) {
- Log.d(TAG, "handleRegulatoryInfoDisplay() sending intent to settings app");
- Intent showRegInfoIntent = new Intent(Settings.ACTION_SHOW_REGULATORY_INFO);
- try {
- context.startActivity(showRegInfoIntent);
- } catch (ActivityNotFoundException e) {
- Log.e(TAG, "startActivity() failed: " + e);
- }
- return true;
- }
- return false;
- }
以上就是Android通过Dialer方式启动暗码的大致源码流程分析。
更多相关文章
- CardView 添加背景图片、改变颜色、水波纹效果的方法
- Android高手进阶教程(十一)--Android 通用获取Ip的方法(判断手机
- Android Studio之工程中导入jni库方法
- Android取消EditText自动聚焦、自动弹出输入法的方法
- 转-Android Studio *.jar 与 *.aar 的生成与*.aar导入项目方法
- Android IPC机制(二):AIDL的基本使用方法
- 在PC端进行android截屏的多种方法
- Android在线更新SDK的方法(使用国内镜像)
随机推荐