当前位置: 移动技术网 > 移动技术>移动开发>Android > android文件管理器用法详解

android文件管理器用法详解

2019年07月24日  | 移动技术网移动技术  | 我要评论

很久没有写东西了,鉴于某某同学文件管理器不会,这里简单介绍一下,同时写一个demon,参考了网上别人写的代码,自己也学习学习,研究研究。

  首先所谓文件管理器,看起来就是一个列表,列表里面是文件夹或者文件,首先把布局写出来,我想在最上方的左边显示文件的路径,右边显示该路径下的文件个数,其实还是一个遍历文件,然后用列表显示出来的问题。下面是listview,用来显示文件列表。下面是运行的效果图:

主界面的布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical" >
  <relativelayout 
    android:id="@+id/top"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <textview 
      android:id="@+id/path"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignparentleft="true"
      android:layout_centervertical="true"
      android:textsize="@*android:dimen/list_item_size"
      android:textcolor="@android:color/white"/>
    
    <textview 
      android:id="@+id/item_count"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:textsize="@*android:dimen/list_item_size"
      android:textcolor="@android:color/white"
      android:layout_alignparentright="true"
      android:layout_centervertical="true"/>
  </relativelayout>
  <view 
    android:layout_width="match_parent"
    android:layout_height="2dip"
    android:background="#09c"/>

  <linearlayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <listview 
      android:id="@+id/file_list"
      android:layout_height="match_parent"
      android:layout_width="match_parent"
      android:fadingedge="none"
      android:cachecolorhint="@android:color/transparent"/>
  </linearlayout>
</linearlayout>

首先在oncreate方法里面调用一个方法去获取布局文件里面的id:

@override
   protected void oncreate (bundle savedinstancestate) {
     super.oncreate(savedinstancestate);
     setcontentview(r.layout.file_manager);
     initview();
 }

initview之后添加apk的权限,777 表示可读可写可操作。

private void initview() {
    mlistview = (listview) findviewbyid(r.id.file_list);
    mpathview = (textview) findviewbyid(r.id.path);
    mitemcount = (textview) findviewbyid(r.id.item_count);
    mlistview.setonitemclicklistener(this);
    string apkroot = "chmod 777 " + getpackagecodepath(); 
    rootcommand(apkroot);
    file folder = new file("/");
    initdata(folder);
  } 

修改root权限的方法:

public static boolean rootcommand (string command) {
    process process = null;
    dataoutputstream os = null;
    try {
      process = runtime.getruntime().exec("su");
      os = new dataoutputstream(process.getoutputstream());
      os.writebytes(command + "\n");
      os.writebytes("exit\n");
      os.flush();
      process.waitfor();
    }
    catch (exception e) {
      return false;
    }
    finally {
      try {
        if (os != null) {
          os.close();
        }
        process.destroy();
      }
      catch (exception e) {
        e.printstacktrace();
      }
    }
    return true;
  }

完了之后我们要获取根目录下面的所有的数据,然后设置到我们的listview中让它显示出来。

private void initdata(file folder) {
    boolean isroot = folder.getparent() == null; 
    mpathview.settext(folder.getabsolutepath()); 
    arraylist<file> files = new arraylist<file>();  
    if (!isroot) {
      files.add(folder.getparentfile()); 
    }
    file[] filterfiles = folder.listfiles(); 
    mitemcount.settext(filterfiles.length + "项"); 
    if (null != filterfiles && filterfiles.length > 0) {
      for (file file : filterfiles) {
        files.add(file);
      }
    }
    mfileadpter = new filelistadapter(this, files, isroot); 
    mlistview.setadapter(mfileadpter);
  }

首先是获取当前是否是根目录,然后把文件的路径设置给我们要显示的view。

然后用一个arraylist来装我们目录下的所有的文件或者文件夹。

首先要把这个文件夹的父类装到我们的列表中去,然后把这个文件夹下的子文件都拿到,也装在列表中,然后调用adapter显示出来。既然说到了adapter, 那就看下adapter吧。

