Android打包Jar(發布SDK)注意事項及問題解決

來源:互聯網
上載者:User

在Android開發過程中,我們經常會有這種需求,需要將自己開發一個類庫打包成jar包以供他人(其他人一般指開發人員)調用,而不是直接打包apk檔案供終端使用者使用。在打包成jar後,你往往會自己先測試一下看jar包能不能直接使用,這時就會常常有如下的幾個問題:

1) Error…..Found duplicate file for APK:res/drawable-xxx/xxx.xx

2) res.Resources$NotFoundException:XXX ID#0x7f090015

3) java.lang.NullPointerException

4) java.lang.NoClassDefFoundError: com.xxx.xxx.R$layout

幾個問題常見的原因是因為資源檔在作怪。

在第一個問你中,資源檔被打包進jar,在目標使用project中,也有相同id的資源檔,引起了衝突,解決方案是別打包資源檔啦,打包進去也不用的,後面會提到。或許你提到可能改變src project(提供jar包的project)裡面的資源id可以表面上解決這個問題。

不打包資源檔,但src project中又引用了res的資源檔,即便你把相應的layout的xml啊String.xml啊等copy到目標project中,也會造成如res.Resources$NotFoundException或者java.lang.NullPointerException,原因是在src中的一些activity調用xml中的資源時,控制項id找不到,例如一個btn = findViewById(R.id.btnXXX);這個btn為空白,就會NullPointerException.這個問題原因還是在stackoverflow上有人給出了合理的解釋.

As you want to import the resources,Since Android makes R class automatically with resources files under /res folder, using R class as final static is impossible.in your source code which will be exported in jar file, DON’T USE R variable because it will be replaced with final static memory address in compile time. Instead of using R use method below……

src項目中匯出src檔案夾成jar,不包含資源檔,資源檔copy到要引用的的其他項目中,但src中不能通過R.id.XXX 擷取xml中的布局等。因為打包成class的時候,final int 等死了(具體可以看看gen/xxx.xx.R.java),在新項目中是不對應的。解決方案就是用反射的方法.代碼如下.
   
public static int getResourseIdByName(String packageName, String className, String name)
{
    Class r = null;
    int id = 0;
    try
    {
        r = Class.forName(packageName + ".R");

        Class[] classes = r.getClasses();
        Class desireClass = null;

        for (int i = 0; i < classes.length; i++)
        {
            if (classes[i].getName().split("$")[1].equals(className))
            {
                desireClass = classes[i];
                break;
            }
        }

        if (desireClass != null)
            id = desireClass.getField(name).getInt(desireClass);
    } catch (ClassNotFoundException e)
    {
        e.printStackTrace();
    } catch (IllegalArgumentException e)
    {
        e.printStackTrace();
    } catch (SecurityException e)
    {
        e.printStackTrace();
    } catch (IllegalAccessException e)
    {
        e.printStackTrace();
    } catch (NoSuchFieldException e)
    {
        e.printStackTrace();
    }

    return id;

}

然後利用int id = getResourceIdByName(context.getPackageName(), “layout”, “main”);擷取layout檔案夾下main.xml的配置layout,通過int id = getResourceIdByName(context.getPackageName(), “string”, “text1″);擷取string.xml下key為text1的字串,通過int id = getResourceIdByName(context.getPackageName(), “id”, “btn”)獲得id為btn的控制項等。這個代碼利用反射運行時找的。
當然具體應用過程中你可以根據上面的這個方法重構一下去掉迴圈找配置而修改成單獨的一些id(key),dimen(key),color(key)之類的方法.這裡就不便(工作需要)將源碼給出當然也沒必要給出了.

網上說使用library方法載入資源檔可以解決,即將src project作為library,目標project引用src project.然後說這個方法解決了通過R.XX.XX擷取資源的問題,但還有一個問題是不可能把這個源碼發布出去讓其他人使用。我試了試,在我的項目中貌似通過R.XX.XX擷取的控制項仍然為null,讓人會報null 指標異常。

但這個給我提供了一個思路解決了一個比較方便的提供SDK的方式。因為上面的提到的那種需要手動copy layout等xml檔案.如果利用library的話可以避免copy這個操作。具體方案就是,同樣src project打包成lib.jar,然後自己手動建一個library project作為中間project,這個project添加lib.jar並將相應的xml檔案copy到此project.如下圖中的nebula_sdk,然後再發布nebula_sdk這個項目給其他人用,這樣既滿足了功能需求同樣也使代碼不易泄漏(打包過程仍然可以使用一定的代碼混淆技術).

建立一個類庫項目,如命名nebula_sdk.



發布出去後,開發人員需要將上面提到的nebula_sdk作為library引用進來。如下圖.



因此得到了兩種android下發布sdk方案:

產生jar,發布jar包同時提供layout xml等配置資源檔.這也是現在很多sdk發布的方式,比如一下廣告的SDKdomob_android_sdk,統計分析的SDK等.

產生jar包,先將library project並將此library project發布出去.這個方法可以省了讓開發人員copy 資源檔這一個過程.

當然如果src project中只涉及圖片之類的(R.drawable.xx)檔案(不涉及通過R.ID.xxx得到布局等控制項)的話也可以按照網上所說的方法把圖片copy到assert目錄下然後通過File IO的方式擷取原本應該放在drawable下的資源檔.當然如果涉及布局等控制項外,還有另外一個解決方案然後布局的話可以用硬coding的方式編碼(不讀取xml布局),不過這個應該比較繁瑣吧。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.