Android NDK和Google Play过滤

时间:2012-06-01 08:17:14

标签: android android-ndk android-manifest google-play apk

Google Play appstore会自动将您的应用程序过滤到具有兼容CPU架构的设备。例如。如果您有一个仅为ARMv5编译的库,则您的应用程序将仅显示具有ARMv5或ARMv7处理器的设备。

如果我有Java备选方案,并且希望我的应用程序也可以通过非ARM设备下载,该怎么办? 例如。我在尝试加载外部库时捕获异常,并在Dex字节码(Java)中实现可行的替代方法。

当我上传.apk时,Android Developer Console会说: “此apk请求1个将用于Google Play过滤的原生平台。 armeabi“

我是否需要为x86和MIPS编译虚拟库?然后在我的Java代码中,检查处理器体系结构以了解我是否可以实际使用该库?应该有一个更好的解决方案。

据我所知,Manifest中没有任何关于CPU架构的内容,我在Developer Console中找不到关闭此过滤器的方法。

希望有人比我更了解Google Play过滤和NDK知道答案。

2 个答案:

答案 0 :(得分:11)

虽然对loadLibrary失败进行捕获可以在任何设备上运行(至少我尝试过的所有设备都包括GTV),但如果apk中不存在该平台的ABI,Play Store将不会显示在设备上。

来自文档(http://developer.android.com/guide/appendix/market-filters.html):包含针对特定平台(例如ARM EABI v7或x86)的本机库的应用程序仅在支持该平台的设备上可见。

理论上,所有平台的构建都能够定位所有设备,但实际上有一些像Google Tv这样的设备没有报告ABI,这意味着只有没有本机代码的apks才会出现在Play商店中在那些设备上。您可以使用多个apks,但是,1表示没有本机代码,1表示支持本机代码的所有平台。

您可以在此处阅读多个apk支持:http://developer.android.com/guide/market/publishing/multiple-apks.html

答案 1 :(得分:6)

这里有一个非常完整的答案:http://grokbase.com/t/gg/android-ndk/125v31e6wy/play-store-market-filtering-of-ndk-libs

让我发布自己的解决方案,这与我在这里发布的几乎相同:Android library .so with x86 architecture missing? (Vuforia)

所以你有一个不能在x86架构上编译的常规Android.mk因为你正在使用的库(libExternalLibrary.so)仅用于arm archi。 你想基于这个库构建一个.so(libMyLibraryBasedOnExternalLibrary.so),当然它不会在没有库的情况下在x86上编译。

我们的想法是使用条件编译指令直接在Android.mk中直接生成x86的Dummy库。

1)创建2个虚拟.cpp文件Dummy0.cpp和Dummy1.cpp例程Dummy0.cpp如下所示:

#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <string>

#ifdef __cplusplus
extern "C"
{
#endif

int dummy0                        =  0;

#ifdef __cplusplus
}
#endif

然后,编辑构建库的Android.mk并按如下方式修改它:

LOCAL_PATH := $(call my-dir)

ifeq ($(TARGET_ARCH_ABI), armeabi)


# In this condtion block, we're compiling for arm architecture, and the libExternalLibrary.so is avaialble
# Put every thing the original Android.mk was doing here, importing the prebuilt library, compiling the shared library, etc...
# ...
# ...

else

# In this condtion block, we're not compiling for arm architecture, and the libExternalLibrary.so is not availalble.
# So we create a dummy library instead.

include $(CLEAR_VARS)
# when LOCAL_MODULE equals to ExternalLibrary, this will create a libExternalLibrary.so, which is exactly what we want to do.
LOCAL_MODULE := ExternalLibrary
LOCAL_SRC_FILES := Dummy0.cpp
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
# This will create a libMyLibraryBasedOnExternalLibrary.so
LOCAL_MODULE := MyLibraryBasedOnExternalLibrary
# Don't forget to tell this library is based on ExternalLibrary, otherwise libExternalLibrary.so will not be copied in the libs/x86 directory
LOCAL_SHARED_LIBRARIES := ExternalLibrary
LOCAL_SRC_FILES := Dummy1.cpp
include $(BUILD_SHARED_LIBRARY)

endif

当然,请确保在您的代码中,当您的应用在仅限x86的设备上运行时,您永远不会调用该库:

if ((android.os.Build.CPU_ABI.equalsIgnoreCase("armeabi")) || (android.os.Build.CPU_ABI2.equalsIgnoreCase("armeabi"))) {
    // Good I can launch
    // Note that CPU_ABI2 is api level 8 (v2.2)
    // ...
}