这是一个有图标的文件资源管理器,也许在网上的基于Android的market上有很多比较精美的文件资源管理器,这里我拿这个出来讲并不在于我做的界面如何的精美,而相反我这里的重点并不在界面,我只是想通过这么个列子和大家一起分享Android开发中的一下知识点:(1)目录的遍历(2)自定义Adapter(3)如何取得文件类型,以及调用系统打开对应的文件。这三点也是本程序的关键点所在,如果将这三个知识点掌握了,我想理解这个应用程序也就不再话下。
那么现在让我们一起来阅读代码吧,首先我们知道Android API提供的ArrayAdapter对象只允许存入String数组或List对象,所以在显示文件列表时,只能以一段字符串来显示文件的名称,如果要同时显示文件夹和文件的图标,以及文件名称,甚至文件类型、大小等信息,则必须要自定义一个实现Adapter Interface的对象,就可以自定义想要呈现的Layout,达到同时显示图片文件ICON与多个文字信息的效果,Android API中提供了BaseAdapter(Android.widget.BaseAdapter)对象,只要继承此对象就可以实现出属于自己的Adapter。
实现此范例时,须要先准备文件图标的ICON图片文件,并保存在/res/drawable/文件夹下,图片文件路径如下:
1 |
/res/drawable/back01.png; 回到根目录的图标 |
2 |
/res/drawable/back02.png; 回到上一层的图标 |
3 |
/res/drawable/doc.png; 文件的图标 |
4 |
/res/drawable/folder.png; 文件夹的图标 |
package com.zchening.inote;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.ListView;
public class OpenActivity extends ListActivity
{
/* 变量声明
items:存放显示的名称
paths:存放文件路径
rootPath:起始目录 */
private List items=null;
private List paths=null;
private String rootPath="/";
// private TextView mPath;
private String path="";
@Override
protected void onCreate(Bundle icicle){
super.onCreate(icicle);
/* 载入main.xml Layout */
// setContentView(R.layout.main);
/* 初始化mPath,用以显示目前路径 *///@Test@??
// mPath=(TextView)findViewById(R.id.mPath);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
getFileDir(Environment.getExternalStorageDirectory());
}else{
getFileDir(new File(rootPath));
}
}
/* 取得文件架构的方法 */
private void getFileDir(File fileDir){
/* 设置目前所在路径*/
// mPath.setText(filePath);
items=new ArrayList();
paths=new ArrayList();
File f=fileDir;
String filePath=f.getPath();
// 取得当前路径下所有文件
File[] files=f.listFiles();
// 如果不是根目录
if(!filePath.equals(rootPath))
{
/*第一笔设置为【回到根目录】 */
items.add("b1");
paths.add(rootPath);
/*第二笔设置为【回到上一层】 */
items.add("b2");
paths.add(f.getParent());
}
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) && f.getName().equals("sdcard")){
new AlertDialog.Builder(this)
.setIcon(R.drawable.alert_dialog_icon2)
.setTitle(" SD 卡已卸载或移除,请先安装 SD 卡!")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
Intent i=new Intent(OpenActivity.this,MainActivity.class);
startActivity(i);
}
}).show();
}
/* 将所有文件添加到ArrayList中 */
for(int i=0;i
<注>BytesEncodingDetect用于判断文本文件的字符编码(见附件)
MyAdapter.java
package irdc.ex05_11;
/* import相关class */
import java.io.File;
import java.util.List;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
/* 自定义的Adapter,继承android.widget.BaseAdapter */
public class MyAdapter extends BaseAdapter
{
/* 变量声明
mIcon1 回到根目录的图片文件
mIcon2回到上一层的图片
mIcon3文件夹的图片文件
mIcon4文件的图片
*/
private LayoutInflater mInflater;
private Bitmap mIcon1;
private Bitmap mIcon2;
private Bitmap mIcon3;
private Bitmap mIcon4;
private List items;
private List paths;
/* MyAdapter的构造器,传入三个参数 */
public MyAdapter(Context context,List it,List pa)
{
/* 参数初始化*/
mInflater = LayoutInflater.from(context);
items = it;
paths = pa;
// 生成4张图片
mIcon1 = BitmapFactory.decodeResource(context.getResources(),R.drawable.back01);
mIcon2 = BitmapFactory.decodeResource(context.getResources(),R.drawable.back02);
mIcon3 = BitmapFactory.decodeResource(context.getResources(),R.drawable.folder);
mIcon4 = BitmapFactory.decodeResource(context.getResources(),R.drawable.doc);
}
/* 因继承BaseAdapter,需重写一下方法*/
@Override
public int getCount()
{
return items.size();
}
@Override
public Object getItem(int position)
{
return items.get(position);
}
@Override
public long getItemId(int position)
{
return position;
}
@Override
public View getView(int position,View convertView,ViewGroup parent)
{
ViewHolder holder;
if(convertView == null)
{
/* 使用自定义的file_row作为Layout */
convertView = mInflater.inflate(R.layout.file_row, null);
/* 初始化holder的text和icon */
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
File f=new File(paths.get(position).toString());
/* 设置【回到根目录】的text和icon */
if(items.get(position).toString().equals("b1"))
{
holder.text.setText("Back to /");
holder.icon.setImageBitmap(mIcon1);
}
/*设置【回到上一层】的text和icon*/
else if(items.get(position).toString().equals("b2"))
{
holder.text.setText("Back to ..");
holder.icon.setImageBitmap(mIcon2);
}
/* 设置【文件和文件夹】的text和icon */
else
{
holder.text.setText(f.getName());
if(f.isDirectory())
{
holder.icon.setImageBitmap(mIcon3);
}
else
{
holder.icon.setImageBitmap(mIcon4);
}
}
return convertView;
}
/* class ViewHolder */
private class ViewHolder
{
TextView text;
ImageView icon;
}
}
写在最后:本范例重点在于如何通过实现自定义的Adapter对象来自定义想要呈现的Layout,以及如何在手机上实现打开文件的功能。
通过自定义的Adapter,可以在ListView中放入任何想要呈现的widget对象,如RadioButton、CheckBox、EditText等,如此一来,在开发程序时,就可以做更多样化得应用。
在主程序中自定义了openFile()这个方法来做打开文件的动作,程序内容如下
/* 调用getMIMEType()来取得MimeType */
String type = getMIMEType(f);
/* 设置intent的file和MimeType */
intent.setDataAndType(Uri.fromFile(f),type);
startActivity(intent);
其中使用intent.setDataAndType(Uri,type)来指定要打开的文件及文件的MIME Type,并以startActivity()的方式来打开文件。getMIMEType()这个方法中,依据文件的拓展名来设置文件的MIME Type,MIME Type格式为“文件类型/文件拓展名”,目前程序中针对部分类型的文件做MIME Type的判断,其余的文件则一律将MIME Type设置为“*/*”,当系统受到文件的类型为“*”时,会自动弹出应用程序的菜单,让用户自己选择要用哪个程序打开文件。
-----------------------------------------------------
<注>
部分代码参考自《Android SDK范例大全》
附件:判断文本文件的字符编码