Issue
I'm trying to load some shader files for an Android App written in C++. It's using the NativeActivity
and native_app_glue
. I'm having a hard time actually getting the Android Asset system to work as expected.
The simplest case that I've tried is:
#include <android_native_app_glue.h>
void android_main(struct android_app *app) {
AAssetDir *dir = AAssetManager_openDir(app->activity->assetManager, "");
if (dir != nullptr) {
LOGD("Opened Dir");
LOGD("Filename: %s", AAssetDir_getNextFileName(dir));
AAssetDir_close(dir);
} else {
LOGE("Failed to open dir");
}
}
AAssetManager_openDir
returns a valid AAssetDir
ptr but AAssetDir_getNextFileName
always returns nullptr. The NDK's asset_manager.h
header seems to imply that my call should be absolutely valid.
/**
* Open the named directory within the asset hierarchy. The directory can then
* be inspected with the AAssetDir functions. To open the top-level directory,
* pass in "" as the dirName.
*
* The object returned here should be freed by calling AAssetDir_close().
*/
I also seem to be unable to refer to any files by a known file path with other AAssetManager
calls.
AAssetManager_open(app->activity->assetManager, "shaders/triangle.vert.spv", AASSET_MODE_BUFFER);
Also fails even though in my APK I can clearly see the files living correctly in assets/shaders
. I can't find any relevant errors from my app in the Logcat. I couldn't find anything relevant in the Android permissions documents about needing some sort of permission to read internal assets.
I'm currently building against Android 28 with the latest NDK r19. Here is my current android-sdk package set that I'm working with:
Installed packages:
Path | Version | Description | Location
------- | ------- | ------- | -------
build-tools;27.0.3 | 27.0.3 | Android SDK Build-Tools 27.0.3 | build-tools\27.0.3\
emulator | 28.0.25 | Android Emulator | emulator\
ndk-bundle | 19.2.5345600 | NDK | ndk-bundle\
patcher;v4 | 1 | SDK Patch Applier v4 | patcher\v4\
platform-tools | 28.0.2 | Android SDK Platform-Tools | platform-tools\
platforms;android-21 | 2 | Android SDK Platform 21 | platforms\android-21\
platforms;android-28 | 6 | Android SDK Platform 28 | platforms\android-28\
tools | 26.0.1 | Android SDK Tools 26.0.1 | tools\
I currently test by deploying to a Pixel 2 XL with the latest patches.
Am I putting assets in the wrong folder? Is there some recent permission changes I've missed?
EDIT #1:
Did some more investigation. Placed a test.txt
at the root of my APK's assets directory so the APK now has assets/test.txt
. I've tried just opening a handle to this file with:
AAsset *asset = AAssetManager_open(app->activity->assetManager, "test.txt",
AASSET_MODE_BUFFER);
if (asset != nullptr) {
LOGD("Opened test file");
AAsset_close(asset);
} else {
LOGE("Failed to open test file");
}
The app prints "Failed to open test file" to the Logcat. Still at a loss for what may be causing this.
EDIT #2: Replying to the first answer.
Trying a more complete code example as suggested doesn't yield any new results:
#include <android_native_app_glue.h>
void android_main(struct android_app *app) {
AAssetManager *assetManager = app->activity->assetManager;
if (assetManager != nullptr) {
AAssetDir *assetDir = AAssetManager_openDir(assetManager, "");
if (assetDir != nullptr) {
uint32_t fileOpenedCounter = 0;
const char *filename = (const char *)NULL;
while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) {
AAsset *asset =
AAssetManager_open(assetManager, filename, AASSET_MODE_BUFFER);
if (asset != nullptr) {
LOGD("Opened test file");
fileOpenedCounter++;
char buf[1024];
int nb_read = 0;
while ((nb_read = AAsset_read(asset, buf, 27)) > 0) {
LOGD("buf: %s", buf);
}
AAsset_close(asset);
} else {
LOGE("Failed to open test file");
}
}
LOGD("Opened %d files from root directory", fileOpenedCounter);
AAssetDir_close(assetDir);
} else {
LOGE("Failed to open root directory");
}
} else {
LOGE("Asset Manager was invalid");
}
}
All I get from the Logcat is the debug log: "Opened 0 files from root directory". This seems to imply that the AAssetManager pointer I have is valid and it can open the directory but it can't find any files or subdirectories.
Solution
I've figured this out. It's a really dumb issue that I doubt most will run into but I'm going to document it here.
Some backstory that I did not think was relevant. I'm not using Android Studio. I'm using the fips build system. It has a simple python script that packages the APK. The script is called from CMake.
I did not understand how aapt packaged asset files. So what I was doing was running a post-build script that would run aapt add
and add my shader files into the APK and then re-align and re-zip the APK.
Taking another look at the aapt tool's help command output I realized there was the -A
flag for adding an assets directory during APK compilation. I was improperly adding my assets into the APK in the first place
The fix was dead simple:
Re-route shader compilation to build into an
assets
directory next to where fips runs its APK packaging.Add
'-A', 'assets'
to the AAPT packaging command in the fips packaging script
A quick look at the change:
# package the APK
cmd = [
AAPT,
'package',
'-v', '-f',
'-S', 'res',
'-M', 'AndroidManifest.xml',
'-A', 'assets',
'-I', SDK_HOME + 'platforms/android-' + args.version + '/android.jar',
'-F', args.path + args.name + '-unaligned.apk',
'bin'
]
So yeah. This had nothing to do with the Android NDK APIs and far more with the actual APK packaging step. Too bad there's nothing in the NDK API to report that a file wasn't found, which would have been a tip-off. There was also no warning from the aapt tool that using aapt add
didn't really add assets to the assets directory in the way I thought it did.
Answered By - Honeybunch
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.