android怎樣調用@hide和internal API

 

android怎樣調用@hide和internal API

 分類:

Android有兩種類型的API是不能經由SDK訪問的。java

第一種是位於com.android.internal包中的API。我將稱之爲internal API。第二種API類型是一系列被標記爲@hide屬性的類和方法。從嚴格意義上來說,這不是一個單一的API,而是一組小的被隱藏的API,但我仍將其假設爲一種API,並稱之爲hidden API。android

Hidden API 例子架構

你能夠查看一下android的源碼,並能找到一些變量、函數和類等,都被@hide屬性標記了。ide

下面的例子就是在WifiManager(API 10源碼)中隱藏的變量。wordpress

clip_image002

另外一個例子是在WifiManager(API 10源碼)中隱藏了setWifiApEnabled函數。函數

clip_image004

所以,只要你看到@hide屬性,那你看到的就是hidden API。工具

Internal和hidden API的區別post

Hidden API之因此被隱藏,是想阻止開發者使用SDK中那些未完成或不穩定的部分(接口或架構)。舉個例子,Bluetooth API在API 5(Android 2.0)上纔開放;在API 3 和4上都是用@hide屬性隱藏了。當這些API被驗證和清理後,Google的開發者會移除@hide屬性,並讓其在API 5官方化。不少地方在API 4 和5之間發生了變化。若是你的程序依賴某些隱藏的API,當其部署到新的平臺上時,就有可能陷入困境。優化

對於internal API來講,歷來都沒有計劃將其開放出來。它就是Android的「內部廚房」,對開發者來講,應該將其視做黑盒。凡事都會有變化的。若是你依賴某些internal API,也有可能在新的Android release上,這些internal API發生變化,從而令你失望。網站

總結一下區別:

Hidden API = 進行中的工做;

Internal API = 黑盒;

Internal和hidden API的編譯時 vs. 運行時

當你使用Android SDK進行開發的時候,你引用了一個很是重要的jar文件——android.jar。它位於Android SDK平臺的文件夾中(SDK_DIR/platforms/platform-X/android.jar,其中,X表示API等級)。這個android.jar移掉了com.android.internal包中全部的類,也移掉了全部標記有@hide的類,枚舉,字段和方法。

但當你在設備上啓動應用程序時,它將加載framework.jar(簡單來講,它和android.jar等同),而其未移掉internal API和hidden API。(但它對開發者來講,並不能友好地訪問,所以,我將向你們展現不經過反射如何使用這些API)。

關於internal API,還有一件事須要說明。Eclipse的ADT插件增長了一個額外的規則,那就是禁止使用com.android.internal包中的任何東西。因此,即使是咱們能夠拿到最原始的android.jar(未刪減版),也沒有輕鬆的辦法經過Eclipse使用這些internal API。

你能夠親自檢查一下。建立一個新的Android工程(或者使用已有的)。查看一下它引用的類庫(右擊project Properties –> Java Build Path –> Libraries)。

clip_image006

clip_image008

重要的總結:internal和hidden API在SDK中是按照同樣的方式處理的(都從android.jar中移除了),但internal API更慘的是,還被Eclipse的ADT插件顯式禁止了。

不經過反射使用internal和hidden API

這些文章的終極目標是讓開發者可以不經過反射使用Internal和Hidden API。若是你完成了接下來部分中描述的步驟,你將能使用這些Internal和Hidden API,如同公開的API。你再也不須要使用反射。

注:若是你正在使用這些非公開的API,你必須知道,你的程序有着極大的風險。基本上,沒法保證在下一次的Android OS更新時,這些API不被破壞,也沒法保證不一樣的運營商有着一致的行爲。你本身決定吧。

接下來有三個場景:

1. Internal 和hidden API均可用(場景A)

2. 只Hidden API可用(場景B)

3. 只Internal API可用(場景C)

場景A是B、C的總和。場景B是最簡單的一個(不須要對Eclipse的ADT修改)。

場景A:閱讀Part1, 2, 3, 4, 5

場景B:閱讀Part1, 2, 3, 5

場景C:閱讀Part1, 2, 3, 4, 5

 

 

