Cómo obtener archivos en activos desde Android NDK
Estoy tratando de acceder a un archivo de imagen en la carpeta de activos desde el lado nativo. Ahora puedo buscar con éxito a través de la carpeta de los activos y sus subdirectorios que localizan el archivo particular que estoy buscando:
AAssetDir* assetDir = AAssetManager_openDir(asset_manager, "images"); const char* filename; while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) { __android_log_print(ANDROID_LOG_DEBUG, "Debug", filename); } AAssetDir_close(assetDir);
También estoy usando OSG. Fijé la imagen como textura a mi shader con el código siguiente:
- Gradle build Error: Causa: org.gradle.api.internal.ExtensibleDynamicObject
- ¿Cuáles son las consecuencias si intentamos conectar un hilo nativo permanentemente a la DVM (JVM)?
- Error de compilación de pjsip 2.5.5
- Cómo comprobar el registro de bloqueo usando android ndk en cocos2d-x
- Android NDK #define problemas
texture->setImage(osgDB::readImageFile(fileNameWithPath));
Pero ese nombre de archivo debe incluir la ruta absoluta también ya que no se encuentra en el mismo directorio. Sin embargo, descubrí que no puedo obtener la ruta absoluta para el directorio de activos, ya que se comprime junto con el APK.
Siendo que no puedo acceder al camino absoluto, ¿de qué otra manera podría usar para obtener la imagen? También a la nota, deseo guardar los archivos en la carpeta del activo como appose a la tarjeta del sd.
- Bloquear el cuadro de diálogo desde el código JNI
- Construyendo ICU con NDK
- ¿Cómo incluir un .so lib en el proyecto Intellij IDEA for Android?
- El vinculador NDK 11 trata las advertencias como errores
- Error de Compilación NDK de Android NDK_PROJECT_PATH = nulo
- NDK / JNI: identificando el hilo actual
- Vinculación de STL a un ejecutable NDK independiente de Android
- Java.lang.UnsatisfiedLinkError falla en algunos dispositivos
Puede leer la imagen desde el activo con AAssetManager_open
& AAsset_read
, pero como el recurso se encuentra en apk no se puede obtener un nombre de ruta de acceso para él, sino que también se comprime allí. Puede guardar los datos en un archivo y leerlos posteriormente o directamente puede procesar el fragmento que obtuvo del archivo de activos si OSG lo permite.
Desde aquí :
AAssetDir* assetDir = AAssetManager_openDir(mgr, ""); const char* filename = (const char*)NULL; while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) { AAsset* asset = AAssetManager_open(mgr, filename, AASSET_MODE_STREAMING); char buf[BUFSIZ]; int nb_read = 0; FILE* out = fopen(filename, "w"); while ((nb_read = AAsset_read(asset, buf, BUFSIZ)) > 0) fwrite(buf, nb_read, 1, out); fclose(out); AAsset_close(asset); } AAssetDir_close(assetDir);
Una cosa más vale la pena mencionar es que androide pone la restricción en el tamaño de los activos que se pueden leer en el momento, a 1Mb. En caso de que su archivo es más grande que eso, usted tiene que dividirlo en trozos. Aquí está mi solución de trabajo que carga el archivo en pedazos al vector de caracteres:
AAssetManager * mgr = app->activity->assetManager; AAssetDir* assetDir = AAssetManager_openDir(mgr, ""); const char* filename; std::vector<char> buffer; while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) { //search for desired file if(!strcmp(filename, /* searched file name */)) { AAsset *asset = AAssetManager_open(mgr, filename, AASSET_MODE_STREAMING); //holds size of searched file off64_t length = AAsset_getLength64(asset); //keeps track of remaining bytes to read off64_t remaining = AAsset_getRemainingLength64(asset); size_t Mb = 1000 *1024; // 1Mb is maximum chunk size for compressed assets size_t currChunk; buffer.reserve(length); //while we have still some data to read while (remaining != 0) { //set proper size for our next chunk if(remaining >= Mb) { currChunk = Mb; } else { currChunk = remaining; } char chunk[currChunk]; //read data chunk if(AAsset_read(asset, chunk, currChunk) > 0) // returns less than 0 on error { //and append it to our vector buffer.insert(buffer.end(),chunk, chunk + currChunk); remaining = AAsset_getRemainingLength64(asset); } } AAsset_close(asset); } }