Android彈出系統(tǒng)自帶安全鍵盤(pán)的奇淫技巧

最近在做遠(yuǎn)程控制功能,手機(jī)APP端控制電腦桌面端。有個(gè)功能是APP端輸入文本,顯示在電腦端輸入框內(nèi)。由于當(dāng)前遠(yuǎn)程控制功能還在初級(jí)階段,只需實(shí)現(xiàn)輸入數(shù)字、英文大小寫(xiě)字母、特殊符號(hào)和部分控制鍵,故只需要彈出一個(gè)安全鍵盤(pán)。

安全鍵盤(pán)在很多銀行APP里使用廣泛,一般用來(lái)輸入密碼。密碼通常是由數(shù)字、英文大小寫(xiě)字母和特殊符號(hào)構(gòu)成,沒(méi)有中文,所以輸入法鍵盤(pán)也就不需要支持語(yǔ)言切換,純英文鍵盤(pán)就可以。

一般來(lái)說(shuō),安全鍵盤(pán)可自定義,繼承KeyboardView然后設(shè)置自定義的布局文件(需要在xml目錄下自定義)。

但是在深入反編譯研究了TeamViewer的APK后發(fā)現(xiàn),TeamViewer彈出的安全鍵盤(pán)并不是自定義的而是系統(tǒng)自帶的。有以下證據(jù):

  1. 資源文件里沒(méi)有安全鍵盤(pán)相關(guān)的icon和字符串;
  2. 這個(gè)所謂的“安全鍵盤(pán)”的彈出動(dòng)畫(huà)明顯區(qū)別于自定義的鍵盤(pán),因?yàn)樗牟季治募镌谧远x的鍵盤(pán)上方加了一個(gè)工具條,在“安全鍵盤(pán)”彈出時(shí)可以看到工具條明顯的跳動(dòng),而自定義的鍵盤(pán)彈出時(shí)并沒(méi)有;
  3. 彈出這個(gè)“安全鍵盤(pán)”時(shí),無(wú)法截屏,彈出自定義鍵盤(pán)時(shí)可以截屏。當(dāng)然禁止截屏可以在代碼里通過(guò)
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE)實(shí)現(xiàn),但是在全局搜索了反編譯之后的代碼并沒(méi)有發(fā)現(xiàn),可見(jiàn)無(wú)法截屏應(yīng)該是因?yàn)檫@個(gè)“安全鍵盤(pán)”導(dǎo)致的。
    安全鍵盤(pán)(因?yàn)闊o(wú)法截圖,只能拍照了)
自定義鍵盤(pán)

TeamViewer彈出的這個(gè)“安全鍵盤(pán)”完全滿足我們的需求,而且不用自定義,省去了很多繁瑣的工作。既然這樣,那么我們也嘗試彈出這個(gè)“安全鍵盤(pán)”吧。

不好意思,這個(gè)小功能點(diǎn)我斷斷續(xù)續(xù)做了兩天,還是無(wú)果。彈出來(lái)的輸入法永遠(yuǎn)都是系統(tǒng)默認(rèn)的搜狗。是我太菜了么?

搜狗鍵盤(pán)

當(dāng)時(shí)我甚至在懷疑,這個(gè)“安全鍵盤(pán)”的xml布局文件是不是運(yùn)行時(shí)動(dòng)態(tài)地從服務(wù)器上下載的,導(dǎo)致我無(wú)法在反編譯的資源文件里找到一些線索。但轉(zhuǎn)念一想,這也不是什么機(jī)密文件,而且這個(gè)鍵盤(pán)布局也不需要更新變化(不像銀行的安全鍵盤(pán),按鍵位置隨機(jī)變化)。然后我又仔仔細(xì)細(xì)的搜索了setKeyboard這個(gè)自定義鍵盤(pán)必須使用的方法,想著是不是有遺漏之處,依然毫無(wú)線索。

