喜歡的小伙伴歡迎關(guān)注,我會定期分享Android知識點及解析,還會不斷更新的BATJ面試專題,歡迎大家前來探討交流,如有好的文章也歡迎投稿。
創(chuàng)新互聯(lián)公司是一家專注于網(wǎng)站設(shè)計制作、成都網(wǎng)站設(shè)計與策劃設(shè)計,義烏網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設(shè)10年,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:義烏等地區(qū)。義烏做網(wǎng)站價格咨詢:13518219792
在撥號盤中輸入*#*#
#*#*
后,APP 可以監(jiān)控到這些輸入,然后做相應(yīng)的動作,比如啟動應(yīng)用,是不是有點騷。
下面看下這個騷操作是如何實現(xiàn)的。
cdn.xitu.io/2019/7/15/16bf36d0c72336f9?imageslim">
DialtactsActivity 中有個 showDialpadFragment 方法,用來加載顯示撥號盤,因此入口就從 showDialpadFragment 看起,基于 Android P 分析。
private?void?showDialpadFragment(boolean?animate)?{ ??//…… ??final?FragmentTransaction?ft?=?getFragmentManager().beginTransaction(); ??if?(dialpadFragment?==?null)?{ ????dialpadFragment?=?new?DialpadFragment(); ????ft.add(R.id.dialtacts_container,?dialpadFragment,?TAG_DIALPAD_FRAGMENT); ??}?else?{ ????ft.show(dialpadFragment); ??} ??//…… }
具體實現(xiàn)在 DialpapFragment 中,看到 DialpapFragment 實現(xiàn)了 TextWatcher,TextWatcher 有 3 個重要方法,分別為:beforeTextChanged,onTextChanged 和 afterTextChanged,重點看 afterTextChanged 方法。
public?class?DialpadFragment?extends?Fragment ????????implements?View.OnClickListener, ????????View.OnLongClickListener, ????????View.OnKeyListener, ????????AdapterView.OnItemClickListener, ????????TextWatcher, ????????PopupMenu.OnMenuItemClickListener, ????????DialpadKeyButton.OnPressedListener?{ ????//…… ????@Override ????public?void?afterTextChanged(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(); ????} ????//…… }
這里調(diào)用了 SpecialCharSequenceMgr 輔助工具類的 handleChars 方法,看這個方法。
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) ??????||?handleRegulatoryInfoDisplay(context,?dialString) ??????||?handlePinEntry(context,?dialString) ??????||?handleAdnEntry(context,?dialString,?textField) ??????||?handleSecretCode(context,?dialString))?{ ????return?true; ??} ??if?(MotorolaUtils.handleSpecialCharSequence(context,?input))?{ ????return?true; ??} ??return?false; }
handleChars 方法中,會對各種特殊的 secret code 進(jìn)行匹配處理,這里我們看 handleSecretCode。
static?boolean?handleSecretCode(Context?context,?String?input)?{
??//?Secret?code?specific?to?OEMs?should?be?handled?first.
??if?(TranssionUtils.isTranssionSecretCode(input))?{
????TranssionUtils.handleTranssionSecretCode(context,?input);
????return?true;
??}
??//?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);
????return?true;
??}
??return?false;
}
再看下 TelephonyManagerCompat.handleSecretCode 方法。
public?static?void?handleSecretCode(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?= ????????new?Intent(SECRET_CODE_ACTION,?Uri.parse("android_secret_code://"?+?secretCode)); ????context.sendBroadcast(intent); ??} }
可以看到在撥號中接收到*#*#
#*#*
這樣的指令時,程序會對外發(fā)送廣播,這就意味著我們能夠接收這個廣播然后可以做我們想做的事情。
接下來我們看看這個接受廣播代碼是怎么寫。
首先在 AndroidManifest 文件中注冊廣播接收器。
???? ???????? ???????? ????
接收廣播,啟動應(yīng)用。
public?class?SecretCodeReceiver?extends?BroadcastReceiver?{ ????@Override ????public?void?onReceive(Context?context,?Intent?intent)?{ ????????if?(intent?!=?null?&&?SECRET_CODE_ACTION.equals(intent.getAction())){ ????????????Intent?i?=?new?Intent(Intent.ACTION_MAIN); ????????????i.setClass(context,?MainActivity.class); ????????????i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ????????????context.startActivity(i); ????????} ????} }
這樣只要在撥號中輸入*#*#1010#*#*
就能啟動相應(yīng)的應(yīng)用程序,OK,收功。
覺得文章不錯的小伙伴幫忙點點贊加關(guān)注哦 ,有什么問題的話也歡迎大家前來探討交流。