Android资源管理器程序

     这是一个有图标的文件资源管理器,也许在网上的基于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<String> items=null;
	private List<String> 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<String>();
	    paths=new ArrayList<String>();
		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<files.length;i++){
	    	items.add(files[i].getName());
	    	paths.add(files[i].getPath());
	    	Log.i("FileTest","getpath:"+files[i].getPath());
	    }

		MyAdapter adapter=new MyAdapter(this,items,paths);
		setListAdapter(adapter);
	  }
	
	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		super.onListItemClick(l, v, position, id);
		String itemName=String.valueOf(l.getItemAtPosition(position));
		Log.i("FileTest","itemName"+l.getItemAtPosition(position));
		path=paths.get(items.indexOf(itemName));
		Log.i("FileTest","path:"+path);
		File file=new File(path);
		if (file.isDirectory()){
			getFileDir(file);
		}else{
			openFile(file);
		}
	}
	
	public void openFile(File file){

//	 	调用getMIMEType()来取得MimeType 
		String type =getMIMEType(file); 
		if (file.getName().endsWith(".txt") || file.getName().endsWith(".hex") || file.getName().endsWith(".dat") || file.getName().endsWith(".ini") || file.getName().endsWith(".log") || file.getName().endsWith(".bin")||file.getName().endsWith(".java") || type.equals("*/*")){
			try{
	    		BytesEncodingDetect s = new BytesEncodingDetect(); 
				String code = BytesEncodingDetect.nicename[s.detectEncoding(file)];
				String str=String.valueOf(this.readFile(file, code));
		    	Intent i = new Intent(this, EditActivity.class);
		    	i.putExtra("path", file.getParent());
		    	Log.i("FileTest","---Path:"+file.getAbsolutePath()+"-----");//@Test@
		    	i.putExtra("self", false);
				i.putExtra("title", file.getName());
				i.putExtra("body", str);
				startActivity(i);
		    	
	    	}catch(Exception e){
	    		Log.i("FileTest",e.getMessage());
	    	}
		}else{/*
	//		 调用getMIMEType()来取得MimeType 
			String type =getMIMEType(file); */
	//		设置intent的file和MimeType 
			Intent intent=new Intent();
			intent.setDataAndType(Uri.fromFile(file),type);
			startActivity(intent);
		}
	}
	
	private String getMIMEType(File f)
	{
	    String type="";
	    String fName=f.getName();
	    /* 后缀名 */
	    String end=fName.substring(fName.lastIndexOf(".")+1,fName.length()).toLowerCase(); 
	    Log.i("FileTest","end :" +end);//@Test@
	    
	    /* 格式 */
	    if(end.equals("m4a")||end.equals("mp3")||end.equals("mid")||end.equals("xmf")||end.equals("ogg")||end.equals("wav")){
	      type = "audio"; 
	    }else if(end.equals("3gp")||end.equals("mp4")){
	      type = "video";
	    }else if(end.equals("jpg")||end.equals("gif")||end.equals("png")||end.equals("jpeg")||end.equals("bmp")){
	      type = "image";
	    }else{
	      type="*";
	    }
	    type += "/*"; 
	    return type; 
	}
	
         //读取文本文件
	 public Object readFile(File file, String code) {
			StringBuilder sb=null;
			try{
				String myCode = code!=null&&!"".equals(code) ? code : "UTF8";
				if (code.equals("GB-2312")||code.equals("OTHER")){
					myCode="GBK";
				}
				InputStreamReader read = new InputStreamReader(new FileInputStream(file.getPath()), myCode);
				BufferedReader fr = new BufferedReader(read);
				String str="";
				sb=new StringBuilder();
				while(null!=(str=fr.readLine())){
					sb.append(str);
					sb.append("\r\n");
				}
				fr.close();
				if (null!=sb){
					return sb.toString();
				}
			}catch (Exception e) {
				Log.i("FileTest",e.getMessage());
			}
			return sb;
		}
  /*
   * 程序中使用自定义的MyAdapter来设置显示的数据,传入存储文件名称和文件路径的两个List对象,
   * 使用setListAdapter()将数据设置给ListView.当用户单击item时,onListItemClick()会被触发,
   * 此时,程序会判断item是文件夹还是文件。是文件夹的话,就调用getFileDir()方法展开下层的目录;
   * 是文件的话,就运行自定义的openFile()方法打开此文件。在openFile()这个方法中,会先取得文件
   * 的MIME TYPE,系统会依传入的MIME TYPE来决定要如何打开文件,如果无法判断,则直接跳出应用程序
   * 列表,让用户选择要用哪一个程序打开。
   * */
  
 }

 <注>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对象,并以file_row.xml作为Layout,程序中依照文件的类型来决定要显示的图标是什么。
file_row.xml

 

<!--?xml version="1.0" encoding="utf-8"?-->
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent">
  <imageview android:id="@+id/icon" android:layout_width="30dip" android:layout_height="30dip">
  </imageview>
  <textview android:id="@+id/text" android:layout_gravity="center_vertical" android:layout_width="0dip" android:layout_weight="1.0" android:layout_height="wrap_content" android:textcolor="@drawable/black">
  </textview>
</linearlayout>

     写在最后:本范例重点在于如何通过实现自定义的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范例大全》

附件:判断文本文件的字符编码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值