Quero usar uma biblioteca nativa existente de outro projeto Android, então apenas copiei a biblioteca construída do NDK ( libcalculate.so ) para meu novo projeto Android. No meu novo projeto Android, criei uma pasta libs/armeabi/
e coloquei libcalculate.so lá. Não há jni / pasta. Meu dispositivo de teste tem arquitetura ARM.
No meu código java, carrego a biblioteca:
static{
System.loadLibrary("calculate");
}
Quando executo meu novo projeto android, recebo o erro:
java.lang.UnsatisfiedLinkError: ...
nativeLibraryDirectories=[/vendor/lib, /system/lib]]] couldn't find "libcalculate.so"
Então, como diz o erro, a biblioteca nativa copiada não está em / verdor / lib ou / system / lib, como resolver esse problema no meu caso?
(Descompactei o pacote apk, em lib / há libcalculate.so)
==== ATUALIZAÇÃO =====
Também tentei criar uma pasta jni / na raiz do projeto e adicionar um arquivo Android.mk em jni /. O conteúdo do Android.mk é:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libcalculate
LOCAL_SRC_FILES := libcalculate.so
include $(PREBUILT_SHARED_LIBRARY)
Então, na raiz do projeto, executei o ndk-build. Depois disso, os diretórios armeabi / e armeabi-v7a / são gerados pelo ndk-build (com libcalculate.so dentro da pasta).
Então eu executo meu maven para construir o projeto com sucesso. No pacote apk final, existem:
lib/armeabi/libcalculate.so
lib/armeabi-v7a/libcalculate.so
Mas quando executo meu aplicativo, o mesmo erro ocorre:
java.lang.UnsatisfiedLinkError: ...
nativeLibraryDirectories=[/vendor/lib, /system/lib]]] couldn't find "libcalculate.so"
fonte
libs/
? Você provavelmente precisa criar um subdiretório por ABI de destino que deseja oferecer suporte (armeabi, armeabi-v7a, x86, mips, etc) e colocar o arquivo .so apropriado em cada subdiretório (ou seja, o arquivo .so construído para armeabi entralibs/armeabi/
, etc).unzip -l package.apk
, por exemplo , ou renomeie o apk para .zip e abra-o com algum aplicativo. Se não estiver lá, algo está errado com o empacotamento (seu IDE percebeu que a pasta está lá, você precisa atualizar o projeto?).Respostas:
Para solucionar a causa (e talvez resolver seu problema ao mesmo tempo), aqui está o que você pode fazer:
Remova a pasta jni e todos os arquivos .mk . Você não precisa deles nem do NDK se não estiver compilando nada.
Copie seu
libcalculate.so
arquivo dentro<project>/libs/(armeabi|armeabi-v7a|x86|...)
. Ao usar o Android Studio, é<project>/app/src/main/jniLibs/(armeabi|armeabi-v7a|x86|...)
, mas vejo que você está usando o eclipse.Construa seu APK e abra-o como um arquivo zip , para verificar se seu
libcalculate.so
arquivo está dentro de lib / (armeabi | armeabi-v7a | x86 | ...) .Remova e instale seu aplicativo
Execute pacotes de pacote dumpsys | grep yourpackagename para obter o nativeLibraryPath ou legacyNativeLibraryDir de seu aplicativo.
Execute ls em nativeLibraryPath que você tinha ou em legacyNativeLibraryDir / armeabi , para verificar se seu libcalculate.so está realmente lá.
Se estiver lá, verifique se não foi alterado em relação ao arquivo libcalculate.so original : ele foi compilado com a arquitetura correta, contém os símbolos esperados, há alguma dependência ausente. Você pode analisar libcalculate.so usando readelf.
Para verificar a etapa 5 a 7, você pode usar meu aplicativo em vez das linhas de comando e ler: Native Libs Monitor
PS: É fácil se confundir sobre onde os arquivos .so devem ser colocados ou gerados por padrão. Aqui está um resumo:
libs / CPU_ABI dentro de um projeto eclipse
jniLibs / CPU_ABI dentro de um projeto Android Studio
jni / CPU_ABI dentro de um AAR
lib / CPU_ABI dentro do APK final
dentro do nativeLibraryPath do aplicativo em um dispositivo <5.0 e dentro do legacyNativeLibraryDir / CPU_ARCH do aplicativo em um dispositivo> = 5.0.
Onde CPU_ABI é qualquer um dos seguintes: armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, mips, mips64 . Dependendo de quais arquiteturas você está almejando e para as quais suas bibliotecas foram compiladas.
Observe também que as libs não são misturadas entre os diretórios CPU_ABI: você precisa do conjunto completo do que está usando, uma lib que está dentro da pasta armeabi não será instalada em um dispositivo armeabi-v7a se houver libs dentro da armeabi -v7a pasta do APK.
fonte
7
seção: você quer dizer que o .so pode ser alterado do APK após ter sido instalado no dispositivo? Em caso afirmativo, haveria uma chance de o sistema danificar o arquivo .so?No gradle, depois de copiar todas as pastas de arquivos para
libs/
Adicionando a linha acima para
sourceSets
nobuild.gradle
arquivo funcionou. Nada mais funcionou de forma alguma.fonte
Você está usando o Gradle? Se assim for, coloque o
.so
arquivo em<project>/src/main/jniLibs/armeabi/
Espero que ajude.
fonte
No meu caso, devo excluir as fontes de compilação pelo gradle e definir o caminho das libs
fonte
O motivo desse erro é porque há uma incompatibilidade de ABI entre seu aplicativo e a biblioteca nativa à qual você vinculou. Em outras palavras, seu aplicativo e seu
.so
têm como alvo ABI diferentes.se você criar seu aplicativo usando os modelos mais recentes do Android Studio, ele provavelmente terá como alvo o,
arm64-v8a
mas seu.so
pode ser o alvo,armeabi-v7a
por exemplo.Existem duas maneiras de resolver este problema:
.so
construiu.A escolha 2 é suja, mas acho que você provavelmente tem mais interesse em:
mude o do seu aplicativo
build.gradle
fonte
Para referência, recebi esta mensagem de erro e a solução foi que quando você especifica a biblioteca, você perde o 'lib' na frente e o '.so' no final.
Portanto, se você tiver um arquivo libmyfablib.so, precisará chamar:
Tendo olhado no apk, instalado / desinstalado e tentado todos os tipos de soluções complexas, eu não conseguia ver o problema simples que estava bem na minha frente!
fonte
System.loadLibrary
no códigoEsta é uma atualização do Android 8.
Na versão anterior do Android, para carregar bibliotecas compartilhadas nativas (para acesso via JNI, por exemplo), conectei meu código nativo para iterar por meio de uma gama de caminhos de diretório potenciais para a pasta lib, com base nos vários algoritmos de instalação / atualização de apk:
Essa abordagem é piegas e não funciona no Android 8; em https://developer.android.com/about/versions/oreo/android-8.0-changes.html, você verá que, como parte de suas alterações de "Segurança", agora você precisa usar sourceDir:
"Você não pode mais supor que os APKs residam em diretórios cujos nomes terminam em -1 ou -2. Os aplicativos devem usar sourceDir para obter o diretório e não depender diretamente do formato do diretório."
Correção, sourceDir não é a maneira de encontrar suas bibliotecas compartilhadas nativas; use algo parecido. Testado para Android 4.4.4 -> 8.0
fonte
Tente ligar para sua biblioteca após incluir a
PREBUILT_SHARED_LIBRARY
seção:Atualizar:
Se você usar esta biblioteca em Java, você precisa compilá-la como uma biblioteca compartilhada
E você precisa implantar a biblioteca no
/vendor/lib
diretório.fonte
Você pode apenas alterar a ABI para usar compilações mais antigas:
Você também deve usar o NDK obsoleto adicionando esta linha a
gradle.properties
:fonte
por favor adicione todo o suporte
app / build.gradle
app \ src \ jni \ Application.mk
fonte
Na minha experiência, em um armeabi-v7a mobile, quando os diretórios armeabi e armeabi-v7a estão presentes no apk, os arquivos .so no diretório armeabi não serão vinculados, embora os arquivos .so em armeabi SEJAM vinculados no mesmo armeabi-v7a móvel, se armeabi-v7a não estiver presente.
fonte
na verdade, você não pode simplesmente colocar um arquivo .so no
/libs/armeabi/
e carregá-lo comSystem.loadLibrary
. Você precisa criar um arquivo Android.mk e declarar um módulo pré-construído onde você especifica seu arquivo .so como uma fonte.Para fazer isso, coloque seu arquivo .so e o arquivo Android.mk na
jni
pasta. Seu Android.mk deve ser parecido com isto:Fonte: documentação do Android NDK sobre pré-construído
fonte