31

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?

Detail

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?

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.

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.

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.

Background

There's a possibility of the "X-Y problem" here, so I'd better explain the background.

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.

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.

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.

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.

4

2 回答 2

6

本教程是从外部加载 DEX 文件的良好开端。只有三个小源文件(MainActivity.java、LibraryInterface.java、LibraryProvider.java)并将secondary_dex.jar从assets文件夹复制到内部应用程序存储[outdex/dex](教程中也尽可能地说明了互联网) )。您必须使用ant构建它,因为它使用自定义构建步骤。我试过了,效果很好。值得一看。
Dalvik 和 ART 中的自定义类加载


更新 此代码已移植到 Android Studio gradle(不需要 ant)。 https://github.com/timrae/custom-class-loader
测试正常将com.example.toastlib.jarSD 卡复制到内部应用程序存储[outdex/dex],(不是 assets 文件夹)。(您必须阅读项目中的README.md文件才能构建它)。

问:如何添加 Activity,我无法将其添加到清单中?
A:使用片段,它们不需要清单中的条目。

问:要添加到现有项目的资源的 Jar 需要能够将其资源与项目自己的资源 (R.) 合并。
A: Hacks 可用,数据文件... 将
Android 资源文件打包到一个可分发的 Jar 文件中

Q: 外部文件权限错误。
答:导入。

问:我需要添加使用权限。
A:使用API​​23你可以通过编程方式添加uses-permissions(但它们仍然需要在Manifest中声明,所以新的权限模型对我们来说可能没有多大用处)。

本部分适用于更一般的用户(@LarsH 对更新有更具体的要求),上面的示例是 17kb apk 和 1 kb jar。您可以将大部分代码放在一次性 jar 中,更新只需加载一个新的 Apk(然后导入批量代码 jar,以最大程度地减少数据传输)。当 Apk 变得太大时,从一个小 Apk 重新开始,所有内容都迁移到另一个 jar(导入 2 个 jar)。您需要平衡编码工作、用户体验、可维护性、可支持性、带宽、android 规则、play store 规则(如果这些词甚至存在;O))。

注意 Dalvik 已停产

Dalvik 的继承者是 Android Runtime (ART),它使用相同的字节码和 .dex 文件(但不是 .odex 文件),其继承旨在提高对最终用户透明的性能。新的运行时环境首次作为技术预览包含在 Android 4.4“KitKat”中,并在以后的版本中完全取代了 Dalvik;Android 5.0“Lollipop”是第一个仅包含 ART 运行时的版本。

于 2016-09-01T18:46:18.570 回答
1

您可以尝试使用相同的sharedUserId和相同的process构建多个 apk 。

这是Threema使用的插件机制

编辑:更多关于 Theema

Threema 有一个主应用程序和两个插件:

这样做主应用程序不需要访问相机或麦克风的权限

于 2016-09-01T19:44:12.410 回答