Название говорит само за себя. Я использую NDK для создания собственной библиотеки для использования с Unity (игровой движок, а не оболочка Ubuntu). У меня уже есть большая часть кода, и он работает на моем Xperia Z Ultra, который работает под управлением Android 4.4.4. Однако недавно я отправил приложение другим людям для тестирования на их телефонах, и оно не работало ни на одном из их телефонов. Они использовали Android 4.0 и 4.1, поэтому я попытался запустить приложение на своем собственном устройстве Android 4.0.4 (старый Xperia Mini Pro) и столкнулся с той же проблемой. После значительного сужения я обнаружил, что корень проблемы заключается во включении OpenCV в сборку, даже если на него вообще нет ссылок.

Вот код, который у меня есть. Во-первых, самый простой файл CPP, который вы видели:

//Test.cpp:
extern "C"
{
    int Test(int a, int b)
    {
        return a + b;
    }
}

Обратите внимание, что он даже не включает ничего из OpenCV. Makefile (или как он там называется в контексте NDK, я в основном работаю с Windows / Visual Studio):

#Android.mk:
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

#---------------------------
#note: if I comment these lines out, the library works just fine.
#if I don't, it won't load at all.
#---------------------------
OPENCV_PACKAGE_DIR := D:\Eclipse\OpenCVAndroid\OpenCV-2.4.9-android-sdk
include $(OPENCV_PACKAGE_DIR)/sdk/native/jni/OpenCV.mk

LOCAL_MODULE    := Test
LOCAL_SRC_FILES := Test.cpp

include $(BUILD_SHARED_LIBRARY)

Сборка этого проекта дает мне файл «libTest.so». Я поместил это в свой проект Unity в Assets / Plugins / Android / (я также пробовал поместить его в Plugins / Android / libs / armeabi-v7a /, не повезло). У меня также есть скрипт внутри единства, который вызывает библиотеку:

//TestNative.cs:
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;

public class TestNative : MonoBehaviour
{
    [DllImport("Test")]
    public static extern int Test(int a, int b);

    void OnGUI()
    {
        try
        {
            GUI.Label(new Rect(0, 0, 100, 100), "2 + 3 = " + Test(2, 3));
        }
        catch (System.Exception e)
        {
            GUI.Label(new Rect(0, 0, 600, 400), e.GetType().ToString() + " " + e.Message + "\n" + e.StackTrace);
        }
    }
}

Когда я запускаю это на своем Z Ultra, он работает нормально. Когда я запускаю его на Mini Pro, он не работает с исключением «DllNotFoundException: Test». Я проверил logcat на наличие ошибок, и вот что он говорит:

01-06 06:46:27.660: D/dalvikvm(11135): Trying to load lib /mnt/asec/com.cet.sna2-2/lib/libTest.so 0x2bb86638
01-06 06:46:27.660: D/dalvikvm(11135): Trying to load lib /mnt/asec/com.cet.sna2-2/lib/libTest.so 0x2bb86638
01-06 06:46:27.660: E/Unity(11135): Unable to find Test

Он больше ничего не говорит, он просто не работает. Тот факт, что он работает на 4.4.4, заставляет меня думать, что это может иметь какое-то отношение к конфигурациям сборки или чему-то в этом роде, но я не могу понять, что это такое. Любые идеи? Благодарю.

2
Arshia001 13 Мар 2015 в 19:19

2 ответа

Лучший ответ

После долгих проб и ошибок я выяснил, что причина ошибки в том, что Android каким-то образом удается испортить зависимости библиотеки. Обходной путь - вручную загрузить библиотеки в определенном порядке их зависимостей с помощью LoadLibrary. Это можно сделать в Unity с помощью AndroidJavaClass, чтобы избежать необходимости писать всю библиотеку jar только для загрузки собственных.

1
Arshia001 11 Июн 2015 в 19:40

Вы должны создать .so, который соответствует архитектуре используемого вами устройства. Вы должны посмотреть эту ссылку: https://developer.nvidia.com/AndroidWorks Он предоставляет полезные инструменты для разработки на Android с помощью Visual Studio. Вы можете легко настроить Android Dynamic Library (.so) в соответствии с нужной архитектурой :)

0
Mehdi-Antoine 10 Июн 2015 в 09:46