Search code examples
androidc++kotlinandroid-ndkassets

Android Asset FileNotFound Exception Using Kotlin and Android NDK C++


I am trying to read .obj files in the assets/ folder by passing the AssetManager object from my Kotlin script to the JNI interface, where I can use C++ to parse the .obj files and add it to my OpenGL scene. But the app is not finding any files in my assets folder.

I grab the AssetManager and attempt to pass it to my JNI inside of my renderer class, under the OnSurfaceCreated callback:

Kotlin File:

private external fun loadModels(assetManager: AssetManager): Void //Loaded correctly from companion object
private lateinit var manager: AssetManager
override fun onSurfaceCreated(unused: GL10, config: EGLConfig?) {
    manager = Resources.getSystem().assets //Gets the asset manager (poorly documented)
    loadModels(manager)
    manager.open("hello.txt") //Throws FileNotFoundException
}

C++ file:

#include <jni.h>
#include <android/log.h>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>

extern "C" JNIEXPORT jobject JNICALL
Java_com_example_mypackage_glRenderer_loadModels(JNIEnv *env, jobject thiz, jobject asset_manager) {
    AAssetManager* pAssetManager = AAssetManager_fromJava(env, asset_manager);
    if (pAssetManager == nullptr) {
        __android_log_print(ANDROID_LOG_ERROR, "GL_JNIConnector.cpp", "Failed to load asset manager");
        //Break
        exit(1);
    }
    //Loop through all files in Models folder
    AAssetDir* pModelsDirectory = AAssetManager_openDir(pAssetManager, "Models/");
    //AAssetDir_rewind(pModelsDirectory);
    const char* filename = AAssetDir_getNextFileName(pModelsDirectory); //Incorrectly returns NULL
    __android_log_print(ANDROID_LOG_DEBUG, "GL_JNIConnector.cpp", "%s", filename);
}

But my AAssetDir_getNextFileName(pModelsDirectory) keeps returning NULL, when the files are present in my assets folder, AND unzipping the .apk file also shows they were added to the app correctly.

I tested it within the Kotlin by making up a hello.txt file and trying to access it in Kotlin using manager.open("hello.txt") and this also throws a FileNotFoundException

This is my directory:

Image of assets directory

Even hovering over the filename in my code points to the file in my assets folder, why can't the app find it in runtime?

Pulling apart the APK with Android Studio shows my assets folder intact in the .apk file

Image of Android Studio APK Analyzer


Solution

  • The issue was I grabbed my asset manager using

    manager = Resources.getSystem().assets
    

    which only gets me access to system resources, not application resources. Instead, I should have passed my context from my surface view class to the renderer class

    //Surface View Class
    class glSurfaceView(context: Context, attrs: AttributeSet) : GLSurfaceView(context, attrs)
    //Renderer Class
    class glRenderer(private val context: Context) : GLSurfaceView.Renderer
    

    so that I could get my asset manager simply using

    manager = context.assets
    

    Thanks to @Michael for pointing that out