Загрузка сторонних общих библиотек из нативной активности Android - PullRequest
15 голосов
/ 12 января 2012

Я построил библиотеку 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)

Ответы [ 4 ]

19 голосов
/ 26 октября 2012

Создание подклассов 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.

7 голосов
/ 14 июля 2012

Вы хотите запустить 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);
    }
}
1 голос
/ 06 февраля 2012

Использование 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.

Этот вопрос может быть актуальным.

0 голосов
/ 12 января 2012

1: U не может использовать dlopen, так как System.loadLibrary является единственным методом загрузки нативной библиотеки из уровня Java.2: путь к библиотеке Ur выглядит не правильно, расположение должно быть примерно таким:поместите его в / data / data / urapp / lib / автоматически.

Надеюсь, приведенная выше информация полезна для вас.

...