工作記錄[續] android OBB


前兩篇在這里:

Android上使用native IO

最近工作中的問題筆記

 

最近遇到的問題是,

java.io.IOException: FAT Full

StackOverflow的結果:

http://stackoverflow.com/questions/18906055/what-causes-jobb-tool-to-throw-fat-full-ioexception

提問者自己解釋了原因, 原因是obb超過512M就出錯了. 但是FAT16最大可以支持2G, 這個是jobb的bug.

同時作者提供了jobb修復的代碼和bin:

https://github.com/monkey0506/jobbifier/tree/master/jObbifier/bin (由於不懂Java/eclipse,花了點時間才編譯打包出來)

 

最后關於在native下 mount一直報錯的問題(AOBB_STATE_ERROR_INTERNAL, AOBB_STATE_ERROR_COULD_NOT_MOUNT)
logcat沒有任何輸出, 同時網上也沒有任何解決方法可以解決我這里遇到的問題.

最后改用在java端mount, 竟然毫無錯誤的成功了...表示很無語. What's wrong with the NDK team? why mounting obb in native fails but in Java end succeeds?

另外, 網上可以找到關於native API code里的問題 https://code.google.com/p/android/issues/detail?id=41983

AStorageManager::getMountedObbPath

https://github.com/android/platform_frameworks_base/blob/master/native/android/storage_manager.cpp

155     const char* getMountedObbPath(const char* filename) {
156         String16 filename16(filename);
157         String16 path16;
158         if (mMountService->getMountedObbPath(filename16, path16)) {
159             return String8(path16).string(); //WTF? return a temp object's buffer? 160         } else {
161             return NULL;
162         }
163     }

由於沒有看String8的實現, 但是單從表面上看, 返回一個local temp object的buffer, 應該是有問題的, 除非buffer是malloc的,但貌似文檔又沒有說要free之類的(或者是mountService內部的也可以). 而實際中我也遇到返回亂碼的情況.

這個問題有人提出很久了, 但是一直沒有人去改..

 

雖然obb的mount都是異步的, 但java的回調是同步的, 而且回調只有在開始了消息循環以后才會被調用. 而native的callback確定是在另外一個線程調用的,難道也要等到消息循環開始以后才可以? 即便是這樣, 這種坑也應該在文檔里面說清楚,或者給個native sample吧..現在只有java的obb sample.

感覺native API上對obb的支持有很多坑還沒有發現. 這部分決定先用java了.

 

 


更新06/05/2014

native代碼是這樣的:

 1 Callback(const char* filename, const SYSTEM::int32_t state, void* callbackdata )
 2 {
 3         Android_App* app = (Android_App*)data;
 4     if( state == AOBB_STATE_MOUNTED )
 5     {
 6         int isMounted = AStorageManager_isObbMounted(app->storage, filename);
 7         assert( isMounted != 0 );
 8 
 9         const char* mntPath = AStorageManager_getMountedObbPath(app->storage, filename);
10         
11         //save persistent path data - current NDK returns tmp string that may even corrupted right after AStorageManager_getMountedObbPath() return
12         //https://code.google.com/p/android/issues/detail?id=41983
13         static char mountPath[PATH_MAX];
14         app->storageRoot = strcpy(mountPath, mntPath);
15         append(mountPath, "/data");
16 
17         LOGI("OBB mounted: %s", filename);
18         pthread_cond_broadcast(&app->cond);
19     }
20     else if( state == AOBB_STATE_UNMOUNTED )
21     {
22         LOGI("OBB unmounted: %s", filename);
23     }
24     else if( state != AOBB_STATE_ERROR_NOT_MOUNTED)
25     {
26         LOGE("VCAndroid_ObbCallbackFunc: %d", state);
27         if( app != null )
28             pthread_cond_broadcast(&app->cond);
29     }
30 }
31 
32 
33 mountOBB()
34 {
35     AStorageManager_mountObb( Callback );
36     pthread_cond_wait(&app->cond, &app->mutex);
37     
38 }
39 
40 
41 //Main thread entry for activity create, called by NactiveActivity.java
42 NativeActivity_onCreate()
43 {
44     ...
45     mountOBB();
46     createthread: android_main(); //this is pseudo code
47     return;
48 }

調用java的native代碼是這樣:

//pseudo codes:

mountOBB()
{
     call Java code to mount
}

bool isOBBMounted()
{
    query Java code whether mount ready
}

NativeActivity_onCreate(...)
{
    ...
    mountOBB();
    create thread: android_main();
}


android_main()
{

    while ((ident= ALooper_pollAll(...)) >= 0 )
    {
        if( isOBBMounted() )
            continue_app();
    }
}

最后嘗試把native代碼也全放在android_main()線程里,而且等窗口創建好, 像用Java代碼那樣循環查詢, 還是失敗...

 

 

還有, 測試的時候還發現, 某些設備push OBB以后app讀取不出來, 最后發現是沒有使用新的標准路徑,
有的設備上/sdcard/Android/obb/com.XXX.XXX/ 是無法訪問的. 要使用sdk/tools/monnitor查看mount的真正路徑,然后方進去

http://stackoverflow.com/questions/18064114/expansion-file-cant-load-obb-from-sdcard-android-obb-on-android-4-2

比如三星的Galaxy S4, 更新到4.4.2的系統, 直接adb push到/sdcard/Android/obb/XXX/main.1.XXX.obb就沒有問題,

而Galaxy Note 10 2014新版雖然系統版本是4.3, 但是就有這個問題, push以后, 應用程序找不到該文件.

不過這個是調試的時候才有的問題. 真正發布的時候, 我們不需要知道真實路徑, app會拿到系統給的路徑, 然后下載obb放到該文件夾下. 調試的時候因為是手動上傳的包, 可能路徑不對.

 


目前在各種設備上測試確定Java的mount沒有出現過問題.

現在為了方便測試, 會優先讀取/sdcard/main.1.XXX.obb 這樣測試的時候obb直接放到sd卡里面就好了,一般測試的時候都是這么做吧.

但是還是不確定新的安卓系統對於非app私有的數據是否有讀取權限限制, 應該沒有, 不過最好先看文檔確認下.

因為Android4.4 KitKat已經沒有外部寫權限了(我覺得這樣更安全,本來是個好事,但是應該一開始就這么搞,現在突然這么搞會出現軟件兼容性問題), 不知道外部讀會不會有問題, 現在測過一兩個4.4的設備還沒有發現問題.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM