源码分析之Android通过Dialer实现暗码启动

2024-09-06 09:08

本文主要是介绍源码分析之Android通过Dialer实现暗码启动,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目前接触比较多的就是通过dialer应用来启动/触发暗码。

也有通过Calculator来实现的。

本文以Dialer为例,

1.经过调试定位,发现拨号盘接对应的Activity为DialtactsActivity。

2.DialtactsActivity中有个showDialpadFragment方法,用来加载显示拨号盘,因为有可能此时拨号盘正处于收缩/隐藏状态。

    /*** 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 Fragmentimplements 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进行匹配处理。

    public static boolean handleChars(Context context, String input, EditText textField) {//get rid of the separators so that the string gets parsed correctlyString 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 *#*#<code>#*#*./// @}/// M: for plug-in @{|| ExtensionManager.getInstance().getDialPadExtension().handleChars(context,dialString)/// @}) {return true;}return false;}
5.接下来分开两种讲,一种是直接弹出对话框的那种,类如*#06#,另一种则是调起别的应用等方式。
5.1 )*#*#<code>#*#*

    /*** 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("#*#*")) {final Intent intent = new Intent(SECRET_CODE_ACTION,Uri.parse("android_secret_code://" + input.substring(4, len - 4)));///android_secret_code://287context.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

        <receiverandroid:name=".EngineerModeReceiver"android:exported="true" ><intent-filter><action android:name="android.provider.Telephony.SECRET_CODE" /><dataandroid: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

    // 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<String> deviceIds = new ArrayList<String>();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启动相关应用

    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方式启动暗码的大致源码流程分析。


这篇关于源码分析之Android通过Dialer实现暗码启动的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1141592

相关文章

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

springboot3打包成war包,用tomcat8启动

1、在pom中,将打包类型改为war <packaging>war</packaging> 2、pom中排除SpringBoot内置的Tomcat容器并添加Tomcat依赖,用于编译和测试,         *依赖时一定设置 scope 为 provided (相当于 tomcat 依赖只在本地运行和测试的时候有效,         打包的时候会排除这个依赖)<scope>provided

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

内核启动时减少log的方式

内核引导选项 内核引导选项大体上可以分为两类:一类与设备无关、另一类与设备有关。与设备有关的引导选项多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导选项。比如,如果你想知道可以向 AHA1542 SCSI 驱动程序传递哪些引导选项,那么就查看 drivers/scsi/aha1542.c 文件,一般在前面 100 行注释里就可以找到所接受的引导选项说明。大多数选项是通过"_