小汪同学

 

Android-文件浏览器(一)

 

  题记:Hi,好久没更新了,深感坚持写技术博客的不易,不过把自己学到的东西拿出来跟大家分享真的很快乐,本人技术水平有限,还望海涵!

  项目需求:Android平台下的 文件浏览器,我们默认浏览SD卡中的文件。

  需求分析:我们知道Android SD卡也是一个文件夹,他的目录在../mnt/sdcard,注意android2.2之前目录是../sdcard,这个大家了解下就行了,那么我们考虑用J2se中的File 就可以遍历这个文件夹,获得里面的文件信息,所以还是比较简单的。

  step1:新建项目A_FileBrowser,我们考虑,由于可能手机没有安装SD卡,所以考虑主界面使用ViewFlipper,可以检查SD是否可用后进行相应界面的切换后显示操作提示,这里我们一切从简,没有对布局进行太多的考虑,xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width
="fill_parent"
android:layout_height
="fill_parent"
android:orientation
="vertical">

<TextView
android:layout_width="fill_parent"
android:layout_height
="wrap_content"
android:text
="@string/hello"
android:id
="@+id/tvTips"
/>

<ViewFlipper
android:id="@+id/viewFlipper1"
android:layout_width
="match_parent"
android:layout_height
="match_parent"
android:background
="#ffffff"
android:orientation
="vertical"
>
<!-- (0)loading -->
<LinearLayout
android:id="@+id/loadLayout"
android:layout_width
="match_parent"
android:layout_height
="match_parent"
android:orientation
="horizontal"
>
<ProgressBar
android:id="@+id/loadProgressbar"
android:layout_height
="wrap_content"
android:layout_width
="wrap_content"
></ProgressBar>"
<LinearLayout
android:layout_width="match_parent"
android:layout_height
="match_parent"
android:orientation
="horizontal"
>
<TextView
android:id="@+id/tvload"
android:layout_marginLeft
="15dip"
android:layout_marginTop
="10dip"
android:layout_width
="wrap_content"
android:layout_height
="wrap_content"
android:text
="@string/loading"
/>

</LinearLayout>

</LinearLayout>

<!-- (1) listview -->
<LinearLayout
android:id="@+id/showLayout"
android:layout_width
="match_parent"
android:layout_height
="match_parent"
>
<ListView
android:id="@+id/listview"
android:layout_width
="match_parent"
android:layout_height
="match_parent"
android:background
="#0f0000"
></ListView>

</LinearLayout>

<!-- (2) falied layout -->
<LinearLayout
android:id="@+id/retryLayout"
android:layout_width
="match_parent"
android:layout_height
="match_parent"
android:orientation
="horizontal"
>
<TextView
android:id="@+id/tvFalied"
android:layout_width
="wrap_content"
android:layout_height
="wrap_content"
android:text
="@string/load_falied"
></TextView>
<Button
android:id="@+id/retryBtn"
android:layout_width
="wrap_content"
android:layout_height
="wrap_content"
android:text
="@string/retry"
/>
</LinearLayout>

</ViewFlipper>

</LinearLayout>

 

step2:编写刚才创建的Activity中的代码:

    这里要重点说明一下这一段代码:

 

private class NewsTask extends AsyncTask<String ,Void,FileAttr [] > {

		@Override
		protected FileAttr[] doInBackground(String... params) {
			//sd card is aviable else show falied
			if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
			{
				File file = new File(params[0]);
				if(file == null || !file.isDirectory())
				{
					return null;
				}
				mStack.push(params[0]);			
				File [] fileList = file.listFiles();
				ArrayList<FileAttr> arrayList = new ArrayList<FileAttr>();
				//
				for(File fi : fileList)
				{
					Log.d(TAG,fi.getName());
					FileAttr attr = new FileAttr();
					if(fi.isDirectory())
					{
						attr.setFileName(fi.getName() );
						attr.setFileType(AttrDefine.DIC);
						Log.d(TAG,"is dic");
					}
					else if(fi.getName().endsWith(".txt"))
					{
						attr.setFileName(fi.getName());
						attr.setFileType(AttrDefine.TXT);
					}
					else if(fi.getName().endsWith(".mp3"))
					{
						attr.setFileName(fi.getName());
						attr.setFileType(AttrDefine.AUD);
					}
					else if(fi.getName().endsWith(".3gp"))
					{
						attr.setFileName(fi.getName());
						attr.setFileType(AttrDefine.VID);
					}
					else if(fi.getName().endsWith(".png") || fi.getName().endsWith(".jpeg"))
					{
						attr.setFileName(fi.getName());
						attr.setFileType(AttrDefine.PIC);
					}
					else
					{
						attr.setFileName(fi.getName());
						attr.setFileType(AttrDefine.UNKNOW);
					}
					
					arrayList.add(attr);
				}
				if(arrayList.size() > 0)
				{
					FileAttr [] fileAttrs = new FileAttr[arrayList.size()];
					for(int i = 0 ;i <arrayList.size() ; i ++)
					{
						fileAttrs[i] = arrayList.get(i);
					}
					return fileAttrs;
				}
				return null;
			}
			else
			{
//				mViewFlipper.setDisplayedChild(2);
//				FileAttr[] files = new FileAttr[1];
//				files[0] = new FileAttr();
//				files[0].setFileType(0);
//				return files;
				return null;
			}
		}

