2012-06-01 19 views
9

Google Play Store automaticamente filtra l'applicazione su dispositivi con architettura CPU compatibile. Per esempio. se disponi di una libreria compilata solo per ARMv5, la tua app verrà visualizzata solo per i dispositivi con processori ARMv5 o ARMv7.Filtro NDK Android e Google Play

Cosa succede se ho un'alternativa Java e voglio che la mia app sia scaricata anche da dispositivi non ARM? E.g. Rilevo un'eccezione quando provo a caricare la libreria esterna e implementare un'alternativa praticabile in Dex bytecode (Java).

Quando carico l'.apk, l'Android Developer Console dice: "Questo apk chiede 1 piattaforme native che verranno utilizzati per il filtraggio di Google Play armeabi"

Devo compilare librerie fittizie per x86 e MIPS? Quindi nel mio codice Java, controlla l'architettura del processore per sapere se posso effettivamente usare la libreria? Ci dovrebbe essere una soluzione migliore.

Per quanto ne so, non c'è nulla nel Manifest sull'architettura della CPU e non riesco a trovare un modo nella Console per gli sviluppatori per disattivare questo filtro.

Speriamo che qualcuno sappia molto più di me sul filtraggio di Google Play e che NDK conosca la risposta.

+0

possibile work around/mocking idea: http://stackoverflow.com/questions/15146174/android-library-so-with-x86-architecture-missing-vuforia – auselen

risposta

11

Durante il trapping per loadLibrary, i guasti funzioneranno su qualsiasi dispositivo (almeno tutto ciò che ho provato inclusi i GTV), ma il Play Store non verrà mostrato sui dispositivi se l'ABI per tale piattaforma non esiste nell'apk.

Dai documenti (http://developer.android.com/guide/appendix/market-filters.html): un'applicazione che include le librerie native destinate a una piattaforma specifica (ARM EABI v7 o x86, ad esempio) sono visibili solo sui dispositivi che supportano tale piattaforma.

In teoria, la creazione di tutte le piattaforme potrebbe essere indirizzata a tutti i dispositivi, ma in pratica ci sono alcuni dispositivi come Google Tv che non riportano ABI, il che significa che solo gli apk che non hanno codice nativo verranno visualizzati nel Play Conservare su quei dispositivi. Puoi utilizzare più apk, tuttavia, 1 senza codice nativo e 1 con tutte le piattaforme che supportano il tuo codice nativo.

Si può leggere su supporto apk multipli qui: http://developer.android.com/guide/market/publishing/multiple-apks.html

+0

E il contrario (che voglio fare ora)? Ho un'applicazione v7 che utilizza librerie v5 (o qualcosa). Ciò significa che dispongo di librerie per entrambe le architetture anche se l'applicazione principale è solo per v7. Attualmente abbiamo appena spostato i file non v7 nella cartella v7, e sembra funzionare, ma è davvero brutto e sbagliato. Non possiamo dividerlo in realtà con più apk perché entrambe le librerie native sono necessarie. – alaeus

+0

@alaeus Questa dovrebbe essere una domanda a parte. Va anche bene - Android ha mantenuto ABI retrocompatibile, quindi il codice ARMv5 funzionerà bene su dispositivi ARMv6/7 (in particolare, tutti usano l'ABI "soft-float" che può avere una significativa penalizzazione delle prestazioni, ma è qualcosa dovremo vivere con). –

6

C'è una risposta molto completa a questa stessa domanda qui: http://grokbase.com/t/gg/android-ndk/125v31e6wy/play-store-market-filtering-of-ndk-libs

Permettetemi di postare la mia soluzione, è quasi la stessa che ho postato qui : Android library .so with x86 architecture missing? (Vuforia)

Quindi si dispone di un normale Android.mk che non può essere compilato su architettura x86 in quanto la libreria (libExternalLibrary.so) che si sta utilizzando viene fornita solo per archi arm. Si desidera creare un .so (libMyLibraryBasedOnExternalLibrary.so) basato su questa libreria e, naturalmente, non verrà mai compilato su x86 senza la libreria.

L'idea è di generare librerie Dummy per x86 direttamente direttamente in Android.mk, utilizzando le istruzioni di compilazione condizionale.

1) Creare 2 file cpp fittizi Dummy0.cpp e Dummy1.cpp exemple Dummy0.cpp assomiglia a questo:

#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 

Quindi, modificare l'Android.mk che costruisce la libreria e modificarlo in questo modo:

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 

Naturalmente, assicurarsi che nel codice che non hai mai chiamare la libreria quando la vostra applicazione è in esecuzione su un solo x86 dispositivo:

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

Sto ottenendo l'errore qui sotto quando sto provando i passaggi simili: /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: errore: impossibile trovare -lExternalLibrary.so collect2: ld restituito 1 stato di uscita –

+0

È un errore di compilazione per quale architettura? Riesci a vedere nei log la compilation di Dummy0.cpp? – jptsetung

+0

Sto costruendo per l'architettura Arm ma prima viene generata la lib ExternalLibrary.so. Non so perché venga in altro momento quando sto costruendo su arm-architecture.Shall uso l'approccio Ndk invece di questo? –