文件架构

Android目录下有很多固定名字的文件夹, 类似Unity中的Resources, Editor这些文件夹, 用来标记相关特殊的功能。具体如下列表:

  • assets资产目录,这里面的文件会被打包到应用成的apk(安装包)里面,不会被本地化(不会被转成二进制文件)
  • bin 编译后的文件目录
  • gen 自动生成的文件目录 用于统一管理资源,通过id使用资源
  • project.properties 代表编译的版本,对应android.jar的版本eg: target= android-19
  • libs支持jar包,会被添加到android depend
  • res资源目录(会把某些文件存为二进制文件)
    • drawable存放应用的图片资源,android系统会根据你的手机分辨率加载不同的图片
    • layout布局文件(设置界面显示样式)
    • menu设置菜单文件
    • values包含一些字符串等等
  • AndroidManifest.xml本应用的配置信息
    • package:唯一标示一个应用的包名
    • versionCode:版本代码
    • versionName:版本名
    • minSdkVersion:支持的最小版本
    • targetSdkVersion:目标版本(一般高版本手机支持低版本应用)
    • application:icon应用图标,label应用名,activity声明活动

StreamingAssets

unity中的StreamingAssets目录通常用来放一些Bundle,或者诸如Fmod的Bank文件, 但此文件夹在Windows平台和IOS平台下可以通过IO接口直接访问, 这就意味着我们可以使用多线程或者线程池来高效率的读取资源。 但遗憾的是这接口不支持Android。 那具体Android如何存储StreamingAssets下的文件呢?

一般的话, 我们可以通过Assetbundle或者WWW的接口来获取StreamingAssets下的资源, 但需要转换下路径, 不能使用物理路径, 而是相应的需要是映射的虚拟路径。官方推荐使用Application.streamingAssetsPath来获得该文件夹的实际位置,其可以规避平台差异。

  • 对于ios平台,其等价于:Application.dataPath + “/Raw”;
  • 对于android平台,其等价于:“jar:file://” + Application.dataPath + “!/assets/”;
private void SetupPath()
{switch (Application.platform){case RuntimePlatform.Android:BundleRootDefault = string.Format("{0}!assets/{1}/", Application.dataPath, BundleFolder);break;case RuntimePlatform.IPhonePlayer:BundleRootDefault = string.Format("{0}/Raw/{1}/", Application.dataPath, BundleFolder);break;default:BundleRootDefault = string.Format("{0}/StreamingAssets/{1}/", Application.dataPath, BundleFolder);break;}
}

但底层Unity生成的Android包安装之后, 究竟是如何存储的, 这里通过实验的方法一探究竟:

第一步, 我们先在StreamingAssets目录下, 放几个文件, 如下图所示:

第二步,生成Gradle工程(工程放在跟Asset目录同级的Temp文件夹下), 这里我们发现StreamingAssets目录下的文件其实对应assets文件夹, 并且我们发现gradle生成的apk的过程中,build文件夹下的目录:

第三步, 安装生成的apk, 这里需要一台root的手机或者模拟器, 这里选择网易的mumu模拟器, 直接在设置里勾一下重启就Root掉了, 真是方便。

