【轉】製做不暴露源碼的Android Library Project

        Android Library Project(庫工程)是一個能夠被其餘Android工程所引用的工程。那爲何須要使用這個工程呢,打個比方,咱們在開發Android項目的時候,經常會遇到這樣的問題,幾個Android項目的開發過程當中,會有能夠重複利用的代碼段或者資源。若是每一個項目都要重複編寫或者添加這些代碼或者資源,將會很是的影響效率。爲了不重複發明輪子,咱們能夠將這些重複的資源添加到Android Library Project中。那麼之後,咱們要複用這些東西的時候,只要在當前項目中引用這個Android Library Project就能夠了。java

       固然咱們的Android Library Project不單單是給咱們本身使用,若是咱們要把這個Android Lib Project共享給別人,可是又不但願暴露本身的源代碼,那麼,這就是咱們這篇文章要講的內容。android

HOW

首先,這篇文章中咱們會提到三個項目。ide

LibraryProject : 咱們須要共享給別人的不包含源代碼的工程。佈局

LibraryProjectSource : LibraryProject包含源代碼的版本。測試

AndroidProject : 引用LibraryProject的版本。ui

         和咱們開發正常的Android項目同樣,咱們先創建一個項目,可是在開始正常的編碼以前,咱們須要先弄清楚原理和注意事項:不暴露源碼的方式是將LibraryProjectSource中的源代碼打包成JAR包,而後添加到咱們要共享給他人的工程中。若是這個工程中沒有引用到資源(res目錄下的文件),那麼就很容易實現了。可是若是有引用到資源(例如經過R.id.resource方式),咱們就能夠能會遇到資源引用錯亂的問題。編碼

          打個比方,在AndroidProject中若是引用TextView能夠會定位到一個ImageView上。這是由於,若是在源代碼中有使用R.id.resource引用資源,在編譯成JAR包的時候,R.id.resource會用R.java文件中相應的十六進制的int值替換。可是在AndroidProject文件中資源的會結合LibraryProject中的資源從新生成一個新的十六進制int值。而同一個資源,在LibraryProjectSource中的這個int值和AndroidProject中的就可能不相同了。spa

因此咱們必須實時的獲取這個十六進制的數值。有兩個方式能夠選擇:code

1.(推薦)經過android.content.res.Resources類的int getIdentifier(String name, String defType, String defPackage) . xml

        好比,咱們須要在Activity中設置佈局,咱們要獲得res/layout/目錄下的 「main_layout.xml」 佈局文件的ID.

   @Override     
   protected void onCreate(Bundle savedInstanceState) {
            ...
            int id = getResources().getIdentifier(「main_layout「, "layout", getPackageName());
            setContentView(id);
            ...
   }

注意:在編寫Library代碼的時候,就應該採用這樣的方式去獲取id值,而不是簡單的用R.id.xxxx.


2.使用Java語言的反射機制。可是使用反射畢竟麻煩。

   Field field = R.layout.class.getField("main_layout");
   int i = field.getInt(new R.layout());
   return i;

PUBLISH

最後,咱們須要將編寫好的源代碼導成JAR包,添加到LibraryProject中。而後咱們就能夠將這個工程共享給其餘人了。具體步驟以下:

1. 將LibraryProjectSource的類文件導出:打開工程文件夾目錄->打開bin目錄->將與工程名相同的JAR文件複製出來。將原工程依賴的JAR包導出:打開工程文件夾目錄->打開libs目錄->其中的JAR文件複製出來。

2. 創建一個與 LibraryProjectSource 的包名相同的 LibraryProject(包名是Android系統辨識應用程序的標誌),建立的時候不選擇建立Activity,將這個工程做爲Lib工程。

3. 將1中導出兩種包複製到Lib工程的libs文件夾下,右鍵Lib工程->Properties->Android->勾選「Is Library」->肯定。將 LibraryProjectSource 文件夾下的資源文件複製到Lib工程下(主要是assets和res文件夾,替換原來的文件)。把原工程中AndroidManifest.xml替換此工程的AndroidManifest.xml。這樣Lib Project就完成了。

以後,寫一個Demo(AndroidProject)測試一下 LibraryProject 可否使用:

新建工程->右鍵工程->Properties->Android->Add->選擇2中創建的LibraryProject->OK;

接着從LibraryProject導入1中導出的類文件:右鍵工程->Properties->Java Build Path->Add JARs->選中2中的Lib 工程下的libs文件下的與1中原工程同名的JAR包,再選擇Order and Export,將加入的包打鉤。

把Lib中的AndroidManifest.xml中必要的部分複製到Demo工程中,例如:原工程中須要用到的權限聲明,activity,service,broadcast部分。

TIPS

打開工程文件夾目錄->打開bin目錄->將與工程名相同的JAR文件複製出來

當咱們從LibraryProjectSource中的bin目錄下拷貝出自動生成的jar的時候,經過jd-gui簡單的反編譯一下,就會發現這個jar其實就是源碼的打包,而且是原封不動的打包。。其實這就有違了咱們的初衷:隱藏源代碼。

解決辦法應該是:導出jar包以後,而後在進行混淆等操做。混淆jar包,能夠用proguard等。

相關文章
相關標籤/搜索