如何在 Android 内部共享使用即时运行时创建的拆分 APK? [英] How to share split APKs created while using instant-run, within Android itself?

查看:21
本文介绍了如何在 Android 内部共享使用即时运行时创建的拆分 APK?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

我有一个应用(

我不确定这个问题是什么时候开始的,但至少在我的 Nexus 5x 和 Android 7.1.2 上确实发生过.甚至可能更早.

我发现了什么

这似乎只是因为在 IDE 上启用了即时运行,因此它可以帮助更新应用程序,而无需一起重新构建它:

禁用后,我可以看到只有一个 APK,就像过去一样:

您可以看到正确的 APK 和拆分的 APK 之间的文件大小差异.

此外,似乎有一个 API 可以获取所有拆分的 APK 的路径:

https://developer.android.com/reference/android/content/pm/ApplicationInfo.html#splitPublicSourceDirs

问题

共享必须拆分为多个 APK 的 APK 的最简单方法是什么?

真的需要以某种方式合并它们吗?

根据文档,这似乎是可能的:

<块引用>

零个或多个拆分 APK 的完整路径,当与在 sourceDir 中定义基础 APK,形成一个完整的应用程序.

但是正确的方法是什么,有没有快速有效的方法呢?也许没有真正创建文件?

是否有 API 可以从所有拆分的 APK 中获取合并的 APK?或者这样的APK可能已经存在于其他路径中,不需要合并?

刚刚注意到我尝试过的所有第三方应用程序都应该共享已安装应用程序的 APK,但在这种情况下未能这样做.

解决方案

我是 Android Gradle 插件的技术负责人 @Google,让我尝试回答您的问题,假设我了解您的用例.

首先,一些用户提到你不应该分享你启用 InstantRun 的构建,他们是正确的.构建在应用程序上的 Instant Run 是针对您要部署到的当前设备/模拟器映像高度定制的.因此,基本上,假设您为运行 21 的特定设备生成启用了 IR 的应用程序版本,如果您尝试在运行 23 的设备上使用那些完全相同的 APK,它将惨遭失败.如有必要,我可以进行更深入的解释,但可以说我们生成了在 android.jar 中找到的 API 上定制的字节码(这当然是特定于版本的).

所以我认为共享这些 APK 没有意义,您应该使用禁用 IR 的构建或发布构建.

现在了解一些细节,每个切片 APK 包含 1 个以上的 dex 文件,所以理论上,没有什么可以阻止您解压缩所有这些切片 APK,将所有 dex 文件塞回 base.apk/rezip/resign,它应该可以正常工作.但是,它仍然是一个启用 IR 的应用程序,因此它将启动小型服务器以侦听 IDE 请求等……我无法想象这样做的充分理由.

希望这会有所帮助.

Background

I have an app (here) that, among other features, allows to share APK files.

In order to do so, it reaches the file by accessing the path of packageInfo.applicationInfo.sourceDir (docs link here), and just shares the file (using ContentProvider when needed, as I've used here).

The problem

This works fine in most cases, especially when installing APK files from either the Play Store or from a standalone APK file, but when I install an app using Android-Studio itself, I see multiple APK files on this path, and none of them are valid ones that can be installed and run without any issues.

Here's a screenshot of the content of this folder, after trying out a sample from "Alerter" github repo :

I'm not sure when this issue has started, but it does occur at least on my Nexus 5x with Android 7.1.2. Maybe even before.

What I've found

This seems to be caused only from the fact that instant run is enabled on the IDE, so that it could help updating the app without the need to re-build it all together :

After disabling it, I can see that there is a single APK, just as it used to be in the past:

You can see the difference in file size between the correct APK and the split one.

Also, it seems that there is an API to get the paths to all of the splited APKs:

https://developer.android.com/reference/android/content/pm/ApplicationInfo.html#splitPublicSourceDirs

The question

What should be the easiest way to share an APK that got to be split into multiple ones ?

Is it really needed to somehow merge them?

It seems it is possible according to the docs :

Full paths to zero or more split APKs that, when combined with the base APK defined in sourceDir, form a complete application.

But what's the correct way to do it, and is there a fast and efficient way to do it? Maybe without really creating a file?

Is there maybe an API to get a merged APK out of all the split ones? Or maybe such an APK already exist anyway in some other path, and there is no need for merging?

EDIT: just noticed that all third party apps that I've tried are supposed to share an installed app's APK fail to do so in this case.

解决方案

I am the tech lead @Google for the Android Gradle Plugin, let me try to answer your question assuming I understand your use case.

First, some users mentioned you should not share your InstantRun enabled build and they are correct. The Instant Run builds on an application is highly customized for the current device/emulator image you are deploying to. So basically, say you generate an IR enabled build of your app for a particular device running 21, it will fail miserably if you try to use those exact same APKs on say a device running 23. I can go into much deeper explanation if necessary but suffice to say that we generate byte codes customized on the APIs found in android.jar (which is of course version specific).

So I do not think that sharing those APKs make sense, you should either use a IR disabled build or a release build.

Now for some details, each slice APK contains 1+ dex file(s), so in theory, nothing prevents you from unziping all those slice APKs, take all the dex files and stuff them back into the base.apk/rezip/resign and it should just work. However, it will still be an IR enabled application so it will start the small server to listen to IDE requests, etc, etc... I cannot imagine a good reason for doing this.

Hope this helps.

这篇关于如何在 Android 内部共享使用即时运行时创建的拆分 APK?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