我解釋了爲何咱們不經過反射就會很難使用internal和hidden API。這是由於android.jar中就沒包含這些API,所以,沒人可以在編譯時引用這些類。

這篇文章將描述如何還原最初的android.jar。這將容許咱們像使用公開的API那樣使用internal和hidden API。

如何獲得原版android.jar?

咱們須要修改android.jar,這樣它才能包含全部的*.class文件(包括internal和hidden API類)。有兩種辦法:

1) Android是一個開源工程。咱們能夠下載源碼並搭建編譯環境,這樣它就不能移除那些internal和hidden的類了。這個辦法比較困難;

2) 每一個模擬器或真機在運行時都會有一個等同android.jar的東西。咱們能夠從這裏拿到jar文件,提取出原始的.class文件,並拷貝到Android SDK的android.jar中。

我將採用方案2。它易於開始,還不須要搭建Linux環境及編譯環境等。

從設備上獲取framework.jar

你可使用命令行(adb pull)從模擬器或設備上下載文件,或者使用DDMS(藉助Eclipse或SDK中的應用)。

注意:模擬器一般在.dex文件中包含代碼,而真機通常在優化版的dex文件中包含代碼——odex文件。操做odex文件比較困難,這也是爲何我選擇模擬器的緣由。

與Android SDK中的android.jar等同的文件是framework.jar。這個文件位於設備的:/system/framework/framework.jar

adb pull /system/framework/framework.jar

當framework.jar從設備上下下來以後,重命名爲framework.zip並解壓到獨立的文件夾中,看起來是這個樣子的:

clip_image002

classes.dex正是咱們須要的。

建立framework-classes.zip

首先,咱們須要把.dex文件轉換成.jar格式。你可使用通用的工具dex2jar。只須要運行:

dev2jar classes.dex

當轉換結束時,你應該獲得了classes.dex.dex2jar.jar文件。重命名爲framework-classes.zip。使用zip查看器,進入到framework-classes.zip/com/android/internal/:

clip_image004

恭喜你,你已經擁有了全部的.class文件,包括internal和hidden API(儘管截圖只確認了internal部分)。

建立original-android.jar

Android SDK的android.jar位於ANDROID_SDK/platforms/android-X/android.jar(X表示API等級)。

拷貝android.jar成custom-android.jar。解壓至custom-android文件夾。將framework-classes.zip中全部的.class文件拷貝到custom-android文件夾中(你須要覆蓋全部已經存在的.class文件)。

而後,壓縮custom-android文件成original-android.zip。重命名爲original-android.jar。

步驟總結

1. 選擇你的目標平臺X

2. 建立目標平臺X的模擬器

3. 啓動模擬器,下載/system/framework/framework.jar

4. 重命名framework.jar -> framework.zip

5. 從framework.zip中抽取classes.dex

6. 使用dex2jar工具,將其轉換成classes.jar

7. 重命名classes.jar -> framework-classes.zip

8. 拷貝android.jar –> custom-android.zip

9. 解壓custom-android.zip至custom-android文件夾

10. 將framework-classes.zip中全部文件拷貝至custom-android文件夾(覆蓋存在的文件)

11. 壓縮custom-android文件夾成original-android.zip

12. 重命名original-android.zip -> original-android.jar

打完收功。

總結

咱們還原了android.jar,使其包含全部的internal和hidden API的.class文件。這只是第一步。下一步將建立定製的android平臺,使其使用未刪節版的android.jar,並將其添加到Android SDK platforms文件夾中。


 

 

我已經展現瞭如何建立一個包含全部internal和hidden API的original-android.jar。

接下來的工做就是要修改已經存在的Android平臺(SDK_DIR/platforms/platform-X/android.jar,X表示API等級)。你能夠直接使用Part2中建立的original-android.jar替換android.jar。但這樣的話,你的全部工程都將直接使用internal和hidden API而沒有任何限制。這不夠方便,由於在多數的工程中你不但願這樣。甚至,你可能更但願禁止這些API(ADT/android.jar的默認行爲)。但對於一些特定的工程,你但願可以使用這些internal和hidden API。

爲了達到這樣的靈活性,你須要建立一個新的自定義的Android平臺。當不須要訪問internal和hidden API時,你只需使用原有的Android平臺。當你使用這些API時,你使用自定義的Android平臺。

