前言
1 . 信息:
Android P(禁用非官方API)目前類似的消息此起彼伏,關(guān)于國(guó)外移動(dòng)開發(fā)者社區(qū) XDA 的活躍者們?cè)?AOSP(Android 開放源代碼項(xiàng)目)的代碼提交記錄中的發(fā)現(xiàn)。從 AOSP 最新的 commits 中可以看到道川,那些使用 Android SDK 里面沒有被文檔提及的非公開 APIs(也就是使用 @hide 注解標(biāo)記的 APIs)的 apps 將受到系統(tǒng)限制冒萄。
2. 驗(yàn)證:
Android P預(yù)覽版已經(jīng)開發(fā)下載帅戒,大家可以下載刷機(jī)逻住,測(cè)試下使用到的api是否被限制。Android官網(wǎng)提供的刷機(jī)包有以下四種,大家可以直接下載刷機(jī)包刷機(jī)進(jìn)行驗(yàn)證装诡。下載地址如下:https://developer.android.com/preview/download.html
刷完包之后迫不及待的測(cè)試了非官方禁用API,測(cè)試結(jié)果和大家猜測(cè)的一樣鸦采,Android p會(huì)給大家彈出toast告知禁止使用非官方API渔伯,具體內(nèi)容請(qǐng)參考:co/dev/appcompat,最終的鏈接地址為:https://developer.android.com/preview/restrictions-non-sdk-interfaces.html
目前官方文檔已經(jīng)明確對(duì)非官方API的限制:
總結(jié)如下:
Android P引入了對(duì)非官方API的限制。無論是通過反射還是通過JNI等方法蓝厌, 只要應(yīng)用程序引用非SDK接口或嘗試使用反射或JNI獲取其句柄拓提,就會(huì)使應(yīng)用受到這些限制。
01
禁用非官方API原因
關(guān)于為何要減少非官方接口寺惫,提高應(yīng)用穩(wěn)定性西雀,在2018年2月28日,Google官方有此類聲明:原文地址:
https://android-developers.googleblog.com/2018/02/improving-stability-by-reducing-usage.html
通過以上內(nèi)容可得知蒋搜,Google早在Android N中已經(jīng)在native層已經(jīng)對(duì)ndk開發(fā)所使用的API進(jìn)行了非官方API接口的限制豆挽,目前在Android P中開始實(shí)施對(duì)java層非官方API(官方SDK接口)的限制帮哈。目的是為了確保Android開發(fā)者和使用者的穩(wěn)定性娘侍,為減少非官方API帶來的崩潰,Google一直在努力著嚎杨。
02
如何區(qū)分官方API和非官方API
官方聲明:SDK接口是Android框架中記錄的接口枫浙。 處理非SDK接口是API抽象化的實(shí)現(xiàn)細(xì)節(jié); 它可隨時(shí)更改箩帚,恕不另行通知紧帕。(官方sdk接口:https://developer.android.com/reference/packages.html)
關(guān)于限制到何種程度是嗜,Goole官方有以下說明:
總結(jié)以下幾點(diǎn):
Android P預(yù)覽版暫時(shí)對(duì)非官方API不做限制,目的是為了提供給開發(fā)者用于測(cè)試應(yīng)用中是否使用非官方API潦嘶。
Android P預(yù)覽版暫時(shí)會(huì)打印使用的非官方API的日志以及彈出相應(yīng)的toast提供給開發(fā)者測(cè)試使用(注:Toast是為了增加關(guān)注度掂僵,logcat中有使用非官方API的詳細(xì)信息)
日志(logcat)信息中包括Android運(yùn)行時(shí)使用的格式的聲明類锰蓬,名稱和類型芹扭。日志消息還指示訪問方式:直接舱卡,通過反射或通過JNI。以及適用的灰名單矫钓。
有兩種灰名單:
light greylisted :包含方法和字段赵辕,它們繼續(xù)在Android P預(yù)覽版中運(yùn)行概龄,但Google無法保證在未來版本的平臺(tái)上訪問這些方法和字段吸重。
dark greylist:開發(fā)人員預(yù)覽版本中無法訪問的方法歪今。
這些日志消息可以使用adb logcat訪問寄猩,并且會(huì)顯示在正在運(yùn)行的應(yīng)用程序的PID下骑疆。日志中的條目可能如下所示:
Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)
Accessing hidden method Landroid/app/ActivityThread;->currentActivityThread()Landroid/app/ActivityThread; (dark greylist, reflection)
03
使用非官方API的后果
在Developer Preview的后續(xù)版本中泊柬,訪問非SDK接口的各種方法都會(huì)產(chǎn)生錯(cuò)誤或其他不良結(jié)果兽赁。下面列出了幾種示例:
終上所述:使用非官方API的小伙伴么刀崖,趕緊檢查下自己的APP是否使用了非官方API吧亮钦,Android P呼之欲出蜂莉,別到時(shí)間措手不及映穗。
04
實(shí)際測(cè)試
有了以上大google的威逼利誘男公,以及各種模式下對(duì)非官方API的限制澄阳,我們來實(shí)際的測(cè)試下:
舉個(gè)例子碎赢,拿 android.net.wifi 包里面的 WifiManager 類來說肮塞,該 Class 里面就包含很多 @hide 標(biāo)記的代碼(其實(shí)源碼中類都包含有很多的@hide標(biāo)記枕赵,有興趣的可以參考下http://androidxref.com/查看源碼拷窜,或者下載源碼https://source.android.com/setup/downloading有興趣的同學(xué)可以進(jìn)一步交流)篮昧,一些變量或方法(這里隨便找網(wǎng)上找了一個(gè)):
/**
* Broadcast intent action indicating whether Wi-Fi scanning is allowed currently
* @hide
*/public static final String WIFI_SCAN_AVAILABLE = "wifi_scan_available";
這里我們通過java reflection功能來實(shí)現(xiàn)該功能笋妥,即調(diào)用隱藏API WIFI_SCAN_AVAILABLE字段:
WifiManager wifiManager = (WifiManager) getApplication().getSystemService(Context.WIFI_SERVICE);
field = wifiManager.getClass().getDeclaredField("WIFI_SCAN_AVAILABLE");
Log.d(Tag, (String) field.get(wifiManager));
上述實(shí)現(xiàn)上很簡(jiǎn)單懊昨,通過反射Filed WIFI_SCAN_AVAILABLE 來打印隱藏Field的值,在pixel Android P預(yù)覽版執(zhí)行結(jié)果如圖所示: