文件管理器实现

2016-6-1 chenhui 随笔

文件管理器的实现比较复杂,本文只介绍一些关键点,为没有思路的同学起到提醒的作用,一些杂七杂八的简单的功能可以自己琢磨。


一个优秀的文件管理器,他应该实现如下功能:

  1. 文件系统浏览和操作(需排序)
  2. 文件分类(如音乐、视频、图片)


文件系统浏览的功能如何实现?


一个 Layout,里面放一个 ListView,就构成了文件系统浏览的界面,接下来要做的就是读取文件系统目录。

对于文件目录的读取,我们有三种选择:根目录、内存、SD卡。由于 SD 卡取消成风,一般来说都是读取内存了,目录是 /mnt/sdcard。


然后打开目录并得到目录项列表,如下:


File file = new File(path);
if (!file.exists() || !file.isDirectory()) {
        return false;
}
File[] listFiles = file.listFiles();
if (listFiles == null)
        return true;


这样就得到了目录项列表,我们最好对他遍历一下,把每个文件的信息都整理成一个对象(比如是否为对象),一起存放到一个列表里,最后对这个列表进行排序。怎么排序呢?网络上有很多中文排序的库和代码,直接复制下来用就可以。


有了目录项列表,该怎么把他插入到 ListView 内呢?当然是 Adapter。我们可以用 ArrayAdapter 或 ListAdapter 来实现。具体代码就不贴了,代码太长。这里一定要注意,别忘了在 getView 里为目录项设置布局。


我们不仅仅是要浏览一个目录里的目录项,并且我们还要对这些目录项进行操作(假设是长按目录项进入编辑模式),所以我们还需要处理到目录项的点击和长按这两个事件,也即 ListView 一项的点击和长按事件,这两个事件的设置可以通过调用 ListView 的 setOnItemClickListener 和 setOnItemLongClickListener 来实现。



fileList.setOnItemClickListener(new OnItemClickListener() {

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) {
		// TODO Auto-generated method stub

		
	}
});

fileList.setOnItemLongClickListener(new OnItemLongClickListener() {

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) {
		// TODO Auto-generated method stub

		
	}
});


对于目录项的单击处理,可区分为目录和文件:如果是目录,则需要再进入这个目录,这就不必多说了;如果是文件,就要通知其他 APP 来打开这个文件。


对于通知其他 APP 来打开文件,又分为两种情况:

  1. 已知的文件类型
  2. 未知的文件类型

得到类型是必须要先做的,我们可以简单的得到判断文件后缀来判断他的类型,得到的方法也很简单,做简单的字符串分割即可:


private static String getMimeType(String filePath) {
	
    // 分割文件路径
    int dotPosition = filePath.lastIndexOf('.');
    // 没有后缀,未知类型
    if (dotPosition == -1)
        return "*/*";
    	
    // 取出后缀字符串
    String ext = filePath.substring(dotPosition + 1, filePath.length()).toLowerCase();
    // 从哈希表中根据后缀取出 Android 认可的格式,这些格式有比如 image/* 就是图片,audio/* 就是音乐
    // 哈希表是自己定义的,里面有哪些格式也请自己添加
    String mimeType = MimeUtils.guessMimeTypeFromExtension(ext);
    // 如果有对应的格式,则返回,否则就是未知类型
    return mimeType != null ? mimeType : "*/*";
}


现在我们知道了文件的格式,就可以进行对应的操作了,下面是打开已知格式文件的代码:


Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(filePath)), type);
context.startActivity(intent);


至于未知类型的文件,谁也不知道他该怎么打开,你大可以告知用户不知道怎么打开这个文件,也可以弹出一个信息框让用户自己确认这是什么类型的文件。


文件浏览和操作的关键点也就是这些了,有了这个框架,自然就能够调用各种各样的 API 来实现不同的功能。

 

文件分类的功能如何实现?


两个方法

  1. 遍历
  2. 使用 Files 类

遍历的方法太过简单粗暴,所以还是第二个类好用一些,关于第二个类,之前我在网络上找到一个工具类,我这里就直接贴过来了。当然他不能直接使用,可以根据实际情况进行修改。


public class FileUtils {  
  
      
    public static void getSpecificTypeOfFile(Context context,String[] extension)  
    {  
        //从外存中获取  
        Uri fileUri=Files.getContentUri("external");  
        //筛选列,这里只筛选了:文件路径和不含后缀的文件名  
        String[] projection=new String[]{  
                FileColumns.DATA,FileColumns.TITLE  
        };  
        //构造筛选语句  
        String selection="";  
        for(int i=0;i<extension.length;i++)  
        {  
            if(i!=0)  
            {  
                selection=selection+" OR ";  
            }  
            selection=selection+FileColumns.DATA+" LIKE '%"+extension[i]+"'";  
        }  
        //按时间递增顺序对结果进行排序;待会从后往前移动游标就可实现时间递减  
        String sortOrder=FileColumns.DATE_MODIFIED;  
        //获取内容解析器对象  
        ContentResolver resolver=context.getContentResolver();  
        //获取游标  
        Cursor cursor=resolver.query(fileUri, projection, selection, null, sortOrder);  
        if(cursor==null)  
            return;  
        //游标从最后开始往前递减,以此实现时间递减顺序(最近访问的文件,优先显示)  
        if(cursor.moveToLast())  
        {  
            do{  
                //输出文件的完整路径  
                String data=cursor.getString(0);  
                Log.d("tag", data);  
            }while(cursor.moveToPrevious());  
        }  
        cursor.close();  
          
    }  
}


使用方法如下,传入 Context 和后缀名即可:


FileUtils.getSpecificTypeOfFile(this, new String[]{".doc",".apk"});  







发表评论:

Copyright ©2015-2016 freehui All rights reserved