再結(jié)合前面說(shuō)到的三條這個(gè)“安全鍵盤(pán)”是系統(tǒng)自帶的而不是自定義的證據(jù),我再次確定,這個(gè)“安全鍵盤(pán)”確實(shí)是系統(tǒng)自帶的,一定是還有什么鍵盤(pán)屬性設(shè)置,被我遺漏了。

于是我又開(kāi)始仔細(xì)看著枯燥的反編譯后的代碼文件。功夫不負(fù)有心人,在TeamViewer接收文字輸入的控件里(繼承了AutoCompleteTextView),他們重寫(xiě)了onCreateInputConnection方法,里面有兩句配置:

paramEditorInfo.inputType = 524433;
paramEditorInfo.imeOptions = 268435457;

看到的第一眼,直覺(jué)告訴我,就是你們了。先不管這兩個(gè)數(shù)字看起來(lái)有多么奇怪,立馬先給自己的app加上再說(shuō),運(yùn)行起來(lái),打開(kāi)一看,搞定!

興奮了幾分鐘,冷靜下來(lái),準(zhǔn)備繼續(xù)深入分析下去。

刪掉了paramEditorInfo.imeOptions = 268435457;這句后,依然可以彈出安全鍵盤(pán)。那么這個(gè)524433到底是何方神圣呢?

524433的16進(jìn)制是0x80091,EditorInfoinputType可以設(shè)置的類型在android.text.InputType這個(gè)類里,并沒(méi)有0x80091這個(gè)值,那么應(yīng)該是多個(gè)value位運(yùn)算后的結(jié)果。在InputType里湊了一會(huì),發(fā)現(xiàn)是以下幾個(gè):
TYPE_CLASS_TEXT(0x00000001),TYPE_TEXT_VARIATION_VISIBLE_PASSWORD(0x00000090)TYPE_TEXT_FLAG_NO_SUGGESTIONS(0x00080000)和。
完整的代碼是:

editorInfo.inputType = InputType.TYPE_CLASS_TEXT
                | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;

TYPE_CLASS_TEXT一般和TYPE_TEXT_FLAG_NO_SUGGESTIONS一起使用來(lái)禁止輸入法鍵盤(pán)的智能提示功能(這個(gè)功能對(duì)暫時(shí)只支持輸入單個(gè)字符的遠(yuǎn)程控制來(lái)說(shuō),確實(shí)不需要)。TYPE_TEXT_VARIATION_VISIBLE_PASSWORD這個(gè)用來(lái)讓密碼可見(jiàn)。嘗試了下設(shè)置inputType為單獨(dú)的TYPE_TEXT_VARIATION_VISIBLE_PASSWORD并不能彈出安全鍵盤(pán),當(dāng)然其他兩個(gè)更不行了。必須將inputType設(shè)置成InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS才能有效彈出安全鍵盤(pán)。

以上測(cè)試結(jié)果基于OPPO Reno。

后面又測(cè)試了Pixel,結(jié)果大跌眼鏡。Pixel根本彈不出所謂的安全鍵盤(pán),不過(guò)也跟安全鍵盤(pán)無(wú)異。只是這個(gè)鍵盤(pán)就是默認(rèn)的輸入法鍵盤(pán),隨便寫(xiě)一個(gè)EditText設(shè)置屬性android:inputType="none"就可以調(diào)出來(lái)。只是彈出這個(gè)鍵盤(pán)后,依舊可以截屏(因?yàn)榫褪且粋€(gè)普通的鍵盤(pán))。

Pixel默認(rèn)鍵盤(pán)

猜測(cè)是OPPO對(duì)輸入法做了魔改,禁用了系統(tǒng)自帶的默認(rèn)鍵盤(pán),改為了搜狗鍵盤(pán)。

假如說(shuō)一開(kāi)始就用Pixel做嘗試,就不會(huì)遇到彈不出“安全鍵盤(pán)”的問(wèn)題,也就不會(huì)耽擱那么多時(shí)間來(lái)想方設(shè)法尋求解決方案。不過(guò)也正因如此,才發(fā)現(xiàn)了這么一些有趣的現(xiàn)象和解決方案。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容