I use OBB to hold my data and need to use Android NDK to access the data. However, I can't seem to mount the obb file to retrieve data. I name my obb after the scheme according to APK Expansion Files documentation.
e.g., main.1.com.example.native_activity.obb
I then put it under /data/Android/obb/com.example.native_activity folder as suggested by the online doc above.
However, by using the following code, I can't make the obb mount:
AStorageManager* man = AStorageManager_new();
char* data = malloc(256);
AStorageManager_mountObb(man, "main.1.com.example.native_activity.obb", "somekey", my_obbCallbackFunc, data);
char* obbPath = AStorageManager_getMountedObbPath(man, "main.1.com.example.native_activity.obb");
LOGI("mounted path: %s", obbPath);
free(data);
data = NULL;
AStorageManager_delete(man);
man = NULL;
The obbPath
turned out to be always empty.
I don't know how to get a proper key so it was just a randomization.
UPDATE:
I corrected two issues from my side.
First, the obb file was not created using the Android jobb tool but renamed from a zip file. So I recreated the file using:
jobb -d assets/ -o obb/main.1.com.example.native_activity.obb -k mykey -pn com.example.native_activity -pv 11
And pushed it under
/sdcard/Android/obb/com.example.native_activity/
I then used the key and a callback function in the mountObb call with code like this:
char obbPath[256];
sprintf(obbPath, "/sdcard/Android/obb/com.example.native_activity/main.1.com.example.native_activity.obb");
struct stat sts;
if(stat(obbPath, &sts) == -1)
{
LOGI("File not found: %s\n", obbPath);
}
else
{
LOGI("File found: %s", obbPath);
}
AStorageManager* man = AStorageManager_new();
char* data = malloc(256);
AStorageManager_mountObb(man, obbPath, "mykey", my_obbCallbackFunc, data);
char* mntPath = AStorageManager_getMountedObbPath(man, obbPath);
int isMounted = AStorageManager_isObbMounted(man, obbPath);
LOGI("mounted path: %s, already mounted?: %d", mntPath, isMounted);
free(data);
data = NULL;
AStorageManager_delete(man);
man = NULL;
return 1;
and the callback
void my_obbCallbackFunc(const char* filename, const int32_t state, void* data)
{
LOGI("my_obbCallbackFunc: %d", state);
}
The Logcat output I got:
08-09 08:45:15.960: I/native-activity(9166): Touched screen.
08-09 08:45:15.960: I/native-activity(9166): File found: /sdcard/Android/obb/com.example.native_activity/main.1.com.example.native_activity.obb
08-09 08:45:15.960: E/Parcel(9166): Reading a NULL string not supported here.
08-09 08:45:15.960: I/native-activity(9166): mounted path: , already mounted?: 0
08-09 08:45:15.970: I/native-activity(9166): Touched screen.
08-09 08:45:15.970: I/native-activity(9166): File found: /sdcard/Android/obb/com.example.native_activity/main.1.com.example.native_activity.obb
08-09 08:45:15.970: E/Parcel(9166): Reading a NULL string not supported here.
08-09 08:45:15.970: I/native-activity(9166): mounted path: , already mounted?: 0
08-09 08:45:16.030: I/native-activity(9166): my_obbCallbackFunc: 1
08-09 08:45:16.030: I/native-activity(9166): my_obbCallbackFunc: 24
08-09 08:45:16.030: I/native-activity(9166): my_obbCallbackFunc: 24
08-09 08:45:16.030: I/native-activity(9166): my_obbCallbackFunc: 24
08-09 08:45:16.030: I/native-activity(9166): my_obbCallbackFunc: 24
08-09 08:45:16.030: I/native-activity(9166): my_obbCallbackFunc: 24
08-09 08:45:16.030: I/native-activity(9166): my_obbCallbackFunc: 24
According to android-ndk-r8d/platforms/android-9/arch-arm/usr/include/android/storage_manager.h
, the error code from the callback means
AOBB_STATE_MOUNTED = 1,
AOBB_STATE_ERROR_ALREADY_MOUNTED = 24,
However, this contradicts the logcat print out of the return value of AStorageManager_isObbMounted() call, which reads that it is not yet mounted.
I'm totally confused.
Solved it myself.
There is definitely something counter-intuitive about the mount-query APIs because the obb has been mounted under /mnt/obb/ when I check the file system but the API keeps returning 0 and refuses to give me the path. It probably (the detail semantic is not documented anywhere) means that THIS very request has failed to get the obb mounted although the file did get already mounted before (error code 24 from the callback).
So if I unmount first before mounting again in the code it should be fine. So basically add this:
AStorageManager_unmountObb(man, obbPath, 1, my_obbCallbackFunc, data);
before
AStorageManager_mountObb(man, obbPath, "mykey", my_obbCallbackFunc, data);
And with callback:
void my_obbCallbackFunc(const char* filename, const int32_t state, void* data)
{
LOGI("my_obbCallbackFunc: %d", state);
AStorageManager* man = AStorageManager_new();
int isMounted = AStorageManager_isObbMounted(man, filename);
char* mntPath = AStorageManager_getMountedObbPath(man, filename);
LOGI("my_obbCallbackFunc: fn: %s: mounted path: %s, already mounted?: %d", filename, mntPath, isMounted);
AStorageManager_delete(man);
}
the successful output:
08-09 10:41:53.060: I/native-activity(10753): File found: /sdcard/Android/obb/com.example.native_activity/main.1.com.example.native_activity.obb
08-09 10:41:53.070: E/Parcel(10753): Reading a NULL string not supported here.
08-09 10:41:53.070: I/native-activity(10753): mounted path: , already mounted?: 0
08-09 10:41:53.080: I/native-activity(10753): Touched screen.
08-09 10:41:53.080: I/native-activity(10753): File found: /sdcard/Android/obb/com.example.native_activity/main.1.com.example.native_activity.obb
08-09 10:41:53.110: I/native-activity(10753): my_obbCallbackFunc: 2
08-09 10:41:53.110: E/Parcel(10753): Reading a NULL string not supported here.
08-09 10:41:53.110: I/native-activity(10753): mounted path: , already mounted?: 0
08-09 10:41:53.110: E/Parcel(10753): Reading a NULL string not supported here.
08-09 10:41:53.110: I/native-activity(10753): my_obbCallbackFunc: fn: /storage/Android/obb/com.example.native_activity/main.1.com.example.native_activity.obb: mounted path: , already mounted?: 0
08-09 10:41:53.110: I/native-activity(10753): Touched screen.
08-09 10:41:53.110: I/native-activity(10753): File found: /sdcard/Android/obb/com.example.native_activity/main.1.com.example.native_activity.obb
08-09 10:41:53.110: E/Parcel(10753): Reading a NULL string not supported here.
08-09 10:41:53.110: I/native-activity(10753): mounted path: , already mounted?: 0
08-09 10:41:53.130: I/native-activity(10753): Touched screen.
08-09 10:41:53.130: I/native-activity(10753): File found: /sdcard/Android/obb/com.example.native_activity/main.1.com.example.native_activity.obb
08-09 10:41:53.130: E/Parcel(10753): Reading a NULL string not supported here.
08-09 10:41:53.130: I/native-activity(10753): mounted path: , already mounted?: 0
08-09 10:41:53.260: I/native-activity(10753): my_obbCallbackFunc: 1
08-09 10:41:53.300: I/native-activity(10753): my_obbCallbackFunc: 2
08-09 10:41:53.300: E/Parcel(10753): Reading a NULL string not supported here.
08-09 10:41:53.300: I/native-activity(10753): my_obbCallbackFunc: fn: /storage/Android/obb/com.example.native_activity/main.1.com.example.native_activity.obb: mounted path: , already mounted?: 1
08-09 10:41:53.300: E/Parcel(10753): Reading a NULL string not supported here.
08-09 10:41:53.300: I/native-activity(10753): my_obbCallbackFunc: fn: /storage/Android/obb/com.example.native_activity/main.1.com.example.native_activity.obb: mounted path: , already mounted?: 0
08-09 10:41:53.490: I/native-activity(10753): my_obbCallbackFunc: 1
08-09 10:41:53.520: I/native-activity(10753): my_obbCallbackFunc: 2
08-09 10:41:53.520: E/Parcel(10753): Reading a NULL string not supported here.
08-09 10:41:53.520: I/native-activity(10753): my_obbCallbackFunc: fn: /storage/Android/obb/com.example.native_activity/main.1.com.example.native_activity.obb: mounted path: , already mounted?: 0
08-09 10:41:53.520: E/Parcel(10753): Reading a NULL string not supported here.
08-09 10:41:53.520: I/native-activity(10753): my_obbCallbackFunc: fn: /storage/Android/obb/com.example.native_activity/main.1.com.example.native_activity.obb: mounted path: , already mounted?: 1
08-09 10:41:53.680: I/native-activity(10753): my_obbCallbackFunc: 1
08-09 10:41:53.720: I/native-activity(10753): my_obbCallbackFunc: 2
08-09 10:41:53.720: E/Parcel(10753): Reading a NULL string not supported here.
08-09 10:41:53.720: I/native-activity(10753): my_obbCallbackFunc: fn: /storage/Android/obb/com.example.native_activity/main.1.com.example.native_activity.obb: mounted path: , already mounted?: 1
08-09 10:41:53.720: E/Parcel(10753): Reading a NULL string not supported here.
08-09 10:41:53.720: I/native-activity(10753): my_obbCallbackFunc: fn: /storage/Android/obb/com.example.native_activity/main.1.com.example.native_activity.obb: mounted path: , already mounted?: 0
08-09 10:41:53.870: I/native-activity(10753): my_obbCallbackFunc: 1
08-09 10:41:53.880: I/native-activity(10753): my_obbCallbackFunc: fn: /storage/Android/obb/com.example.native_activity/main.1.com.example.native_activity.obb: mounted path: /mnt/obb/437f5d6d13a1da1d3b41bb46963e3720, already mounted?: 1
UPDATE: Several more twists that I had to fix before getting this to work completely:
jobb
, in addition to naming the file correctly, the -pv
option has to be used with the correct versionCode as in the manifest.AOBB_STATE_ERROR_COULD_NOT_MOUNT
(error code 21) in your mount callback. This encourages the versioned usage but makes ad-hoc testing on the same OBB hard, i.e., it's not "recommended" to keep changing the OBB without incrementing the versionCode. This means you need to delete the OBB first to "overwrite" the exact same OBB file.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With