我的Mac上有一个Android构建环境。当我运行ant debug
时,它会将libandroidnative.so
干净地打包到APK文件中进行部署。这是意料之中的事。
我正在将我的构建设置迁移到Windows PC上。当我运行ant debug
时,它成功完成,而没有将"libandroidnative.so"打包到APK文件中。
代码库完全相同——这是从同一个repo中提取的。NDK(r8)和SDK(2013-05-22)的版本完全相同。
这是我的Mac上的(工作)输出:
res/layout/main.xml
AndroidManifest.xml
resources.arsc
res/drawable-hdpi/ic_launcher.png
res/drawable-ldpi/ic_launcher.png
res/drawable-mdpi/ic_launcher.png
res/drawable-xhdpi/ic_launcher.png
classes.dex
lib/armeabi/gdbserver
lib/armeabi/libandroidnative.so <--- success!
lib/x86/gdbserver
lib/x86/libandroidnative.so
META-INF/MANIFEST.MF
META-INF/CERT.SF
META-INF/CERT.RSA
这是我电脑上的非工作输出:
res/layout/main.xml
AndroidManifest.xml
resources.arsc
res/drawable-hdpi/ic_launcher.png
res/drawable-ldpi/ic_launcher.png
res/drawable-mdpi/ic_launcher.png
res/drawable-xhdpi/ic_launcher.png
classes.dex
lib/armeabi/gdbserver
lib/armeabi-v7a/gdbserver
lib/x86/gdbserver
META-INF/MANIFEST.MF
META-INF/CERT.SF
META-INF/CERT.RSA
请注意,Eclipse构建也会发生同样的情况。
这是我的Ant构建文件(无注释):
<?xml version="1.0" encoding="UTF-8"?>
<project name="AndroidNativeLayer" default="help">
<property file="local.properties" />
<property file="ant.properties" />
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<loadproperties srcFile="project.properties" />
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<import file="custom_rules.xml" optional="true" />
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>
我拿到了。TLDR;eclipse在生成新文件之前删除旧的.so文件,无论运行ndk构建是否生成新文件。确保ndk-build命令创建一个新命令。
在我的例子中,只有当环境变量设置为某个值时,我才进行构建。我在Android.mk中有一个逻辑分支,如果环境变量不匹配,它会自动退出。
在Linux/Mac上,可以键入set SOME_VAR="foo"
。在Windows上的批处理文件中,键入set SOME_VAR="foo"
会在环境变量名中包含引号。
太可怕了,完全是我的错。我之所以继续提出这个问题,是因为这个问题开始时的普遍智慧可能是相关的。
同样值得理解的是:您可以键入aapt list binsomepackage.apk
来生成我在原始帖子中使用的列表。
根据http://docs.xamarin.com/guides/android/advanced_topics/cpu_architecture,对于不同的android版本,原生库表现不同。
Android 4.0之前的Ice Cream Sandwich将只从.apk 中的单个ABI提取本地库
因此,当针对4.0之前的Android版本时,有必要为应用程序将支持的每个ABI提供所有本地库。
此外,它还提到
安卓4.0冰淇淋三明治改变了提取逻辑。它会枚举所有本机库,查看文件的基本名称是否已经已提取,如果满足以下两个条件,则该库将被提取
它还没有被提取出来。本地库的ABI与目标的主要或次要ABI。
不幸的是,这种行为依赖于订单。
本机库按"顺序"处理(如所列,用于例如,解压缩),并且提取第一个匹配。自从.apk包含libtwo.so的armeabi和armeabi-v7a版本armeabi列在第一位,它是提取的armeabi版本,不是armeabi-v7a版本:
>如果该应用程序将在4.0.4之前的Android上运行,该应用程序只包含armeabi-v7a,而不包含armeabi。包括x86或任何其他ABI都不会造成问题;只是两者兼而有之armeabi和armeabi-v7a是一个问题
对于4.0.4后
Android 4.0.4改变了提取逻辑:它将枚举所有原生库,读取文件的基本名称,然后提取主ABI版本(如果存在)或辅助ABI(如果存在的话)。这允许"合并"行为