zoukankan      html  css  js  c++  java
  • 工作记录[续] 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的设备还没有发现问题.

  • 相关阅读:
    java 基础知识
    winform判断一个事件是否已经绑定了事件处理函数
    优质文章
    优质博客
    缩略图的创建
    记录一次错误处理 (xml序列化和反序列化相关)
    文件同步软件
    博客园优质博主集锦
    不错的博文集锦
    cesiumjs
  • 原文地址:https://www.cnblogs.com/crazii/p/3762510.html
Copyright © 2011-2022 走看看