最近发现,有很小一部分海外的玩家在谷歌商店下载游戏之后,进游戏黑屏。从bugly上面查看报错日志,发现是读取obb文件失败了。谷歌商店规定超过100m的apk,需要分离obb上传。所以这种情况只会出现在谷歌商店的游戏包里面。
我的项目里面读取obb是分成2种情况的,第一种,是unity本身的api读取,比如Resources.Load()方法。另一种,是通过java原始方法,找到obb文件的路径,然后通过getInputStream方法,把obb文件当作是zip包一样读取。
经过多方面的排除,发现是某些特定的机型,在READ_EXTERNAL_STORAGE(读取外部存储)的权限禁止的情况下,会出现一个外部存储没挂载的情况,从Environment.getExternalStorageState()方法返回了"unmounted"。
在这种情况下,getObbDir()得到的路径会访问不了,所以导致了obb文件加载不到。很神奇的是,如果不用obb,单纯用unity本身的Application.persistentDataPath,获取的路径是可操作的,这个路径按正常的理解,是在data/storage/emulated/0/Android/data/com.xxx.xxx/files下,而obb的路径一般是在data/storage/emulated/0/Android/obb/com.xxx.xxx下,难道是Android/data/不需要权限,而Android/obb/需要权限?
带着这个疑问,我尝试着把Application.persistentDataPath在unity里面用OnGUI显示出来,然后分别打开和禁用READ_EXTERNAL_STORAGE权限。终于发现了问题的所在。
当有读权限的时候,应用默认访问的路径是data/storage/emulated/0/Android/文件夹
当读写权限被禁止的时候,storage目录被禁止访问,就是所谓的没有挂载,所以会分配了另外一个目录作为程序的默认访问目录:data/user/0/ 其中0是用户序号,据说安卓6.0之后支持多用户,所以有这个文件夹。
Unity的api对obb读取方式应该是独立于正常资源的,persistentDataPath可以正常的获取到路径,但obb的路径估计还是通过getObbDir之类的方法得到的,所以导致了路径不能访问,加载obb失败了。
我们一直讨论的都是某部分特殊的手机,正常的手机不会这样,正常手机在禁用了READ_EXTERNAL_STORAGE权限之后,还是能正常访问data/storage/emulated/0/Android/文件夹的,Environment.getExternalStorageState()获取也是"mounted"的。然后,这种问题当然只会出现在安卓6.0及以上的手机,因为6.0以下的手机不存在动态申请权限的操作。
于是尝试获取权限去解决这个问题。正常的思路很简单,只需要在游戏启动的时候,判断一下是否拥有这个权限,如果没有权限就弹出动态权限申请的弹窗,让用户同意授权就行了。
然而实际操作中,发现这部分的手机,在设置里面的权限授权状态如果是禁止的,那么他就根本不会弹出授权窗口,直接就返回了拒绝。这个情况,我个人的猜测是,安卓6.0以后的系统,对于权限一般会有允许,询问,禁止三种,然后在禁止的时候,一般会有个小选项,“禁止后不再提示”。但在出问题的手机系统里面,实际上是没有询问这种状态的,如果在设置里面禁止了,等同的效果是禁止后不再提示。
所以,我们还是不能通过权限弹窗去解决这个问题。我们可以帮助玩家跳转到手机设置面板去,让玩家手动去修改设置。跳转的方法是:
Intent myAppSettings = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse(“package:” + getPackageName()));
startActivityForResult(myAppSettings, REQUEST_APP_SETTINGS);
但这种操作比较的不友好,玩家也不一定知道怎样操作。
最终我们想达到的目的是让伤害降低到最小,让大部分正常的玩家还是可以通过权限弹窗去授权权限,让小部分不会弹窗的用户,跳转去手机设置面板。于是不能通过权限去直接判断是否需要弹窗。幸好之前我们在判断挂载方式的时候,发现了这种手机的特点是如果禁止读取外部存储权限时,挂载方式是"unmounted"的,所以我们可以通过挂载方式,先判断一下。如果发现了"unmounted"的,就先提示玩家去手动设置授权。
解决部分手机读取obb失败的问题
最新推荐文章于 2024-09-13 21:55:44 发布