問(wèn)題描述
簡(jiǎn)短的總結(jié)是:如何構(gòu)建 APK 和單獨(dú)的庫(kù)(我的意思是某種形式的類(lèi)集(理想情況下,還有資源),例如 JAR、AAR 或 DEX 文件),但不包括那些APK 中的庫(kù);相反,應(yīng)用會(huì)在運(yùn)行時(shí)加載它們?
The short summary is: How do I build an APK and separate libraries (by which I mean sets of classes (and ideally, resources too) in some form, such as JAR, AAR or DEX files), but not include those libraries in the APK; instead, the app loads them at run time?
所以我的主要問(wèn)題是如何構(gòu)建這樣的應(yīng)用程序(例如 Gradle 配置).如何指定哪些類(lèi)進(jìn)入哪些 JAR 或 DEX 文件?我是否要為每個(gè)想要結(jié)束的 DEX 文件創(chuàng)建一個(gè) Android Studio 模塊?
So my main question is how to build such an app (e.g. Gradle configuration). How do I specify which classes go into which JAR or DEX files? Do I create an Android Studio module for each DEX file I want to end up with?
一個(gè)密切相關(guān)的問(wèn)題是 Java 代碼應(yīng)該如何加載外部庫(kù)并在運(yùn)行時(shí)訪(fǎng)問(wèn)它們的類(lèi).對(duì)于后者,我希望 通過(guò)類(lèi)加載器從 dex 文件訪(fǎng)問(wèn)應(yīng)用程序的類(lèi) 會(huì)起作用.
A closely related question is how the Java code should then load the external libraries and access their classes at run time. For the latter, I'm hopeful that the approach shown at accessing to classes of app from dex file by classloader would work.
我已經(jīng)嘗試了 https://developer.android.com 上的說(shuō)明/studio/projects/android-library.html,但這會(huì)構(gòu)建一個(gè)確實(shí)包含依賴(lài)庫(kù)的 APK.
I've tried the instructions at https://developer.android.com/studio/projects/android-library.html, but that builds an APK that does include the dependency library.
我也嘗試過(guò) Multidex (https://developer.android.com/studio/build/multidex.html),但這似乎并沒(méi)有讓開(kāi)發(fā)人員對(duì)哪些類(lèi)進(jìn)入哪個(gè) DEX 文件有任何控制權(quán),而且,將它們?nèi)看虬揭粋€(gè) APK 中.AFAICT 無(wú)法在運(yùn)行時(shí)控制這些 DEX 文件的加載.
I've also tried Multidex (https://developer.android.com/studio/build/multidex.html), but that doesn't seem to leave the developer any control over which classes go in which DEX file, and furthermore, packages them all into a single APK. AFAICT there is no way to control the loading of these DEX files at run time.
這里可能存在XY 問(wèn)題",所以我最好解釋一下背景.
There's a possibility of the "X-Y problem" here, so I'd better explain the background.
我正在為客戶(hù)構(gòu)建應(yīng)用程序.它不會(huì)通過(guò)應(yīng)用商店分發(fā),因此無(wú)法訪(fǎng)問(wèn)正常的更新機(jī)制.相反,客戶(hù)端希望應(yīng)用程序能夠通過(guò)下載自身的新組件來(lái)替換舊組件來(lái)更新自身,而無(wú)需手動(dòng)旁加載新的 APK.這里的主要?jiǎng)訖C(jī)是更新必須對(duì)非技術(shù)用戶(hù)很容易.如果應(yīng)用程序可以控制更新過(guò)程,它可以使其流暢并引導(dǎo)用戶(hù).
I'm building an app for a client. It's not going to be distributed through an app store, so it won't have access to the normal mechanism for updates. Instead, the client wants the app to be able to update itself by downloading new components of itself to replace the old components, without a need to manually sideload a new APK. The primary motive here is that the updates have to be easy for non-technical users. If the app can control the update process, it can make it smooth and guide the user.
此外,該應(yīng)用程序?qū)⒂糜诨ヂ?lián)網(wǎng)訪(fǎng)問(wèn)稀缺和昂貴的地區(qū),因此客戶(hù)希望能夠以較小的塊(例如 2MB)發(fā)布應(yīng)用程序更新,而不是強(qiáng)迫用戶(hù)重新下載整個(gè)應(yīng)用程序接收一個(gè)小的更新.
Moreover, the app will be used in areas where internet access is scarce and expensive, so the client wants to be able to issue app updates in smaller chunks (e.g. 2MB) rather than forcing the user to re-download the whole app to receive a small update.
我應(yīng)該提到的要求的一個(gè)方面是,在運(yùn)行時(shí)要加載的庫(kù)應(yīng)該存在于 microSD 卡上.這也有助于在沒(méi)有互聯(lián)網(wǎng)訪(fǎng)問(wèn)的情況下分發(fā)更新.
One aspect of the requirements I should mention, in case it matters, is that the libraries to be loaded at run time are supposed to live on a microSD card. This can also help with distribution of updates without internet access.
應(yīng)用程序的當(dāng)前狀態(tài)是編寫(xiě)了大約 50%:也就是說(shuō),已經(jīng)發(fā)布了幾個(gè)早期版本,但是現(xiàn)在需要對(duì)應(yīng)用程序進(jìn)行修改(重組)以滿(mǎn)足上述要求以及其他要求.
The current status of the app is that it's about 50% written: That is, a couple of earlier versions have been released, but the app now needs to be modified (restructured) to meet the above requirements, as well as others.
推薦答案
本教程是外部加載 DEX 文件的良好開(kāi)端.只有三個(gè)小源文件(MainActivity.java、LibraryInterface.java、LibraryProvider.java)并將secondary_dex.jar從assets文件夾復(fù)制到內(nèi)部應(yīng)用程序存儲(chǔ)[outdex/dex](教程中也盡可能地說(shuō)明了互聯(lián)網(wǎng))).您必須使用 ant 構(gòu)建它,因?yàn)樗褂米远x構(gòu)建步驟.我試過(guò)了,效果很好.值得一看.
Dalvik 和 ART 中的自定義類(lèi)加載
This tutorial is a good start for external loading of DEX files.
Only three small files of source (MainActivity.java, LibraryInterface.java, LibraryProvider.java) and it copies secondary_dex.jar from the assets folder, into internal application storage [outdex/dex] (the internet is also stated as possible in the tutorial).
You have to build it with ant, because it uses custom build steps.
I tried it, it works fine. Worth a look.
custom class loading in Dalvik and ART
更新此代碼已移植到 Android Studio gradle(不需要 ant).https://github.com/timrae/custom-class-loader
測(cè)試正常.將 com.example.toastlib.jar 從 SD 卡 復(fù)制到 內(nèi)部應(yīng)用程序存儲(chǔ) [outdex/dex],(不是 assets 文件夾).(您必須閱讀項(xiàng)目中的 README.md 文件來(lái)構(gòu)建它).
UPDATE
this code has been ported to Android Studio gradle (no need for ant).
https://github.com/timrae/custom-class-loader
Tested ok. Copies com.example.toastlib.jar from the SDcard into internal application storage [outdex/dex],(not assets folder).
( you must read the README.md file in the project to build it).
問(wèn):如何添加 Activity,我無(wú)法將其添加到清單中?
答:使用片段,它們不需要清單中的條目.
Q: How do I add an Activity, I cannot add it to the manifest ?
A: Use Fragments, they don't need entries in the manifest.
問(wèn):一個(gè)帶有資源的 Jar,旨在添加到現(xiàn)有的項(xiàng)目需要能夠?qū)⑵滟Y源與項(xiàng)目的資源合并自有資源(R.).
A:黑客可用,數(shù)據(jù)文件...
在可分發(fā)的 Jar 文件中打包 Android 資源文件
Q: A Jar with resources that is meant to be added to an existing
project needs to be able to merge its resources with the project's
own resources (R.).
A: Hacks are available, Data file...
Packaging Android resource files within a distributable Jar file
問(wèn):外部文件的權(quán)限錯(cuò)誤.
A:導(dǎo)入它.
Q: The external file has wrong permissions.
A: Import it.
問(wèn):我需要添加使用權(quán)限.
A:使用 API23,您可以通過(guò)編程方式添加使用權(quán)限(但它們?nèi)匀恍枰?Manifest 中聲明,因此 新權(quán)限模型對(duì)我們來(lái)說(shuō)可能沒(méi)多大用處.
Q: I need to add uses-permission.
A: Use API23 you can programmatically add uses-permissions (but they still need to be declared in the Manifest, so the new permissions model is probably not much use to us).
此部分適用于更一般的用戶(hù)(@LarsH 對(duì)更新有更具體的要求),上面的示例是 17kb apk 和 1 kb jar.您可以將大部分代碼放在一次性 jar 中,更新只需加載一個(gè)新的 Apk(然后導(dǎo)入批量代碼 jar,以最大程度地減少數(shù)據(jù)傳輸).當(dāng) Apk 變得太大時(shí),從一個(gè)小 Apk 重新開(kāi)始,所有內(nèi)容都遷移到另一個(gè) jar(導(dǎo)入 2 個(gè) jar).您需要平衡編碼工作量、用戶(hù)體驗(yàn)、可維護(hù)性、可支持性、帶寬、android 規(guī)則、play store 規(guī)則(如果這些詞甚至存在的話(huà);O)).
This section is for more general users (@LarsH has more specific requirements about updates), The example above is 17kb apk and 1 kb jar. You could put the bulk of you code in the one-off jar, and updates would involve just loading an new Apk (and then importing the bulk code jar, to minimise the data transfer). When the Apk gets too big, start again with a small Apk and everything migrated to another jar (import 2 jar's). You need to balance coding effort, user experience, maintainability, supportability, bandwidth, android rules, play store rules (if these words even exist ;O)).
注意 Dalvik 已停產(chǎn)
Dalvik 的繼承者是 Android Runtime (ART),它使用相同的字節(jié)碼和 .dex 文件(但不是 .odex 文件),其繼承旨在提高對(duì)最終用戶(hù)透明的性能.新的運(yùn)行時(shí)環(huán)境首次作為技術(shù)預(yù)覽包含在 Android 4.4KitKat"中,并在以后的版本中完全取代了 Dalvik;Android 5.0Lollipop"是第一個(gè)僅包含 ART 運(yùn)行時(shí)的版本.
The successor of Dalvik is Android Runtime (ART), which uses the same bytecode and .dex files (but not .odex files), with the succession aiming at performance improvements transparent to the end users. The new runtime environment was included for the first time in Android 4.4 "KitKat" as a technology preview, and replaced Dalvik entirely in later versions; Android 5.0 "Lollipop" is the first version in which ART is the only included runtime.
這篇關(guān)于如何構(gòu)建應(yīng)用程序動(dòng)態(tài)加載的 APK 和分離庫(kù)的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!