Android SDK文件夾結構

讓咱們看一下Android SDK樹是如何組織的:

clip_image002

咱們須要「platforms」文件夾。看一下里面:

clip_image004

這裏列出了支持的Android平臺。

如今,咱們看一下它是如何與Eclipse設定關聯的。選擇你的工程,右擊–> Properties –> Android。你將會看到一組支持的Android平臺(與…/platforms/folder類似)。下面是截圖:

clip_image006

建立新的平臺

爲了建立一個新的平臺,咱們須要拷貝android-9文件夾 -> android-9-internals。讓咱們作一些修正:

1. 刪除其中的android.jar

2. 拷貝original-android.jar,並更名爲android.jar

3. 修改build.prop文件:

ro.build.version.sdk=9 -> ro.build.version.sdk=-9

ro.build.version.release=2.3 -> ro.build.version.release=2.3.extended

重啓Eclipse。並確認你能看到新的平臺。下面是我所看到的:

clip_image008

爲何我選擇API等級爲-9?這是由於它必須是一個數字,並且它不能是9(或者其它已經存在的API等級)。不然,你自定義的平臺將不能被使用(它在列表裏可見,但選中後也不能正常工做,編譯時仍然使用相應API等級的原始平臺)。

下面是引用類庫的截圖(當前工程選中了自定義的平臺):

clip_image010

總結

在上一篇中,我已經告訴你如何建立一個未刪節版的android.jar。在這一篇中,我向你展現瞭如何建立一個自定義的Android平臺,並在其中使用original-android.jar。這對於hidden API來講已經足夠了。但對於internal API來講,還須要另外一步。這是由於ADT仍然不容許使用com.android.internal包中的類(參見上圖中的「forbidden」訪問規則)。下一節我將向你展現如何定製ADT來容許使用internal包中的類。

============華麗的分割線=============

在實際的操做過程當中,我建立的自定義的android.jar(API 10)不能被Eclipse成功加載,會出現如下的錯誤框,如同網站上其它人操做的結果同樣,期待解決方案。

clip_image012

不過,做者提供了可用的自定義的android.jar,若是不想本身嘗試的話,能夠直接從網站下載,地址將在Part5中給出,稍等。


 

爲了可以使用Internal和Hidden API,你須要:

1. 建立自定義的original-android.jar,包含全部的.class文件

2. 建立自定義的Android平臺來使用original-android.jar

3. 修改ADT插件,容許使用com.android.internal包(只爲Internal API)

4. 建立新的工程,引用自定義的Android平臺(本文中的例子)

在本文中,我將向大家展現如何使用那些Internal和Hidden API。

此外,在本文的結尾,我列出了一些自定義的Android平臺,它們都包含Internal和Hidden API。我附帶了它們,是爲了可能你不想花太多時間在這方面,但又想快速的嘗試什麼。

例子

建立一個新工程,選擇2.3.extender平臺:

clip_image002

下面是代碼:

clip_image004

這個代碼使用了Internal API(PowerProfile)和Hidden API(isWifiApEnabled)。我不用使用反射就能編譯並運行這些代碼。

自定義平臺

下面有些平臺,是我爲本身建立的。只用拷貝它們到SDK_DIR\platforms文件夾下。這只是讓Hidden API可用。對於Internal API,你須要修改你的ADT插件。

API 3:http://www.megaupload.com/?d=S1F2MKYZ

API 4:http://www.megaupload.com/?d=VUCTRI3Y

API 7:http://www.megaupload.com/?d=7ITNILBK

API 8:http://www.megaupload.com/?d=EXT5FKKT

API 9:http://www.megaupload.com/?d=EXT5FKKT

API 10:http://www.megaupload.com/?d=FCV78A9M

==============華麗的分割線=============

我嘗試了其中的幾個自定義平臺,發現,internal 和hidden API真的是可用了,但也有一些意外的問題,如AlertDialog.Builder(Context context)竟然說Context參數是多餘的。。

沒花時間去研究爲何會這樣,若是哪位童鞋知道緣由,告訴我哈~~

來源:http://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-1-introduction/

相關文章
相關標籤/搜索