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
.