private class filelistadapter extends baseadapter {

    private context context;
    private arraylist<file> files;
    private boolean isroot;
    private layoutinflater minflater;
    
    public filelistadapter (context context, arraylist<file> files, boolean isroot) {
      this.context = context;
      this.files = files;
      this.isroot = isroot;
      minflater = layoutinflater.from(context);
    }
    
    @override
    public int getcount () {
      return files.size();
    }

    @override
    public object getitem (int position) {
      return files.get(position);
    }

    @override
    public long getitemid (int position) {
      return position;
    }
    
    @override
    public view getview (int position, view convertview, viewgroup parent) {
      viewholder viewholder;
      if(convertview == null) {
        viewholder = new viewholder();
        convertview = minflater.inflate(r.layout.file_list_item, null);
        convertview.settag(viewholder);
        viewholder.title = (textview) convertview.findviewbyid(r.id.file_title);
        viewholder.type = (textview) convertview.findviewbyid(r.id.file_type);
        viewholder.data = (textview) convertview.findviewbyid(r.id.file_date);
        viewholder.size = (textview) convertview.findviewbyid(r.id.file_size);
      } else {
        viewholder = (viewholder) convertview.gettag();
      }
      
      file file = (file) getitem(position);
      if(position == 0 && !isroot) {
        viewholder.title.settext("返回上一级");
        viewholder.data.setvisibility(view.gone);
        viewholder.size.setvisibility(view.gone);
        viewholder.type.setvisibility(view.gone);
      } else {
        string filename = file.getname();
        viewholder.title.settext(filename);
        if(file.isdirectory()) {
          viewholder.size.settext("文件夹");
          viewholder.size.settextcolor(color.red);
          viewholder.type.setvisibility(view.gone);
          viewholder.data.setvisibility(view.gone);
        } else {
          long filesize = file.length();
          if(filesize > 1024*1024) {
            float size = filesize /(1024f*1024f);
            viewholder.size.settext(new decimalformat("#.00").format(size) + "mb");
          } else if(filesize >= 1024) {
            float size = filesize/1024;
            viewholder.size.settext(new decimalformat("#.00").format(size) + "kb");
          } else {
            viewholder.size.settext(filesize + "b");
          }
          int dot = filename.indexof('.');
          if(dot > -1 && dot < (filename.length() -1)) {
            viewholder.type.settext(filename.substring(dot + 1) + "文件");
          }
          viewholder.data.settext(new simpledateformat("yyyy/mm/dd hh:mm").format(file.lastmodified()));
        }
      }
      return convertview;
    }
    
    class viewholder {
      private textview title;
      private textview type;
      private textview data;
      private textview size;
    }
  }

看下adapter的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical" >
  <textview 
      android:id="@+id/file_title"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:textsize="25sp"
      android:textcolor="#fff000"/>
  <linearlayout 
    android:id="@+id/file_info"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <textview 
      android:id="@+id/file_size"
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:textcolor="#ffffcc"
      android:layout_weight="1"
      android:textsize="18sp"/>
    
    <textview 
      android:id="@+id/file_type"
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:textcolor="#ffffcc"
      android:layout_weight="1"
      android:gravity="right"
      android:textsize="18sp"/>
    <textview 
      android:id="@+id/file_date"
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:textcolor="#ffffff"
      android:layout_weight="1"
      android:gravity="right"
      android:textsize="18sp"/>
  </linearlayout>
</linearlayout>

列表的item项分2行显示,上面一行显示文件名

下面一行分别显示文件大小,文件类型,文件修改时间。

我们可以通过file file = (file) getitem(position);拿到item项的文件,如果是在第一个并且不再根目录我们就把第一个也就是parentfile显示为:“返回上一级”,下一行的都隐藏掉。

如果不是第一个位置,可以拿到这个文件的一系列信息。

先把string filename = file.getname();文件名拿到,显示出来。

如果这个文件是一个文件夹,就把文件的大小显示为“文件夹”,类型和修改时间隐藏掉。

如果不是一个文件夹, 可以拿到文件的长度long filesize = file.length();

根据特定的长度显示文件的大小,b, kb, mb, gb等。

然后拿到文件的类型,通过最后一个“.”之后的字符串就是该文件的类型。

通过viewholder.data.settext(new simpledateformat("yyyy/mm/dd hh:mm").format(file.lastmodified())); 设置文件的最近修改时间。

然后可以设置每个item项的点击事件,如下所示:

@override
  public void onitemclick (adapterview<?> parent, view view, int position, long id) {
    file file = (file) mfileadpter.getitem(position);
    if(!file.canread()) {
      new alertdialog.builder(this).settitle("提示").setmessage("权限不足").setpositivebutton(android.r.string.ok, new onclicklistener() {
        
        @override
        public void onclick (dialoginterface dialog, int which) {
          
        }
      }).show();
    } else if(file.isdirectory()) {
      initdata(file);
    } else {
      openfile(file);
    }
  }

如果这个文件不能读,就弹出对话框显示“权限不足”。

如果是一个文件夹,就在调用一次显示所有文件的方法:initdata(file);把这个文件夹作为参数传递下去。

如果是一个文件,就可以调用打开文件的方法打开这个文件。

如何打开文件呢?

可以根据不同的文件的后缀名找到不同的文件类型:

可以用一个二维数组把一些常用的文件类型封装起来。如下:

private final string[][] mime_maptable = {
    // {后缀名, mime类型}
    { ".3gp", "video/3gpp" }, 
    { ".apk", "application/vnd.android.package-archive" }, 
    { ".asf", "video/x-ms-asf" }, 
    { ".avi", "video/x-msvideo" },
    { ".bin", "application/octet-stream" }, 
    { ".bmp", "image/bmp" }, 
    { ".c", "text/plain" }, 
    { ".class", "application/octet-stream" },
    { ".conf", "text/plain" }, 
    { ".cpp", "text/plain" }, 
    { ".doc", "application/msword" },
    { ".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document" }, 
    { ".xls", "application/vnd.ms-excel" },
    { ".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }, 
    { ".exe", "application/octet-stream" },
    { ".gif", "image/gif" }, 
    { ".gtar", "application/x-gtar" }, 
    { ".gz", "application/x-gzip" }, 
    { ".h", "text/plain" }, 
    { ".htm", "text/html" },
    { ".html", "text/html" }, 
    { ".jar", "application/java-archive" }, 
    { ".java", "text/plain" }, 
    { ".jpeg", "image/jpeg" },
    { ".jpg", "image/jpeg" }, 
    { ".js", "application/x-javascript" }, 
    { ".log", "text/plain" }, 
    { ".m3u", "audio/x-mpegurl" },
    { ".m4a", "audio/mp4a-latm" }, 
    { ".m4b", "audio/mp4a-latm" }, 
    { ".m4p", "audio/mp4a-latm" }, 
    { ".m4u", "video/vnd.mpegurl" },
    { ".m4v", "video/x-m4v" }, 
    { ".mov", "video/quicktime" }, 
    { ".mp2", "audio/x-mpeg" }, 
    { ".mp3", "audio/x-mpeg" }, 
    { ".mp4", "video/mp4" },
    { ".mpc", "application/vnd.mpohun.certificate" }, 
    { ".mpe", "video/mpeg" }, 
    { ".mpeg", "video/mpeg" }, 
    { ".mpg", "video/mpeg" },
    { ".mpg4", "video/mp4" }, 
    { ".mpga", "audio/mpeg" }, 
    { ".msg", "application/vnd.ms-outlook" }, 
    { ".ogg", "audio/ogg" },
    { ".pdf", "application/pdf" }, 
    { ".png", "image/png" }, 
    { ".pps", "application/vnd.ms-powerpoint" },
    { ".ppt", "application/vnd.ms-powerpoint" }, 
    { ".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation" },
    { ".prop", "text/plain" }, 
    { ".rc", "text/plain" }, 
    { ".rmvb", "audio/x-pn-realaudio" }, 
    { ".rtf", "application/rtf" },
    { ".sh", "text/plain" }, 
    { ".tar", "application/x-tar" }, 
    { ".tgz", "application/x-compressed" }, 
    { ".txt", "text/plain" },
    { ".wav", "audio/x-wav" }, 
    { ".wma", "audio/x-ms-wma" }, 
    { ".wmv", "audio/x-ms-wmv" }, 
    { ".wps", "application/vnd.ms-works" },
    { ".xml", "text/plain" }, 
    { ".z", "application/x-compress" }, 
    { ".zip", "application/x-zip-compressed" }, 
    { "", "*/*" } 
    };

分别对应的是后缀名和对应的文件类型。

我们可以根据文件的后缀名拿到文件的mimetype类型:

private string getmimetype(file file) {
    string type = "*/*";
    string filename = file.getname();
    int dotindex = filename.indexof('.');
    if(dotindex < 0) {
      return type;
    }
    string end = filename.substring(dotindex, filename.length()).tolowercase();
    if(end == "") {
      return type;
    }
    for(int i=0; i<mime_maptable.length; i++) {
      if(end == mime_maptable[i][0]) {
        type = mime_maptable[i][1] ;
      }
    }
    return type;
  }

先遍历后缀名,如果找到,就把对应的类型找到并返回。

拿到了类型,就可以打开这个文件。

用这个intent.setdataandtype(uri.fromfile(file), type); 打开设置打开文件的类型。

如果type是*/*会弹出所有的可供选择的应用程序。

 到这里一个简易的文件管理器就成型了。

源代码:

package com.android.test;

import java.io.dataoutputstream;
import java.io.file;
import java.text.decimalformat;
import java.text.simpledateformat;
import java.util.arraylist;

import android.app.activity;
import android.app.alertdialog;
import android.content.context;
import android.content.dialoginterface;
import android.content.intent;
import android.content.dialoginterface.onclicklistener;
import android.graphics.color;
import android.net.uri;
import android.os.bundle;
import android.view.layoutinflater;
import android.view.view;
import android.view.viewgroup;
import android.widget.adapterview;
import android.widget.adapterview.onitemclicklistener;
import android.widget.baseadapter;
import android.widget.listview;
import android.widget.textview;
import android.widget.toast;

public class filemanager extends activity implements onitemclicklistener {
  
  private listview mlistview;
  private textview mpathview;
  private filelistadapter mfileadpter;
  private textview mitemcount;
  
  @override
  protected void oncreate (bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.file_manager);
    initview();
  }
  
  private void initview() {
    mlistview = (listview) findviewbyid(r.id.file_list);
    mpathview = (textview) findviewbyid(r.id.path);
    mitemcount = (textview) findviewbyid(r.id.item_count);
    mlistview.setonitemclicklistener(this);
    string apkroot = "chmod 777 " + getpackagecodepath(); 
    rootcommand(apkroot);
    file folder = new file("/");
    initdata(folder);
  }
  
  public static boolean rootcommand (string command) {
    process process = null;
    dataoutputstream os = null;
    try {
      process = runtime.getruntime().exec("su");
      os = new dataoutputstream(process.getoutputstream());
      os.writebytes(command + "\n");
      os.writebytes("exit\n");
      os.flush();
      process.waitfor();
    }
    catch (exception e) {
      return false;
    }
    finally {
      try {
        if (os != null) {
          os.close();
        }
        process.destroy();
      }
      catch (exception e) {
        e.printstacktrace();
      }
    }
    return true;
  }
  
  private void initdata(file folder) {
    boolean isroot = folder.getparent() == null; 
    mpathview.settext(folder.getabsolutepath()); 
    arraylist<file> files = new arraylist<file>();  
    if (!isroot) {
      files.add(folder.getparentfile()); 
    }
    file[] filterfiles = folder.listfiles(); 
    mitemcount.settext(filterfiles.length + "项"); 
    if (null != filterfiles && filterfiles.length > 0) {
      for (file file : filterfiles) {
        files.add(file);
      }
    }
    mfileadpter = new filelistadapter(this, files, isroot); 
    mlistview.setadapter(mfileadpter);
  }
  
  private class filelistadapter extends baseadapter {

    private context context;
    private arraylist<file> files;
    private boolean isroot;
    private layoutinflater minflater;
    
    public filelistadapter (context context, arraylist<file> files, boolean isroot) {
      this.context = context;
      this.files = files;
      this.isroot = isroot;
      minflater = layoutinflater.from(context);
    }
    
    @override
    public int getcount () {
      return files.size();
    }

    @override
    public object getitem (int position) {
      return files.get(position);
    }

    @override
    public long getitemid (int position) {
      return position;
    }
    
    @override
    public view getview (int position, view convertview, viewgroup parent) {
      viewholder viewholder;
      if(convertview == null) {
        viewholder = new viewholder();
        convertview = minflater.inflate(r.layout.file_list_item, null);
        convertview.settag(viewholder);
        viewholder.title = (textview) convertview.findviewbyid(r.id.file_title);
        viewholder.type = (textview) convertview.findviewbyid(r.id.file_type);
        viewholder.data = (textview) convertview.findviewbyid(r.id.file_date);
        viewholder.size = (textview) convertview.findviewbyid(r.id.file_size);
      } else {
        viewholder = (viewholder) convertview.gettag();
      }
      
      file file = (file) getitem(position);
      if(position == 0 && !isroot) {
        viewholder.title.settext("返回上一级");
        viewholder.data.setvisibility(view.gone);
        viewholder.size.setvisibility(view.gone);
        viewholder.type.setvisibility(view.gone);
      } else {
        string filename = file.getname();
        viewholder.title.settext(filename);
        if(file.isdirectory()) {
          viewholder.size.settext("文件夹");
          viewholder.size.settextcolor(color.red);
          viewholder.type.setvisibility(view.gone);
          viewholder.data.setvisibility(view.gone);
        } else {
          long filesize = file.length();
          if(filesize > 1024*1024) {
            float size = filesize /(1024f*1024f);
            viewholder.size.settext(new decimalformat("#.00").format(size) + "mb");
          } else if(filesize >= 1024) {
            float size = filesize/1024;
            viewholder.size.settext(new decimalformat("#.00").format(size) + "kb");
          } else {
            viewholder.size.settext(filesize + "b");
          }
          int dot = filename.indexof('.');
          if(dot > -1 && dot < (filename.length() -1)) {
            viewholder.type.settext(filename.substring(dot + 1) + "文件");
          }
          viewholder.data.settext(new simpledateformat("yyyy/mm/dd hh:mm").format(file.lastmodified()));
        }
      }
      return convertview;
    }
    
    class viewholder {
      private textview title;
      private textview type;
      private textview data;
      private textview size;
    }
  }

  @override
  public void onitemclick (adapterview<?> parent, view view, int position, long id) {
    file file = (file) mfileadpter.getitem(position);
    if(!file.canread()) {
      new alertdialog.builder(this).settitle("提示").setmessage("权限不足").setpositivebutton(android.r.string.ok, new onclicklistener() {
        
        @override
        public void onclick (dialoginterface dialog, int which) {
          
        }
      }).show();
    } else if(file.isdirectory()) {
      initdata(file);
    } else {
      openfile(file);
    }
  }
  
  private void openfile(file file) {
    intent intent = new intent();
    intent.addflags(intent.flag_activity_new_task); 
    intent.setaction(intent.action_view); 
    string type = getmimetype(file); 
    intent.setdataandtype(uri.fromfile(file), type); 
    try {
      startactivity(intent);
    }
    catch (exception e) {
      toast.maketext(this, "未知类型,不能打开", toast.length_short).show();
    }
  }
  
  private string getmimetype(file file) {
    string type = "*/*";
    string filename = file.getname();
    int dotindex = filename.indexof('.');
    if(dotindex < 0) {
      return type;
    }
    string end = filename.substring(dotindex, filename.length()).tolowercase();
    if(end == "") {
      return type;
    }
    for(int i=0; i<mime_maptable.length; i++) {
      if(end == mime_maptable[i][0]) {
        type = mime_maptable[i][1] ;
      }
    }
    return type;
  }
  
  private final string[][] mime_maptable = {
    // {后缀名, mime类型}
    { ".3gp", "video/3gpp" }, 
    { ".apk", "application/vnd.android.package-archive" }, 
    { ".asf", "video/x-ms-asf" }, 
    { ".avi", "video/x-msvideo" },
    { ".bin", "application/octet-stream" }, 
    { ".bmp", "image/bmp" }, 
    { ".c", "text/plain" }, 
    { ".class", "application/octet-stream" },
    { ".conf", "text/plain" }, 
    { ".cpp", "text/plain" }, 
    { ".doc", "application/msword" },
    { ".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document" }, 
    { ".xls", "application/vnd.ms-excel" },
    { ".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }, 
    { ".exe", "application/octet-stream" },
    { ".gif", "image/gif" }, 
    { ".gtar", "application/x-gtar" }, 
    { ".gz", "application/x-gzip" }, 
    { ".h", "text/plain" }, 
    { ".htm", "text/html" },
    { ".html", "text/html" }, 
    { ".jar", "application/java-archive" }, 
    { ".java", "text/plain" }, 
    { ".jpeg", "image/jpeg" },
    { ".jpg", "image/jpeg" }, 
    { ".js", "application/x-javascript" }, 
    { ".log", "text/plain" }, 
    { ".m3u", "audio/x-mpegurl" },
    { ".m4a", "audio/mp4a-latm" }, 
    { ".m4b", "audio/mp4a-latm" }, 
    { ".m4p", "audio/mp4a-latm" }, 
    { ".m4u", "video/vnd.mpegurl" },
    { ".m4v", "video/x-m4v" }, 
    { ".mov", "video/quicktime" }, 
    { ".mp2", "audio/x-mpeg" }, 
    { ".mp3", "audio/x-mpeg" }, 
    { ".mp4", "video/mp4" },
    { ".mpc", "application/vnd.mpohun.certificate" }, 
    { ".mpe", "video/mpeg" }, 
    { ".mpeg", "video/mpeg" }, 
    { ".mpg", "video/mpeg" },
    { ".mpg4", "video/mp4" }, 
    { ".mpga", "audio/mpeg" }, 
    { ".msg", "application/vnd.ms-outlook" }, 
    { ".ogg", "audio/ogg" },
    { ".pdf", "application/pdf" }, 
    { ".png", "image/png" }, 
    { ".pps", "application/vnd.ms-powerpoint" },
    { ".ppt", "application/vnd.ms-powerpoint" }, 
    { ".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation" },
    { ".prop", "text/plain" }, 
    { ".rc", "text/plain" }, 
    { ".rmvb", "audio/x-pn-realaudio" }, 
    { ".rtf", "application/rtf" },
    { ".sh", "text/plain" }, 
    { ".tar", "application/x-tar" }, 
    { ".tgz", "application/x-compressed" }, 
    { ".txt", "text/plain" },
    { ".wav", "audio/x-wav" }, 
    { ".wma", "audio/x-ms-wma" }, 
    { ".wmv", "audio/x-ms-wmv" }, 
    { ".wps", "application/vnd.ms-works" },
    { ".xml", "text/plain" }, 
    { ".z", "application/x-compress" }, 
    { ".zip", "application/x-zip-compressed" }, 
    { "", "*/*" } 
    };
}

最后补充一下,布局文件中的dimension是编译到jar包里面去了的,没有jar包的童鞋可以改成自己定义大小。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网