android文件管理器用法详解
很久没有写东西了,鉴于某某同学文件管理器不会,这里简单介绍一下,同时写一个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包的童鞋可以改成自己定义大小。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: Android 媒体库数据更新方法总结
下一篇: 你别在这拉啊!