Android NDK: чтение файла из ресурсов внутри общей библиотеки

В моем приложении я должен передать файл из папки активов в общую библиотеку. Я не могу сделать это с использованием jni прямо сейчас. Я использую предварительно скомпилированную разделяемую библиотеку в своем проекте, в которой у меня есть жестко заданный путь к моему файлу, но я получаю сообщение об ошибке "Нет такого файла или каталога". Так что в моем файле .apk у меня есть файл .so в папке libs/armeabi-v7a, а мой файл в папке / assets.

Я пытался сделать это так:

char *cert_file = "/assets/cacert.cert";
av_strdup(cert_file);

И некоторые другие пути, но это не работает.

Это вообще возможно?

3 ответа

Решение

Ваши ресурсы упакованы в ваш apk, поэтому вы не можете обращаться к ним напрямую во время выполнения, как в приведенном вами примере кода. У вас есть 2 варианта здесь:

  • Обработать активы как входной поток, используя

Context.getAssets().open('cacert.cert')

  • Скопируйте ваш ресурс в локальный файл в вашем каталоге dir, а затем укажите имя файла скопированного файла.

Вы можете просто использовать класс AAssetManager в C++.

В основном вам нужно:

  • Во время инициализации вашей библиотеки получите указатель на: AAssetManager* assetManager
  • Используйте его, чтобы прочитать ваш файл:

    // Open your file
    AAsset* file = AAssetManager_open(assetManager, filePath, AASSET_MODE_BUFFER);
    // Get the file length
    size_t fileLength = AAsset_getLength(file);
    
    // Allocate memory to read your file
    char* fileContent = new char[fileLength+1];
    
    // Read your file
    AAsset_read(file, fileContent, fileLength);
    // For safety you can add a 0 terminating character at the end of your file ...
    fileContent[fileLength] = '\0';
    
    // Do whatever you want with the content of the file
    
    // Free the memoery you allocated earlier
    delete [] fileContent;
    

Вы можете найти официальную документацию ndk здесь.

Редактировать: чтобы получить объект AAssetManager:

  • В нативном действии вы выполняете основные функции в качестве параметра android_app * app, вам просто нужно получить его здесь: app->activity->assetManager
  • Если у вас есть Java-активность, вам нужно отправить через JNI экземпляр java-объекта AssetManager, а затем использовать функцию AAssetManager_fromJava()

Основываясь на ответе @Sistr, я использовал getBufferвместе с AASSET_MODE_BUFFER(вместо AAsset_read).

Однако я пытался записать буфер в ofstream. Я получил сбои сигнала, используя:

      ofstream myStream(<some file>, ios_base::binary);
auto buffer = AAsset_getBuffer(asset);
myStream << buffer;

Я предполагаю, что это потому, что указатель буфера указывает на актив без NULLсимвол в конце (я читал текстовый ресурс; исходный код Android ). С использованием writeфункция сработала:

      ofstream myStream(<some file>, ios_base::binary);
auto buffer = AAsset_getBuffer(asset);
myStream.write((char *)buffer, AAsset_getLength(asset));

Это потому, что <<operatorне нужно звонить strlenчтобы узнать, сколько символов нужно написать, поскольку это явно указано AAsset_getLength.

Другие вопросы по тегам