原标题:Android 装逼技术之暗码启动应用
公众号回复关键字「1024」有惊喜
什么是暗码?
在拨号盘中输入*#*##*#*后,APP 可以监控到这些输入,然后做相应的动作,比如启动应用,是不是有点骚。
下面看下这个骚操作是如何实现的。
效果预览
源码DialtactsActivity#showDialpadFragment
DialtactsActivity 中有个 showDialpadFragment 方法,用来加载显示拨号盘,因此入口就从 showDialpadFragment 看起,基于 Android P 分析。
privatevoidshowDialpadFragment(booleananimate){
//……
finalFragmentTransaction ft = getFragmentManager.beginTransaction;
if(dialpadFragment == null) {
dialpadFragment = newDialpadFragment;
ft.add(R.id.dialtacts_container, dialpadFragment, TAG_DIALPAD_FRAGMENT);
} else{
ft.show(dialpadFragment);
}
//……
}
具体实现在 DialpapFragment 中,看到 DialpapFragment 实现了 TextWatcher,TextWatcher 有 3 个重要方法,分别为:beforeTextChanged,onTextChanged 和 afterTextChanged,重点看 afterTextChanged 方法。
DialpadFragment#afterTextChangedpublicclassDialpadFragmentextendsFragment
implementsView.OnClickListener,
View.OnLongClickListener,
View.OnKeyListener,
AdapterView.OnItemClickListener,
TextWatcher,
PopupMenu.OnMenuItemClickListener,
DialpadKeyButton.OnPressedListener{
//……
@Override
publicvoidafterTextChanged(Editable input){
// 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(!digitsFilledByIntent
&& SpecialCharSequenceMgr.handleChars(getActivity, input.toString, digits)) {
// A special sequence was entered, clear the digits
digits.getText.clear;
}
if(isDigitsEmpty) {
digitsFilledByIntent = false;
digits.setCursorVisible( false);
}
if(dialpadQueryListener != null) {
dialpadQueryListener.onDialpadQueryChanged(digits.getText.toString);
}
updateDeleteButtonEnabledState;
}
//……
}
这里调用了 SpecialCharSequenceMgr 辅助工具类的 handleChars 方法,看这个方法。
SpecialCharSequenceMgr#handleCharspublicstaticbooleanhandleChars(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)
|| handleRegulatoryInfoDisplay(context, dialString)
|| handlePinEntry(context, dialString)
|| handleAdnEntry(context, dialString, textField)
|| handleSecretCode(context, dialString)) {
returntrue;
}
if(MotorolaUtils.handleSpecialCharSequence(context, input)) {
returntrue;
}
returnfalse;
}
handleChars 方法中,会对各种特殊的 secret code 进行匹配处理,这里我们看 handleSecretCode。
SpecialCharSequenceMgr#handleSecretCodestaticbooleanhandleSecretCode(Context context, String input){
// Secret code specific to OEMs should be handled first.
if(TranssionUtils.isTranssionSecretCode(input)) {
TranssionUtils.handleTranssionSecretCode(context, input);
returntrue;
}
// Secret codes are accessed by dialing *#*##*#* or "*##"
if(input.length > 8&& input.startsWith( "*#*#") && input.endsWith( "#*#*")) {
String secretCode = input.substring( 4, input.length - 4);
TelephonyManagerCompat.handleSecretCode(context, secretCode);
returntrue;
}
returnfalse;
}
再看下 TelephonyManagerCompat.handleSecretCode 方法。
TelephonyManagerCompat#handleSecretCodepublicstaticvoidhandleSecretCode(Context context, String secretCode){
// Must use system service on O+ to avoid using broadcasts, which are not allowed on O+.
if(BuildCompat.isAtLeastO) {
if(!TelecomUtil.isDefaultDialer(context)) {
LogUtil.e(
"TelephonyManagerCompat.handleSecretCode",
"not default dialer, cannot send special code");
return;
}
context.getSystemService(TelephonyManager.class).sendDialerSpecialCode(secretCode);
} else{
// System service call is not supported pre-O, so must use a broadcast for N-.
Intent intent =
newIntent(SECRET_CODE_ACTION, Uri.parse( "android_secret_code://"+ secretCode));
context.sendBroadcast(intent);
}
}
可以看到在拨号中接收到*#*##*#* 这样的指令时,程序会对外发送广播,这就意味着我们能够接收这个广播然后可以做我们想做的事情。
接下来我们看看这个接受广播代码是怎么写。
应用
首先在 AndroidManifest 文件中注册广播接收器。
android:name=".SecretCodeReceiver">
接收广播,启动应用。
publicclassSecretCodeReceiverextendsBroadcastReceiver{
@Override
publicvoidonReceive(Context context, Intent intent){
if(intent != null&& SECRET_CODE_ACTION.equals(intent.getAction)){
Intent i = newIntent(Intent.ACTION_MAIN);
i.setClass(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
}
这样只要在拨号中输入*#*#1010#*#*就能启动相应的应用程序,OK,收功。
责任编辑: