重点看在Android上的实现
网络异常,图片无法展示
|
- CCFileUtils-android.cpp
FileUtils* FileUtils::getInstance() { if (s_sharedFileUtils == nullptr) { // Android的类 s_sharedFileUtils = new FileUtilsAndroid(); } return s_sharedFileUtils; }
std::string FileUtils::fullPathForFilename(const std::string &filename) const{ std::string fullpath; // 这个_searchPathArray里面就有assets这个很特殊的目录 for (const auto& searchIt : _searchPathArray) { for (const auto& resolutionIt : _searchResolutionsOrderArray) { // 里面有平台代码,换取fullpath fullpath = this->getPathForFilename(newFilename, resolutionIt, searchIt); if (!fullpath.empty()) { // Using the filename passed in as key. _fullPathCache.emplace(name, fullpath); return fullpath; } } } } // 最终会来到这个函数 std::string FileUtils::getFullPathForDirectoryAndFilename(const std::string& directory, const std::string& filename) const { // get directory+filename, safely adding '/' as necessary std::string ret = directory; if (directory.size() && directory[directory.size()-1] != '/'){ ret += '/'; } ret += filename; // if the file doesn't exist, return an empty string if (!isFileExistInternal(ret)) { ret = ""; } return ret; }
// 安卓平台判断文件是否是内置的资源 bool FileUtilsAndroid::isFileExistInternal(const std::string& strFilePath) const { if (strFilePath.empty()) { return false; } bool bFound = false; // Check whether file exists in apk. if (strFilePath[0] != '/') { const char* s = strFilePath.c_str(); // Found "assets/" at the beginning of the path and we don't want it // 注意这个_defaultResRootPath,它是一个protected变量,在init有赋值 if (strFilePath.find(_defaultResRootPath) == 0) s += _defaultResRootPath.length(); if (obbfile && obbfile->fileExists(s)) { bFound = true; }else if (FileUtilsAndroid::assetmanager){ // 看到了Android平台的jni代码 AAsset* aa = AAssetManager_open(FileUtilsAndroid::assetmanager, s, AASSET_MODE_UNKNOWN); if (aa){ bFound = true; AAsset_close(aa); } else { // CCLOG("[AssetManager] ... in APK %s, found = false!", strFilePath.c_str()); } } } else { FILE *fp = fopen(strFilePath.c_str(), "r"); if (fp) { bFound = true; fclose(fp); } } return bFound; } #define ASSETS_FOLDER_NAME "assets/" bool FileUtilsAndroid::init() { _defaultResRootPath = ASSETS_FOLDER_NAME; // ... } void FileUtils::setSearchPaths(const std::vector<std::string>& searchPaths) { // 每一次添加searchpaths的时候,都会检查rootPath的存在 bool existDefaultRootPath = false; // ... if (!existDefaultRootPath) { _searchPathArray.push_back(_defaultResRootPath); } }
安卓平台的搜索路径:
- assets/src/
- assets/res/
- assets/
至此也就搞明白了,fullpath在Android上是一个假的路径
由于assets文件夹中的文件在APK文件中被打包,因此它们没有绝对路径。
string FileUtilsAndroid::getWritablePath() const { // Fix for Nexus 10 (Android 4.2 multi-user environment) // the path is retrieved through Java Context.getCacheDir() method string dir(""); string tmp = JniHelper::callStaticStringMethod("org/cocos2dx/lib/Cocos2dxHelper", "getCocos2dxWritablePath"); if (tmp.length() > 0) { dir.append(tmp).append("/"); return dir; } else { return ""; } }
public static String getCocos2dxWritablePath() { //赋值的逻辑: Cocos2dxHelper.sFileDirectory = activity.getFilesDir().getAbsolutePath(); return Cocos2dxHelper.sFileDirectory; }
Android的各种dir
目录方法 | 路径 | 特点和用途 | 卸载应用程序时是否会被删除 |
getDir() | /data/data/包名/app_data/自定义目录名 | 应用程序的私有数据目录,通常用于存储应用程序的数据库文件或其他私有数据。可以指定自定义目录 | 是 |
getFilesDir() | /data/data/包名/files | 应用程序的私有文件目录,通常用于存储应用程序的数据文件。 固定目录 | 是 |
getCacheDir() | /data/data/包名/cache | 应用程序的私有缓存目录,通常用于存储临时文件或缓存数据。 | 是 |
getExternalFilesDir() | /storage/emulated/0/Android/data/包名/files | 应用程序在外部存储设备上的私有文件目录,通常用于存储需要与其他应用程序共享的数据文件。 | 否 |
getExternalCacheDir() | /storage/emulated/0/Android/data/包名/cache | 应用程序在外部存储设备上的缓存目录,通常用于存储临时文件或缓存数据。 | 否 |