2012-06-01 44 views
9

Google Play應用商店會自動將您的應用過濾爲兼容CPU架構的設備。例如。如果您有一個僅針對ARMv5編譯的庫,則您的應用只會顯示具有ARMv5或ARMv7處理器的設備。Android NDK和Google Play過濾

如果我有一個Java替代品,並且希望我的應用程序也可以被非ARM設備下載,該怎麼辦? 例如我在嘗試加載外部庫時遇到異常,並在Dex字節碼(Java)中實現了可行的替代方法。

當我上傳.apk文件,Android開發者控制檯說: 「該apk請求將被用於谷歌Play篩選 armeabi 1個的原生平臺」

我需要編譯的x86虛擬圖書館和MIPS?然後在我的Java代碼中,檢查處理器體系結構以確定我是否可以真正使用該庫?應該有更好的解決方案。

據我所知,目前還沒有在清單有關CPU架構,我無法找到在開發者控制檯的方式來關閉這個濾波器。

希望有人知道比我做的更多的Google Play過濾和NDK知道答案。

+0

可能解決/嘲笑的想法:http://stackoverflow.com/questions/15146174/android-library-so-with-x-86-architecture-missing-vuforia – auselen

回答

11

雖然陷阱loadLibrary失敗將適用於任何設備(至少我所嘗試的所有設備包括GTV),但如果該平臺的ABI不存在於apk中,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

+0

相反(我現在要做的)呢?我有一個使用v5(或某些)庫的v7應用程序。這意味着即使主應用程序僅適用於v7,我也有兩種體系結構的庫。目前我們剛剛將非v7文件移動到v7文件夾中,它似乎可行,但它確實很醜陋,也是錯誤的。由於需要兩個本地庫,所以我們不能將它分割成多個apks。 – alaeus

+0

@alaeus這應該是一個單獨的問題。這也很好--Android保持了ABI的向後兼容性,所以ARMv5代碼在ARMv6/7設備上運行得很好(特別是它們都使用「軟浮點」ABI,這會對性能造成嚴重損失,我們必須忍受)。 –

6

有一個非常完整的答案,同樣的問題在這裏:http://grokbase.com/t/gg/android-ndk/125v31e6wy/play-store-market-filtering-of-ndk-libs

讓我發表我自己的解決方案,這幾乎是我在這裏張貼相同:Android library .so with x86 architecture missing? (Vuforia)

所以你有一個常規的Android.mk,不能在x86架構上編譯,因爲你使用的庫(libExternalLibrary.so)只提供給arm archi。 你想建立一個基於這個庫的.so(libMyLibraryBasedOnExternalLibrary.so),當然,如果沒有這個庫,它不會永遠不會編譯。

這個想法是直接在Android.mk中使用條件編譯指令直接爲x86生成虛擬庫。

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) 
    // ... 
} 
+0

當我嘗試類似步驟時,出現以下錯誤:/android/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6/bin/../lib/gcc/arm-linux-androideabi/ 4.6.x-google /../../../../ arm-linux-androideabi/bin/ld:error:找不到-lExternalLibrary.so collect2:ld返回1退出狀態 –

+0

這是一個編譯錯誤哪個架構?你能在日誌中看到Dummy0.cpp的彙編嗎? – jptsetung

+0

我正在爲Arm架構構建,但是第一個庫ExternalLibrary.so被生成了。我不知道爲什麼它會在構建arm架構時到達其他部分。我應該使用Ndk方法而不是這個嗎? –