最近项目(Cocos2dx)上线了一个新的渠道,Android包要求targetSDK提升到API33(Android13)。打包没有问题,但是发给渠道后对面用Android12的手机登录发现资源无法加载,于是通过日志查看到:
assets/xxx :Can't create dir:/storage/emulated/0/Android/data/com.xx.xx/assets/xx
确认无法加载的问题是,下载文件的时候因为创建文件夹失败(Can't create dir),导致资源压根没在下下来。知道问题所在,定位到Cocos2dx工程:CCFileUtils-android.cpp
bool FileUtilsAndroid::createDirectory(const std::string& dirPath)
{
bool bRet = true;
if (access(dirPath.data(), F_OK) == 0)
return true;
size_t len = dirPath.length();
for (size_t i = 0 ; i < len ; i ++)
{
if (dirPath[i] == '/')
{
std::string p = dirPath.substr(0, i);
if (access(dirPath.data(), F_OK) != 0)
{
bRet = bRet & (mkdir(p.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == 0);
}
}
}
return bRet;
}
在 适配Android11之前,这段代码都是执行无误的,但是在Android11及之后,存储发生了变化,
mkdir(path,mode) mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP权限无法正常创建文件夹。于是我们将权限提高点,改成:
bRet = bRet & (mkdir(p.data(), S_IRWXU | S_IRWXG | S_IRWXO) == 0);
该函数完整的为:
bool FileUtilsAndroid::createDirectory(const std::string& dirPath)
{
bool bRet = true;
if (access(dirPath.data(), F_OK) == 0)
return true;
size_t len = dirPath.length();
for (size_t i = 0 ; i < len ; i ++)
{
if (dirPath[i] == '/')
{
std::string p = dirPath.substr(0, i);
if (access(dirPath.data(), F_OK) != 0)
{
bRet = bRet & (mkdir(p.data(), S_IRWXU | S_IRWXG | S_IRWXO) == 0);
}
}
}
return bRet;
}
尝试,OK,正常创建文件夹。
以下是部分mkdird的权限解释:
mkdir的原型为:int mkdir(const char *path, mode_t mode);
意思为,用mode权限创建以path目录
mode方式:
S_IRWXU 00700权限,代表该文件所有者拥有读,写和执行操作的权限
S_IRUSR(S_IREAD) 00400权限,代表该文件所有者拥有可读的权限
S_IWUSR(S_IWRITE) 00200权限,代表该文件所有者拥有可写的权限
S_IXUSR(S_IEXEC) 00100权限,代表该文件所有者拥有执行的权限
S_IRWXG 00070权限,代表该文件用户组拥有读,写和执行操作的权限
S_IRGRP 00040权限,代表该文件用户组拥有可读的权限
S_IWGRP 00020权限,代表该文件用户组拥有可写的权限
S_IXGRP 00010权限,代表该文件用户组拥有执行的权限
S_IRWXO 00007权限,代表其他用户拥有读,写和执行操作的权限
S_IROTH 00004权限,代表其他用户拥有可读的权限
S_IWOTH 00002权限,代表其他用户拥有可写的权限
S_IXOTH 00001权限,代表其他用户拥有执行的权限
欢迎指正!