StreamingAssets安装之后,默认解压到/data/app/包名 文件夹下, 我们通过abd shell命令进入手机(需要电脑配置好Android开发环境。

可以看到里面有个base.apk, 通过命令查看其占用磁盘大小, 基本可以定位这个就是我们放置StreamingAssets文件的

du -h base.apk

我们知道.apk本质就是zip压缩, 这里我们改其后缀, 然后使用unzip命令解压, 就可以看到一开始Unity放入StreamingAssets里的文件啦。

访问assets文件夹下的资源, 可以通过java或者JNI的接口:

public String readFromAssets(String name){String resultStr = "";
try {InputStream inStream = this.getResources().getAssets().open(name);resultStr = convertStream2String(inStream);//convertStreamToString(inStream);
} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();
}
return resultStr;

JNI的c++接口:

#include "mylog.h"
#include <jni.h>
#include <sys/types.h>
#include <stdlib.h>
#include <android/asset_manager_jni.h>
#include <android/asset_manager.h>extern "C"{
JNIEXPORT  jstring JNICALL Java_org_yanzi_lib_MyLib_readFromAssets(JNIEnv* env,jclass clazz, jobject assetManager,jstring name);
JNIEXPORT  jstring JNICALL Java_org_yanzi_lib_MyLib_readFromAssets(JNIEnv* env, jclass clazz, jobject assetManager,jstring name){LOGI("readFromAssets enter..."); //jclass this,jstring resultStr;AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);if(mgr==NULL){LOGI(" %s","AAssetManager==NULL");return 0;}/*获取文件名并打开*/jboolean iscopy;const char *mfile = env->GetStringUTFChars(name, &iscopy); //(*env)->GetStringUTFChars(name, &iscopy); env,AAsset* asset = AAssetManager_open(mgr, mfile,AASSET_MODE_UNKNOWN);env->ReleaseStringUTFChars(name, mfile); //env,if(asset==NULL){LOGI(" %s","asset==NULL");return 0;}/*获取文件大小*/off_t bufferSize = AAsset_getLength(asset);LOGI("file size : %d\n",bufferSize);char *buffer=(char *)malloc(bufferSize+1);buffer[bufferSize]=0;int numBytesRead = AAsset_read(asset, buffer, bufferSize);LOGI("readFromAssets: %s",buffer);resultStr = env->NewStringUTF(buffer);free(buffer);/*关闭文件*/AAsset_close(asset);LOGI("readFromAssets exit...");return resultStr;}
}

需要注意的是, 使用JNI的接口,Application.mk文件需要做如下设置:

APP_STL:=gnustl_static
APP_CPPFLAGS:=-frtti -fexceptions
APP_ABI:= armeabi-v7a

PlayerPrefs存储路径

我们知道PlayerPrefs在windows下, 储存在注册表中, Android平台Unity又是怎么处理的?

通过上图,可以发现PlayerPrefs的值是以xml的形式存储在 /data/data/youPackageName/shared_prefs的目录下。由于不是直接储存在压缩包内, 这个xml应该可以通过io接口访问(需要获取相应的权限, 并在Androidmenifest.xml中声明), 但是由于非root手机一般都进入不到此文件夹, 我们平时也无法直接在资源管理器里访问或者编辑此xml。

/data/data/youPackageName/即内部存储路径下。所有内部存储中保存的文件在用户卸载应用的时候会被删除。Java访问的接口:

  • files

    • Context.getFilesDir(),该方法返回/data/data/youPackageName/files的File对象。
    • Context.openFileInput()与Context.openFileOutput(),只能读取和写入files下的文件,返回的是FileInputStream和FileOutputStream对象。
    • Context.fileList(),返回files下所有的文件名,返回的是String[]对象。
    • Context.deleteFile(String),删除files下指定名称的文件。
  • cache

    • Context.getCacheDir(),该方法返回/data/data/youPackageName/cache的File对象。
  • customDir

    • getDir(String name, int mode),返回/data/data/youPackageName/下的指定名称的文件夹File对象,如果该文件夹不存在则用指定名称创建一个新的文件夹。

persistentDataPath, temporaryCachePath

这两个目录路径在storage/Android/data/youPackageName目录下, 一般情况下可以通过手机自带的文件浏览器可以直接 编辑/删除 这些文件, 权限给的比较高,卸载程序此两个文件夹也会一起删除。temporaryCachePath是一个临时目录, 在操作系统磁盘不足的情况下, 会自动被系统清除, 适合存一些临时的文件, 而persistentDataPath适合存一些持久化的文件, 比如说游戏的bundle。

persistentDataPath: storage/Android/data/yourpackageName/files
temporaryCachePath: storage/Android/data/yourpackageName/cache

使用原生的方式获取路径:

MLog.d(TAG, "output: " + gameContext.getExternalFilesDir("").getAbsolutePath();
MLog.d(TAG, "package: " + gameContext.getPackageResourcePath());
MLog.d(TAG, "cache: " + gameContext.getCacheDir().getPath());
MLog.d(TAG, "exCache: " + gameContext.getExternalCacheDir().getPath());
MLog.d(TAG, "file: " + gameContext.getFilesDir().getPath());
MLog.d(TAG, "code: " + gameContext.getPackageCodePath());

对应的输出是:

内部存储,外部存储的概念

内部存储

概念:注意内部存储不是内存。内部存储位于系统中很特殊的一个位置,如果你想将文件存储于内部存储中,那么文件默认只能被你的应用访问到,且一个应用所创建的所有文件都在和应用包名相同的目录下。也就是说应用创建于内部存储的文件,与这个应用是关联起来的。当一个应用卸载之后,内部存储中的这些文件也被删除。从技术上来讲如果你在创建内部存储文件的时候将文件属性设置成可读,其他app能够访问自己应用的数据,前提是他知道你这个应用的包名,如果一个文件的属性是私有(private),那么即使知道包名其他应用也无法访问。 内部存储空间十分有限,因而显得可贵,另外,它也是系统本身和系统应用程序主要的数据存储所在地,一旦内部存储空间耗尽,手机也就无法使用了。所以对于内部存储空间,我们要尽量避免使用。Shared Preferences和SQLite数据库都是存储在内部存储空间上的。内部存储一般用Context来获取和操作。
访问内部存储的API方法:
1、Environment.getDataDirectory()
2、getFilesDir().getAbsolutePath()
3、getCacheDir().getAbsolutePath()
4、getDir(“myFile”, MODE_PRIVATE).getAbsolutePath()

外部存储

概念:最容易混淆的是外部存储,因为老的Android系统的跟新的Android系统是有差别的,很多人去网上查找资料,看了一下以前的资料,又看了一下现在的资料,但是发现它们说法不一样然后就困惑了。首先说一个大家普遍的概念“如果在pc机上是区分外部存储和内部存储的话,那么电脑自带的硬盘算是内部存储,U盘或者移动硬盘就是外部存储了。”因此很多人带着这样的理解去看待安卓手机,把内置存储(机身存储)当做内部存储,而把扩展的SD卡当做是外部存储。这么认为确实没错,因为在4.4(API19)以前的手机上确实是这样的,手机自身带的存储卡就是内部存储,而扩展的SD卡就是外部存储。但是从4.4的系统开始,很多的中高端机器都将自己的机身存储扩展到了8G以上,比如有的人的手机是16G的,有的人的手机是32G的,但是这个16G,32G是内部存储吗,不是的!!!,它们依然是外部存储,也就是说4.4系统及以上的手机将机身存储存储(手机自身带的存储叫做机身存储)在概念上分成了”内部存储internal” 和”外部存储external” 两部分。既然16G,32G是外部存储,那有人又有疑惑了,那4.4系统及以上的手机要是插了SD卡呢,SD卡又是什么呢,如果SD卡也是外部存储的话,那怎么区分机身存储的外部存储跟SD卡的外部存储呢?对,SD卡也是外部存储,那怎么区分呢,在4.4以后的系统中,API提供了这样一个方法来遍历手机的外部存储路径:

File[] files;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {files = getExternalFilesDirs(Environment.MEDIA_MOUNTED);for(File file:files){Log.e("main",file);}
}

如果你的手机插了SD卡的话,那么它打印的路径就有两条了,例如我的华为荣耀7插了SD卡,它的结果如下:
/storage/emulated/0/Android/data/packname/files/mounted
/storage/B3E4-1711/Android/data/packname/files/mounted
其中/storage/emulated/0目录就是机身存储的外部存储路径, 而/storage/B3E4-1711/就是SD卡的路径

参考

  • android工程目录结构
  • Android获取文件夹路径 /data/data/
  • Android文件存储—内部存储,外部存储

Android下的特殊文件夹相关推荐

  1. android 7 创建文件夹,Android 在 res/layout 文件夹 下创建一个 子文件夹实例

    Android 资源文件夹 Layout 文件夹 Layout 文件是存放Android的布局文件的资源文件夹,但是如果你想要在里面创建子文件夹,你会发现xml文件报错. 如何在Layout文件夹下方 ...

  2. android 根目录uri,如何在根目录下创建一个文件夹Android

    我需要在根目录下创建CAT_IMG文件夹,并在列表视图中检索它.但CAT_IMG文件夹不在根目录中创建.我在清单文件中添加了权限.请帮我在根目录下创建一个文件夹.如何在根目录下创建一个文件夹Andro ...

  3. android studio在raw文件夹下使用MediaPlayer播放Mp3音乐

    android studio在raw文件夹下使用MediaPlayer播放Mp3音乐 1.在res文件夹下创建raw文件夹 2.在新建好文件夹之后,将MP3文件拖入进刚刚创建好的raw文件夹内 3.使 ...

  4. Android中layout目录的作用,Android 开发中layout下的子文件夹

    Android 开发中layout下的子文件夹 发布时间:2020-10-25 11:42:36 来源:脚本之家 阅读:71 作者:厚土火焰山 如果一个项目内有很多个界面,那么在layout下会有太多 ...

  5. Android Studio mipmap各文件夹下图片尺寸一览表

    Android studio中mipmap文件夹有五个,分别对应不同的图片分辨率,具体尺寸表见下图.

  6. (转)Unity Assets目录下的特殊文件夹名称(作用和是否会被打包到build中)

    原文:http://wiki.unity3d.com/index.php/Special_Folder_Names_in_your_Assets_Folder 1.隐藏文件夹 以.开头的文件夹会被Un ...

  7. asset文件夹路径 unity_Unity Assets目录下的特殊文件夹名称

    1.隐藏文件夹 以.开头的文件夹会被Unity忽略.在这种文件夹中的资源不会被导入,脚本不会被编译.也不会出现在Project视图中. 2.Standard Assets 在这个文件夹中的脚本最先被编 ...

  8. Win10-更改c盘下的用户文件夹名[转]

    转载 Win10-更改c盘下的用户文件夹名[转] 2019年 版权声明:本文为转载文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 转载链接:https://blog. ...

  9. android studio各个资源文件夹以及作用备注

    src:存放所有的*.java源程序. gen:为ADT插件自动生成的代码文件保存路径,里面的R.java将保存所有的资源ID. assets:可以存放项目一些较大的资源文件,例如:图片.音乐.字体等 ...

最新文章

  1. windows下python2.7.14版本的安装
  2. Python_面向对象_类1
  3. 【转】Service Intent must be explicit的解决方法
  4. haproxy mysql配置文件详解_HAProxy基础配置-haproxy的配置文件说明
  5. tomcat装死原因汇总
  6. 12分钟训练COCO模型!速度精度双提高
  7. MySQL Partition扫盲
  8. 【Xamarin开发 Android 系列 6】 Android 结构基础(上)
  9. java视频教程下载
  10. 为什么中国电气自动化工程师这么难招
  11. 手机屏幕怎么计算机,怎样把手机屏幕投到电脑
  12. 现在90后程序员有必要考证吗?
  13. 云计算机遇与挑战,中国云计算产业发展面临机遇与挑战
  14. 电脑的开机密码忘记了怎么打开
  15. spring boot注解@PostConstruct
  16. Nginx+Tomcat实现负载均衡与动静分离
  17. 替代Windows文件服务器,windows文件服务器替代
  18. 在计算机领域中,通常用英文单词 bit 来表示,2013安徽省全国计算机等级考试二级笔试试卷VB试题及答案...
  19. 【项目设计】高并发内存池
  20. 周赛一 1004 uu的金坷垃

热门文章

  1. 网友评价 iPhone 8:大爱玻璃后壳、True Tone 屏幕
  2. 深信服 2022届校园招聘 C++笔试编程题目
  3. 一个叫鲁迅的人,终于从教科书里滚了...
  4. VMware配置虚拟机映射,实现局域网络互相访问
  5. 科普|AGV自动运输车的不同导航方式以及优缺点
  6. 攀藤G5S数据位编码
  7. 小菊的语义分割3——数据预处理及像素级分类实现原理
  8. 在线观看北京奥运会直播 在网上看奥运会直播
  9. 踢球骨折在家day7
  10. PHP怎样大幅度降低图片大小但最大程度保持图片清晰?