Загрузка сторонних разделяемых библиотек из основной деятельности Android
Я построил библиотеку Assimp как общую библиотеку. Я включил его в свой проект Android ndk, и он отлично работает, но когда я его загружаю, я получаю следующую ошибку:
Невозможно загрузить собственную библиотеку: My-Native-Activity.
(Возможно, я должен добавить, что моя работа отлично работает, когда библиотека не включена и что я проверил apk и на устройстве, библиотека добавляется в папку libs и устанавливается на устройство в/data/данные/мой-приложение/Lib.)
Я много читал, и кажется, что единственный способ решить это - загрузить их с помощью System.loadLibrary, прежде чем запускать мою собственную активность. Я думаю, что предпочитаю загружать их динамически, используя dlopen, прежде чем принимать этот подход.
Правильно ли я полагаю, что Android не будет автоматически загружать разделяемые библиотеки, зависит от моей основной активности (то есть моя разделяемая библиотека)?
Я бы построил его как статическую библиотеку, но это было более 54 Мб, которые не будут работать.
Это мой Android.mk:
Я попытался добавить -lassimp в LOCAL_LDLIBS. Я не уверен, что это было бы правильно, но это не имело никакого значения.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := assimp
LOCAL_SRC_FILES := libassimp.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := native-activity
LOCAL_SRC_FILES := main.cpp
LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv2
LOCAL_STATIC_LIBRARIES := android_native_app_glue
LOCAL_SHARED_LIBRARIES := assimp
LOCAL_CPPFLAGS += -march=armv7-a -mfloat-abi=softfp
LOCAL_CFLAGS := $(LOCAL_CPPFLAGS)
TARGET_ARCH_ABI := armeabi-v7a
LOCAL_C_INCLUDES += $(LOCAL_PATH)
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/native_app_glue)
Ответы
Ответ 1
Подклассификация android.app.NativeActivity - это самый простой способ решить эту проблему.
package com.you;
public class MyNativeActivity extends android.app.NativeActivity {
static {
System.loadLibrary("assimp");
}
}
Затем измените свой AndroidManifest.xml
. Замените android.app.NativeActivity
на MyNativeActivity
и удалите тег hasCode="false"
.
В качестве дополнительной заметки Android выполняет поиск зависимостей при загрузке разделяемой библиотеки. Но область поиска ограничена /system/lib
.
Ответ 2
Вы хотите запустить NativeActivity с помощью java-активности. Таким образом вы можете загружать общие библиотеки перед NativeActivity.
AndroidManifest.xml
<application android:label="@string/app_name" android:hasCode="true">
<activity android:name="DummyActivity"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="android.app.NativeActivity"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<meta-data android:name="android.app.lib_name"
android:value="native-activity" />
</activity>
</application>
DummyActivity.java
package com.example.native_activity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class DummyActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
System.loadLibrary("some_shared_lib");
System.loadLibrary("native-activity");
super.onCreate(savedInstanceState);
Intent intent = new Intent(DummyActivity.this, android.app.NativeActivity.class);
DummyActivity.this.startActivity(intent);
}
}
Ответ 3
Использование System.loadLibrary
- путь.
Android не будет автоматически загружать зависимые общие библиотеки для вас. Поэтому вам нужно сделать что-то вроде этого:
static {
System.loadLibrary("assimp"); // dependency .so first
System.loadLibrary("native-activity"); // dependent .so second
}
Этот код обычно входит в класс, который содержит собственные методы Java (т.е. методы, определенные с ключевым словом native
, которые отображаются на собственный код). Поскольку этот код выполняется в блоке static
, он выполняется, когда загрузчик классов Java загружает класс - то есть до того, как какой-либо код в классе действительно будет выполнен.
Вам не нужно добавлять ссылки на assimp
в LOCAL_LDLIBS
, потому что вы уже ссылаетесь на assimp
с помощью объявления LOCAL_SHARED_LIBRARIES
.
Этот вопрос может иметь значение.
Ответ 4
1: U не мог использовать dlopen, так как System.loadLibrary - единственный метод, который загружает собственную библиотеку из уровня Java.
2: путь библиотеки Ур выглядит неверно, местоположение должно быть чем-то вроде /data/data/urapp/lib/
U нужно запереть библиотеку ur в файл ur apk, а при установке, android распакует его и поместит в/data/data/urapp/lib/автоматически.
Надежность выше информации полезна для u.