背景知识介绍 与其他平台的应用程序一样,Android中的应用程序也会使用各种资源,比如图片,字串等,会把它们放入源码的相应文件夹下面,如/res/drawable, /res/xml, /res/values/, /res/raw, /res/layout和/assets。Android也支持并鼓励开发者把UI相关的布局和元素,用XML资源来实现。总结起来,Android中支持的资源有: •颜色值 /res/values 以resources为Root的XML文件,定义形式为<color name>value</color> •字串 /res/values 以resources为Root的XML文件<string name>value</string> •图片 /res/drawable 直接放入,支持9 Patch可自由拉伸 •图片的颜色 /res/values 以resources为Root的XML文件,定义形式为<drawable name>value</drawable> •单位资源 /res/values 以resources为Root的XML文件<dimen name>value</dimen> •菜单 /res/menu 以menuo为root的XML文件 •布局 /res/layout 这个就是GUI的布局和元素 •风格和主题 /res/values 以resources为Root的XML文件<style name>value</style> •动画 /res/anim 有二种:一个是帧动画(frame animation),也就是连续变换图片以animation-list为Root的XML文件;另外一种就是补间动画(tweened animation),它对应于API中的Animation和AnimationSet,有translate、scale、rotate、alpha四种,以set为root来定义,这个set就相当于AnimationSet 再说下目录: •/res/anim 用于存放动画 •/res/drawable 存放图片,或等同于图片的资源如shape,或selector •/res/menu 存放Menu •/res/values 存放修饰性资源:字串,颜色,单位,风格和主题 •/res/layout 存放UI布局和元素 •/res/raw 存放运行时想使用的原始文件 •/assets 存放运行时想使用的原始文件 除了原始文件目录/res/raw和/assets以外,其他的资源在编译的时候都会被第三方软件aapt进行处理,一个是把图片和XML文件进行处理,例如把XML编译成为二进制形式;另外处理的目的就是生成R.java文件,这个文件是访问资源时必须要用到的。 /res目录下面的所有文件都会映射到R.java文件中,以整数Id的形式被标识,相同类型的资源被一个内部类来封装,一个R.java的文件类似于这样: 复制代码 代码如下: /* AUTO-GENERATED FILE. DO NOT MODIFY. * * This class was automatically generated by the * aapt tool from the resource data it found. It * should not be modified by hand. */ package com.android.explorer; public final class R { public static final class attr { } public static final class drawable { public static final int icon=0x7f020000; } public static final class id { public static final int action=0x7f060004; public static final int description_panel=0x7f060001; public static final int fileinfo=0x7f060003; public static final int filename=0x7f060002; public static final int linearlayout_test_1=0x7f060005; public static final int linearlayout_test_2=0x7f060006; public static final int linearlayout_test_3=0x7f060007; public static final int thumbnail=0x7f060000; } public static final class layout { public static final int fileant_list_item=0x7f030000; public static final int linearlayout_test=0x7f030001; } public static final class raw { public static final int androidmanifest=0x7f040000; } public static final class string { public static final int app_name=0x7f050001; public static final int hello=0x7f050000; } }
2. 文件夹处理 --- 如何遍历/assets 可以看到如果想要访问/assets下面的文件,必须要知道文件名和相对于/assets的路径。所以,如果你不预先知道其下面有什么的时候又该如何处理呢?那就需要列出它下面所有的文件,然后再选取我们需要的,所以新的问题来了,如何列出/assets下面所有的文件呢? AssetManager提供了一个列出/assets下某个路径下面的方法: 复制代码 代码如下: public finalString[]list(String path) Since: API Level 1 Return a String array of all the assets at the given path. Parameters path A relative path within the assets, i.e., "docs/home.html". Returns •String[] Array of strings, one for each asset. These file names are relative to "path". You can open the file by concatenating "path" and a name in the returned string (via File) and passing that to open().
其实这个文档写的有问题,list()是列出一个文件夹下面的文件,所以应该传入一个文件夹路径而非文档中的"docs/home.html"。 还有一个最大的问题就是如何列出根目录/assets下面的内容,因为只有知道了根目录下面的东西,才能去相对的子目录去找东西,所以这是个必须最先解决的问题。 其实文档没有说的太明白这个方法到底如何使用,也就是说这个String参数到底如何传。猜想着根目录为/assets,所以尝试了以下: 复制代码 代码如下: mAssetManager.list("."); // returns array size is 0 mAssetManager.list("/"); // returns [AndroidManifest.xml, META-INF, assets, classes.dex, res, resources.arsc] // don"t worry, u can see these files though, no way to access them mAssetManager.list("/assets"); // returns array size is 0 //Google了一下,找到了正解: mAssetManager.list(""); // returns stuff in /assets
public int getCount() { return mEntries.length; } public Object getItem(int position) { return mEntries[position]; } public long getItemId(int position) { return (long) position; } public View getView(final int position, View item, ViewGroup parent) { LayoutInflater factory = LayoutInflater.from(mContext); if (item == null) { item = factory.inflate(R.layout.fileant_list_item, null); TextView filename = (TextView) item.findViewById(R.id.filename); TextView fileinfo = (TextView) item.findViewById(R.id.fileinfo); ImageButton action = (ImageButton) item.findViewById(R.id.action); final String entry = mEntries[position]; filename.setText(entry); boolean isDir = isDirectory(entry); if (isDir) { fileinfo.setText("Click to view folder"); action.setVisibility(View.GONE); item.setClickable(true); item.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Intent intent = new Intent(FILEANT_VIEW); intent.putExtra(EXTRA_CURRENT_DIRECTORY, entry); intent.putExtra(EXTRA_PARENT, mParentDirectory); startActivity(intent); } }); } else { final String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(getExtension(entry)); fileinfo.setText(type); item.setClickable(false); action.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { String filepath = entry; if (!TextUtils.isEmpty(mParentDirectory)) { filepath = mParentDirectory + File.separator + filepath; } BufferedInputStream in = new BufferedInputStream(mManager.open(filepath)); // Do whatever you like with this input stream } }); } } return item; } }
/** * Test Whether an entry is a file or directory based on the rule: * File: has extension *.*, or starts with ".", which is a hidden files in Unix/Linux, * otherwise, it is a directory * @param filename * @return */ private boolean isDirectory(String filename) { return !(filename.startsWith(".") || (filename.lastIndexOf(".") != -1)); }
private String getExtension(String filename) { int index = filename.lastIndexOf("."); if (index == -1) { return ""; } return filename.substring(index + 1, filename.length()).toLowerCase(); } }