Poprawna procedura kompilacji była stosunkowo łatwa, moim problemem było to, że uzależnienie libmod1.so od libmod2.so powodowało niezadowalające linki przy starcie - kod mod1 nie mógł znaleźć biblioteki współdzielonej mod2, mimo że oba były obecne w tym samym folderze w ostateczna APK, pod libs/armeabi, libs/x86 itd. Jednakże, aby moja odpowiedź pełna:
Połóż C lub C++ źródła i pliki nagłówkowe pod podkatalogów z JNI dir w projekcie z Androidem na przykład foldery mod1/i mod2/
Według instrukcji NDK, utwórz plik Application.mk, np. Kopalnia jest:
NDK_TOOLCHAIN_VERSION = 4,7
APP_PLATFORM: = android-8
APP_ABI: = armeabi armeabi-v7a x86
- Tworzenie Android.mk następstwie tego szablonu:
LOCAL_PATH: = $ (wezwanie my-dir)
obejmują $ (CLEAR_VARS)
LOCAL_SHARED_LIBRARIES: = MOD2 # To sprawia libmod1.so zależne libmod2.so
LOCAL_MODULE: = mod1
LOCAL_SRC_FILES: = mod1 /file1.c
LOCAL_SRC_FILES + = mod1/file2.cpp
...
obejmują $ (BUILD_SHARED_LIBRARY) # to faktycznie buduje libmod1.so
obejmują $ (CLEAR_VARS)
LOCAL_MODULE: = MOD2
LOCAL_SRC_FILES: = MOD2/file1.cc
LOCAL_SRC_FILES + = MOD2/file2.cc
...
obejmują $ (BUILD_SHARED_LIBRARY) # To buduje libmod2 .so
To wszystko, wszystkie kompilacje bez skarg ze skryptem ndkbuild. Do wywoływania niektórych funkcji z Javy potrzebujesz tylko opakowania C. I oto był mój problem. Ponieważ miałem funkcje wywoływalne z Java tylko w libmod1.tak, mój C klasy otoki w Javie było jak:
public class CWrapper {
static {
System.loadLibrary("mod1");
}
public static native int func1(String aParam);
...
}
Wydawało mi się zupełnie logiczne - Zadzwonię do libmod1.so z Jawy, więc użyłem System.loadLibrary („Mod1”), a od libmod1. więc wie, że to zależy od libmod2.so, a oba pliki są w tym samym folderze, libmod1 będzie wiedział, jak znaleźć i załadować libmod2, prawda? Źle! Po uruchomieniu aplikacji nastąpił awaria z "niezadowolonym łączem". Dokładny komunikat o błędzie:
java.lang.UnsatisfiedLinkError: Cannot load library: soinfo_link_image(linker.cpp:1635): could not load library "libmod2.so" needed by "libmod1.so"; caused by load_library(linker.cpp:745): library "libmod2.so" not found
Szukałem wszędzie na trochę więcej kodu, aby dodać do Android.mk aby rozwiązać ten problem na marne. Wreszcie Eureka! I zmodyfikowane moją klasę CWrapper następująco:
public class CWrapper {
static {
System.loadLibrary("mod2"); // must be first, as mod1 depends on mod2!
System.loadLibrary("mod1");
}
public static native int func1(String aParam);
...
}
i rzeczy rozpoczął pracę jak czar ...
Greg
Z tego możemy wywnioskować, że dynamiczne sprawdza system jest ładowarka i obciążenia (standardowe Zależności zachowanie), podczas gdy program ładujący Java nie. – Samveen
To jest dobra obserwacja, @Samveen. Może powinienem przetestować to ponownie w nowszych wersjach Androida, aby sprawdzić, czy ostatnio coś ulepszyły. – gregko