		@Override
		protected void onPostExecute(FileAttr[] result) {
			if( result == null)
			{
				mViewFlipper.setDisplayedChild(2);
			}
			else 
			{
				mViewFlipper.setDisplayedChild(1);
				Log.d(TAG,result[0].getFileType() + "");
				adapter = new ImageAdapter(result,A_FileBrowserActivity.this);
				mListView.setAdapter(adapter);
				adapter.notifyDataSetChanged();
				mListView.setOnItemLongClickListener(listListener);
				Log.d(TAG,((FileAttr) adapter.getItem(0)).getFileType() + "");
			}
			super.onPostExecute(result);
		}

		@Override
		protected void onPreExecute() {
			mViewFlipper.setDisplayedChild(1);
			
			super.onPreExecute();
		}

		@Override
		protected void onProgressUpdate(Void... values) {
			// TODO Auto-generated method stub
			super.onProgressUpdate(values);
		}
    	
    }

 

   private class NewsTask extends AsyncTask<String ,Void,FileAttr [] >,我们新建了一个私有类,并继承了AsyncTack这个类,后面的三个参数是有选的,如果不需要用的话就用Void代替就可以了,这个类的作用是在后台替我们执行一段代码,并根据我们的输入运行我们需要实现的功能,当然我们可以在他的对应的成员方法中做我们需要做的事情,其中doInBackground(String... params)就是在后台要做的事情,params是我们传递的参数,onPostExecute(FileAttr[] result)是后台执行完毕后,根据后台方法返回值进行下一步代码执行。在这里我们完成了对SD卡的检测,并切换到对应界面,然后对SD卡根目录进行浏览遍历,在listview中显示,运行效果如下:

 

这里还要提一下的是,由于列表显示,Android里面适配器一般都是由我们自己来重写实现,毕竟自由度很大,这也是我认为的Android平台最大魅力的地方,足够开放,我们自定义了一个ImageAdapter extends BaseAdapter,代码如下:

public class ImageAdapter extends BaseAdapter {
	
	public static final int S_YEAR = 1970;
	public static final int S_MONTH = 1;
	public static final int S_DAY = 1;
	
	
	private FileAttr [] mFileAttr;
	private Context mContext;
	public ImageAdapter(FileAttr [] fileAttr , Context context)
	{
		this.mFileAttr = fileAttr;
		this.mContext = context;
	}
	
	
	
	public FileAttr[] getmFileAttr() {
		return mFileAttr;
	}



	public void setmFileAttr(FileAttr[] mFileAttr) {
		this.mFileAttr = mFileAttr;
	}



	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return mFileAttr.length;
	}

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return mFileAttr[position];
	}

	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		View tag = convertView;
		
		if(tag == null)
		{
			tag = LayoutInflater.from(mContext).inflate(R.layout.adapter, null);

		}
		
		ImageView btn = (ImageView)tag.findViewById(R.id.imageView1);
		TextView tv = (TextView)tag.findViewById(R.id.textView1);
		TextView tvAttr = (TextView)tag.findViewById(R.id.tvFileMsg);
		switch(mFileAttr[position].getFileType())
		{
		case AttrDefine.DIC:
			btn.setImageResource(R.drawable.dic);
			break;
		case AttrDefine.AUD:
			btn.setImageResource(R.drawable.audio);
			break;
		case AttrDefine.TXT:
			btn.setImageResource(R.drawable.text);
			break;
		case AttrDefine.VID:
			btn.setImageResource(R.drawable.video);
			break;
		case AttrDefine.PIC:
			btn.setImageResource(R.drawable.pic);
			break;
		case AttrDefine.UNKNOW:
			btn.setImageResource(R.drawable.unknow);
			break;

	//	default:
	//		btn.setImageResource(R.drawable.ic_launcher);
		}
		
		tv.setText(mFileAttr[position].getFileName());
		
		File file = new File(A_FileBrowserActivity.mCurPath + "/" + mFileAttr[position].getFileName());
		if(file != null)
		{
			long length = file.length();
			length /=1000;
			long updataTime = file.lastModified();
			updataTime /= 1000;				//ms 单位
			updataTime /= (3600*24);		//换算成天
			long iyear = updataTime / 365;
			long inext = updataTime - iyear * 365;
			long imonth = inext/30;
			long iday = inext - 30 * imonth; 
			iyear += this.S_YEAR;
			tvAttr.setText(String.valueOf(length) + " kB\n " + String.valueOf(iyear) + "."+String.valueOf(imonth) + "." + String.valueOf(iday)  );
		}
		return tag;
	}

}

  这一块其实大家都应该比较熟了,不再赘述,但是我们的文件信息里面有一个最后修改的时间,这个直接通过File的lastModified方法,返回的是一个相对于1970年1月1号的 一个 long型长整数,而且是ms级的,所以我们进行了一下转换,这里关于闰年没有进行考虑,只是随便简单算了一下,存在不足,有兴趣的童鞋可以去实现一下,不是很难的,还有这里我对几种常见的文件的图标进行了分类显示,这个也很容易做到,不再赘述,这一篇就到这吧,下一篇我们继续,不然一篇太长了吧,你我看了都累!-。-

posted on 2011-11-22 11:20  小汪同学  阅读(1144)  评论(0)    收藏  举报

导航