前两篇在这里:

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

  1. const char* getMountedObbPath(const char* filename) {
  2. String16 filename16(filename);
  3. String16 path16;
  4. if (mMountService->getMountedObbPath(filename16, path16)) {
  5. return String8(path16).string(); //WTF? return a temp object's buffer?
  6. } else {
  7. return NULL;
  8. }
  9. }

由于没有看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 != );
  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. mountOBB()
  33. {
  34. AStorageManager_mountObb( Callback );
  35. pthread_cond_wait(&app->cond, &app->mutex);
  36.  
  37. }
  38.  
  39. //Main thread entry for activity create, called by NactiveActivity.java
  40. NativeActivity_onCreate()
  41. {
  42. ...
  43. mountOBB();
  44. createthread: android_main(); //this is pseudo code
  45. return;
  46. }

调用java的native代码是这样:

  1. //pseudo codes:
  2.  
  3. mountOBB()
  4. {
  5. call Java code to mount
  6. }
  7.  
  8. bool isOBBMounted()
  9. {
  10. query Java code whether mount ready
  11. }
  12.  
  13. NativeActivity_onCreate(...)
  14. {
  15. ...
  16. mountOBB();
  17. create thread: android_main();
  18. }
  19.  
  20. android_main()
  21. {
  22.  
  23. while ((ident= ALooper_pollAll(...)) >= )
  24. {
  25. if( isOBBMounted() )
  26. continue_app();
  27. }
  28. }

最后尝试把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的设备还没有发现问题.

工作记录[续] android OBB的更多相关文章

  1. 【工作记录】android手势事件操作记录

    /* 用户按下触摸屏.快速移动后松开 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float vel ...

  2. 工作记录 - OBB的解决方案

    之前关于OBB的内容: Android上使用native IO 最近工作中的问题笔记 工作记录[续] android OBB 自从用了Java来mount OBB, 再也没有遇到挂载的问题. 但最近在 ...

  3. [工作记录] Android OpenGL ES: non-square texture - continue

    previous: [工作记录] Android OpenGL ES 2.0: square texture not supported on some device recently I found ...

  4. [转]倍数提高工作效率的 Android Studio 奇技

    转自:http://android.jobbole.com/81687/ 倍数提高工作效率的 Android Studio 奇技 2015/10/08 · 技术分享 · 4 评论· Android S ...

  5. MySQL跨表更新字段 工作记录

    工作中遇到两表查询,从user表中获取用户唯一id字段 写入到另外一张qiuzu表中的uid字段中; 二者可以关联起来的只有用户的手机号码tel字段; 了解需求后数据量稍多,不可能一个一个的手动修改 ...

  6. 最近的linux工作记录

    最近的linux工作记录 最近公司走了一些同事,部分服务器交到了我的手里,总结一些常用的操作 注:大写的字符串一般是用来占位,需要替换 创建账户和使用密钥对登陆 1,账户系列 useradd 选项 用 ...

  7. 『记录』Android参考资料

    欢迎留言推荐好的教程.资料.博客及作者等. 『记录』Android参考资料 1.前期环境 Android Studio使用Git Android Studio快捷键总结 Android Studio及 ...

  8. 工作记录--WPF自定义控件,实现一个可设置编辑模式的TextBox

    原文:工作记录--WPF自定义控件,实现一个可设置编辑模式的TextBox 1. 背景 因为最近在使用wpf开发桌面端应用,在查看页面需要把TextBox和Combox等控件设置为只读的.原本是个很简 ...

  9. 图书馆管理系统程序+全套开发文档(系统计划书,系统使用说明,测试报告,UML分析与设计,工作记录)

    图书馆管理系统程序+全套开发文档(系统计划书,系统使用说明,测试报告,UML分析与设计,工作记录): https://download.csdn.net/download/qq_39932172/11 ...

随机推荐

  1. JavaScript -基础- 函数与对象(二)String

    一.判断数据类型typeof与判断对象类型instanceof 1.typeof typeof只能判断基础数据类型,无法判断引用数据类型 <script> var s="hell ...

  2. 《Python》re模块补充、异常处理

    一.re模块 1.match方法 import re # match 验证用户输入的内容 ret = re.match('\d+', 'hhoi2342ho12ioh11') print(ret) # ...

  3. 6.3 C++修改字符串

    参考:http://www.weixueyuan.net/view/6392.html 总结: string字符串同样可以像字符串数组那样按照下标逐一访问字符串中的每一个字符,string字符串的起始 ...

  4. 第三节 java 数组(循环遍历、获取数组的最值(最大值和最小值)、选择排序、冒泡排序、练习控制台输出大写的A)

    获取数组的最值(最大值和最小值) 思路: 1.获取最值需要进行比较,每一次比较都会有一个较大的值,因为该 值不确定,需要一个变量进行临储. 2.让数组中的每一个元素都和这个变量中的值进行比较,如果大于 ...

  5. redis_key键

    exists k1,判断k1是否存在,‘1’就是存在,‘0’ 就是不存在 move k3 2   --->这里就是说把k3移动到2号库. ‘1’为成功,‘0’为失败 ttl k2  --查看k2 ...

  6. Unity中资源打包成Assetsbundle的资料整理

    最近在研究Unity中关于资源打包的东西,网上看了一堆资料,这里做个整合,说整合,其实也就是Ctrl-C + Ctrl-V,不是原创 首先为了尊重原创,先贴出原创者的文章地址: http://blog ...

  7. Nginx部署vue多项目

    server { listen 80; server_name test.hehe.com; location /riskcontrol { root /data; try_files $uri $u ...

  8. 2019-03-06-day005-字典操作

    情商 别人与你相处感觉很轻松. ?为人处世,有笑点. 照顾对方的情绪. 与别人相处可以很好地解决问题. 你身边总有那么一两个人,别人都喜欢与他交往,和他在一起,很舒服. 情商后天可以提升的. 1,你本 ...

  9. Centos7防火墙开放8080端口

    查看已经开发的端口: firewall-cmd --list-ports 开启端口: firewall-cmd --zone=public --add-port=8080/tcp --permanen ...

  10. 【Python】多进程-共享变量(Value、string、list、Array、dict)

    #练习:未使用共享变量 from multiprocessing import Process def f(n, a): n = 3.1415927 for i in range(len(a)): a ...