*res/raw和assets的相同点:
1.两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制。
*res/raw和assets的不同点:1.res/raw中的文件会被映射到R.java文件中,访问的时候直接使用资源ID即R.id.filename;assets文件夹下的文件不会被映射到R.java中,访问的时候需要AssetManager类。2.res/raw不可以有目录结构,而assets则可以有目录结构,也就是assets目录下可以再建立文件夹*读取文件资源:
1.读取res/raw下的文件资源,通过以下方式获取输入流来进行写操作
- InputStream is = getResources().openRawResource(R.id.filename);
2.读取assets下的文件资源,通过以下方式获取输入流来进行写操作
- AssetManager am = null;
- am = getAssets();
- InputStream is = am.open("filename");
补充一下:在未知目录下有哪些文件,该去和获取这些文件的名称并把文件拷贝到目标目录中呢?(用于内置文件但不知道文件名称,需要筛选出想要的文件然后拷贝到目标目录中,推荐内置在assets文件夹中)
1.res/raw目录:通过反射的方式得到R.java里面raw内部类里面所有的资源ID的名称,然后通过名称获取资源ID的值来读取我们想要的文件。2.assets目录:getAssets().list("");来获取assets目录下所有文件夹和文件的名称,再通过这些名称再读取我们想要的文件。
资源id在Android中是如此重要,因此我们只要获得了资源id,即可获得资源。因为某些情况下,我们不能使用某个常量作为资源id(因为我们想用一个变量代替它),所以只能采用两种方式动态获取资源id:
1、反射
java的反射是如此强大,以至于我们在走投无路时总是想起它。我们来看一段代码:
try{
Field field=R.drawable.class.getField(type); // Field[] getFields() 返回具有public属性的成员变量的数组
// Field[] getDelcaredField() 返回所有成员变量组成的数组(不分public和非public属性)
int i= field.getInt(new R.drawable());
Log.d(tag,i+"");
return i;
}catch(Exception e){
Log.e(tag,e.toString());
return R.drawable.unknow;
}
type是一个变量,他的可能值会是“close”、“edit”、“icon”等。我们通过java的反射类Field 去访问 R.drawable 类下面的某个字段。实际上,我们知道在R.drawable 下的字段就是 res.drawable-xxxx 目录下的图片文件的资源id。因此运行上面的这段代码,其实就是通过一个字符串去获取对应图片文件的资源id。比如,当 type 的值为“icon”时,上面的代码会获得res.drawable-xxxx目录下的 icon.png 图片文件的资源id并返回给我们。我们通过资源 id 来把图片显示在ImageView中就是顺理成章的事了。
2、使用Resources 类的 getIdentifier方法
使用反射毕竟还是麻烦。如果同样的事情用 android.content.res.Resources 类来干,就是两句话而已:
Resources res=getResources();
return res.getIdentifier(type,"drawable",getPackageName());
getResources方法是来自于contenxt(也就是Activity类),它直接可以返回一个Resouces对象。而Resouces的getIdentifier方法可以返回R.java中的任何资源id,当然,你必须指定3个参数:字段名,类名,包名。包名指定了的 全限定名的包名部分,如果R 的全限定名为 android.R 或者 com.company.R,则包名在这里就是“android”或“com.company”。getPackageName其实是this.getPackageName(),它直接返回本类的包名。
类名则是资源所属的类。比如我们知道的,在R.java 类中的几个固定的类:drawable、id、string、layout等,在它们下边又定义了许多资源id。
字段名则是资源id的名字。比如这个资源id定义: public static final int del=0x7f020002;
del就是一个资源id的名字,0x7f020002则是它的16进制值。
通过3个参数,getIdentifier 方法就可以通过比较动态的方式获得资源id。
1.上手机时INSTALL_FAILED_INSUFFICIENT_STORAGE 错误提示
主要原因还是asset文件夹里面的东西太大导致的,开始自己放了几个字体在里面,其中有一个5M大的 安装的时候就悲剧了,删除后问题解决。
如果是模拟器爆这个错误,可以添加参数:-partition-size 1024
在网络上查了下关于这个问题的深入原因:
“在使用Android自带的Res\raw或使用Asset时都需要经过Asset Manager,这将会产生一个比较严重的问题,在Android模拟器测试时不存在问题,但放到真机G1时会面临多个问题,经过查看 UNCOMPRESS_DATA_MAX的取值为1048576字节,除以1024不难发现是1MB。也就是说Android手机在处理资源文件时不能大 于1mb的体积”
目前解决的方法只有将文件放入到sdcard,但这样除了microsd的读取IO效率和耗电量解决不是很好,同时sd卡移除时可能存在问题,解决的方法 如果数据量大的化通过sqlite是一种解决方法,同时openFileOutput方式读取也是不错的选择,看来android操作系统中最安全控制的 严格,但犯了一个不小的错误。
参考: