概述:
需求:显示手机内所有文件、文件夹,显示文件内容,对文件拷贝、删除等。
实现:遍历文件,显示文件信息到ListView中;读取文件,显示到界面上;ListView添加菜单,处理文件操作。
扩展:自定义Activity标题栏,创建后台服务播放MP3文件。
代码:
<span style="font-family:Microsoft YaHei;font-size:12px;">public class MainActivity extends Activity {
public static final int MENU_ID_BASE = 0;
@Override
public boolean onContextItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch( item.getItemId() ){
case MENU_ID_BASE+1://删除
Toast.makeText(this, "删除文件", Toast.LENGTH_LONG).show();
break;
case MENU_ID_BASE+2://复制
Toast.makeText(this, "复制文件", Toast.LENGTH_LONG).show();
break;
case MENU_ID_BASE+3://重命名
Toast.makeText(this, "重命名文件", Toast.LENGTH_LONG).show();
break;
}
return super.onContextItemSelected(item);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if ( keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN ){
if ( !isRoot() ){
goBack();
return true;
}
}
return super.onKeyDown(keyCode, event);
}
private ListView m_lv = null;
private TouchCallback m_tcb = null;
private ArrayList<File> m_files = new ArrayList<File>();
private String m_strDir = "./";
private TextView m_tvFile = null;
private OnItemLongClickListenerEx mItemLclickCb = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
m_lv = (ListView)findViewById(R.id.lv1);
m_tvFile = (TextView)findViewById(R.id.tv_file);
m_tcb = new TouchCallback();
mItemLclickCb = new OnItemLongClickListenerEx();
m_tcb.setMainActivity(this);
m_lv.setOnItemClickListener(m_tcb);
mItemLclickCb.SetActivity(this);
mItemLclickCb.SetListView(m_lv);
m_lv.setOnItemLongClickListener(mItemLclickCb);
//m_lv.setOnClickListener(m_tcb);
//生成动态数组,加入数据
File fRoot = new File(m_strDir);
AddFiles(fRoot);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public class MyMapComparator implements Comparator{
@Override
public int compare(Object lhs, Object rhs) {
// TODO Auto-generated method stub
HashMap<String, Object> o1 = (HashMap<String, Object>)lhs;
HashMap<String, Object> o2 = (HashMap<String, Object>)rhs;
String strName1 = (String) o1.get("name");
String strName2 = (String) o2.get("name");
return strName1.compareTo(strName2);
}
}
public class MyFileComparator implements Comparator{
@Override
public int compare(Object lhs, Object rhs) {
// TODO Auto-generated method stub
File o1 = (File)lhs;
File o2 = (File)rhs;
String strName1 = (String) o1.getName();
String strName2 = (String) o2.getName();
return strName1.compareTo(strName2);
}
}
public void AddFiles(File f){
if ( f.isFile() ){
showFileDlg(f);
return ;
}
File[] fs = f.listFiles();
if ( fs == null || fs.length == 0 ){
Toast.makeText(this, "没有权限", Toast.LENGTH_LONG).show();
return ;
}
m_files.clear();
m_strDir = f.getPath();
if ( isRoot() )
m_tvFile.setText(R.string.text_root);
else
m_tvFile.setText(m_strDir);
for(File f1:fs)
m_files.add(f1);
//Arrays.sort(m_files);
Collections.sort(m_files, new MyFileComparator());
ArrayList<HashMap<String, Object>> listItem = new ArrayList<HashMap<String, Object>>();
for ( File f1:m_files ){
HashMap<String, Object> map = new HashMap<String, Object>();
String strName = f1.getName();
if ( f1.isDirectory() )
map.put("image", R.drawable.dir);
else
{
map.put("image", getFileImgId(strName));
}
map.put("attrs", GetFileAttrs(f1));
map.put("name", strName);
listItem.add(map);
}
SimpleAdapter sa = new SimpleAdapter(this, listItem, R.layout.lv1, new String[] {"image", "attrs", "name"},
new int[]{R.id.iv, R.id.tv1, R.id.tv2});
m_lv.setAdapter(sa);
}
public String GetFileAttrs(File f){
String str = "";
if ( f.canRead() )
str += "读 ";
if ( f.canWrite() )
str += "写 ";
if ( f.canExecute() )
str += "执行";
if ( str.isEmpty() )
str = "无权限";
return str;
}
public File GetFileByIndex(int nIndex){
if ( m_files == null )
return null;
int nCount = m_files.size();
if ( nIndex<0 || nIndex>=nCount )
return null;
return m_files.get(nIndex);
}
public boolean isRoot(){
if ( (m_strDir.compareTo(".") == 0) || (m_strDir.compareTo("./") == 0) )
return true;
return false;
}
public void goBack(){
if ( isRoot() ){
return ;
}
int nPos = m_strDir.lastIndexOf("/");
String str = m_strDir.substring(0, nPos);
File f = new File(str);
AddFiles(f);
}
public int getFileImgId(String strFile){
int nPos = strFile.lastIndexOf(".");
if ( nPos == -1 || nPos == strFile.length()-1 )
return R.drawable.file;
int nPos1 = strFile.lastIndexOf("/");
if ( nPos1 > nPos )
return R.drawable.file;
String strExt = strFile.substring(nPos+1);
if ( strExt.compareToIgnoreCase("xml") == 0 )
return R.drawable.xml;
if ( strExt.compareToIgnoreCase("mp3") == 0 )
return R.drawable.mp3;
if ( strExt.compareToIgnoreCase("bat") == 0 )
return R.drawable.bat;
if ( strExt.compareToIgnoreCase("rc") == 0 )
return R.drawable.rc;
if ( strExt.compareToIgnoreCase("db") == 0 )
return R.drawable.db;
if ( strExt.compareToIgnoreCase("doc") == 0 )
return R.drawable.doc;
if ( strExt.compareToIgnoreCase("gif") == 0 )
return R.drawable.gif;
if ( strExt.compareToIgnoreCase("ico") == 0 )
return R.drawable.ico;
if ( strExt.compareToIgnoreCase("jpg") == 0
|| strExt.compareToIgnoreCase("jpeg") == 0
|| strExt.compareToIgnoreCase("bmp") == 0 )
return R.drawable.jpg;
if ( strExt.compareToIgnoreCase("png") == 0 )
return R.drawable.png;
return R.drawable.file;
}
public void showFileDlg(File f) {
Intent in = new Intent(this, FileActivity.class);
//Bundle b = new Bundle();
//b.putString("filename", f.getPath());
in.putExtra("filename", f.getPath());
//in.putExtras(b);
startActivity(in);
}
}</span>
因为要对遍历的文件按照字母顺序排序,自定义一个比较类MyFileComparator;根据文件的扩展名设置ListView中显示的图标;点击ListView时,如果是文件夹则遍历并将列表清空后添加新的列表。对于文件,则显示文件的部分内容(因为有的问价很大,加载完会把程序卡死),显示文件内容的Activity代码:
<span style="font-family:Microsoft YaHei;font-size:12px;">public class FileActivity extends Activity{
private TextView m_tv = null;
private MediaPlayer m_mp = null;
private Intent m_it = new Intent("com.demo.SERVICE_PLAYER");
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.titlebar);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.titlebar);
TextView tv = (TextView)findViewById(R.id.title_text);
tv.setText("文件浏览");
tv.setTextSize(20);
tv = (TextView)findViewById(R.id.title_left_text);
tv.setText("标题");
tv.setTextSize(16);
Button btn = (Button)findViewById(R.id.title_back);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
finish();
}
});
setContentView(R.layout.file_xml);
m_tv = (TextView)findViewById(R.id.editText1);
Intent in = getIntent();
String strName = in.getStringExtra("filename");
File f = new File(strName);
long lSize = f.length();
if ( lSize > 1024*1024 ){
int nPos = strName.lastIndexOf('.');
if ( nPos != -1 ){
String strExt = strName.substring(nPos+1);
if ( strExt.compareToIgnoreCase("mp3") == 0 ){
m_it.putExtra("filename", strName);
startService(m_it);
Toast.makeText(this, "开始播放音乐", Toast.LENGTH_LONG).show();
return ;
}
}
Toast.makeText(this, "文件太大", Toast.LENGTH_LONG).show();
}
else
ReadFile(f);
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
if ( m_mp != null ){
m_mp.stop();
m_mp.release();
}
stopService(m_it);
super.onStop();
}
public void ReadFile(File f){
FileInputStream fis = null;
try {
fis = new FileInputStream(f);
StringBuilder sb = new StringBuilder();
int nBuffLen = 10*1024; //10KB
byte[] buff = new byte[nBuffLen];
while( true ){
int nRead = fis.read(buff);
if ( nRead<=0 )
break;
String str = new String(buff, 0, nRead);
sb.append(str);
if ( nRead<nBuffLen )
break;
}
m_tv.setText(sb.toString());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch( IOException e ) {
e.printStackTrace();
}
finally{
if ( fis != null )
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}</span>
对于MP3文件,点击时创建服务播放,服务代码:
<span style="font-family:Microsoft YaHei;font-size:12px;">public class PlayerService extends Service{
private static final String NAME = "PlayerService";
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
String strName = intent.getStringExtra("filename");
playMp3(strName);
Log.i(NAME, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
initPlayer();
super.onCreate();
Log.i(NAME, "onCreate");
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
if ( m_player!=null ){
m_player.stop();
m_player.release();
}
Log.i(NAME, "onDestroy");
super.onDestroy();
}
public void playMp3(String strName){
if ( m_player == null )
m_player = new MediaPlayer();
else
m_player.reset();
try {
m_player.setDataSource(strName);
m_player.prepare();
m_player.start();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void initPlayer(){
m_player = new MediaPlayer();
m_player.setOnCompletionListener(m_onCle);
m_player.setOnPreparedListener(m_onPle);
}
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
Log.i(NAME, "onBind");
String strName = arg0.getStringExtra("filename");
return null;
}
static public class OnCompletionListenerEx
implements OnCompletionListener{
@Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
}
}
static public class OnPreparedListenerEx
implements OnPreparedListener{
@Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
}
}
private MediaPlayer m_player = null;
private OnCompletionListenerEx m_onCle = new OnCompletionListenerEx();
private OnPreparedListenerEx m_onPle = new OnPreparedListenerEx();
}</span>
<span style="font-family:Microsoft YaHei;font-size:12px;">
</span>
自定义标题栏方法:
<span style="font-family:Microsoft YaHei;font-size:12px;"><span style="white-space:pre">在</span>Activity的onCreate中设置自己的标题栏布局<span style="white-space:pre"></span></span><pre name="code" class="java">super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.titlebar);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.titlebar);
在styles.xml中添加自定义主题样式
<span style="font-family:Microsoft YaHei;font-size:12px;"> <style name="MyCustomTheme" parent="android:Theme">
<item name="android:windowBackground">@android:color/background_dark</item>
<item name="android:windowTitleSize">50dp</item>
</style></span>
然后在AndroidManifest.xml中设置自己的主题
<span style="font-family:Microsoft YaHei;font-size:12px;"><activity android:name=".FileActivity"
android:label="@string/text_file"
android:theme="@style/MyCustomTheme" >
</activity></span>
运行截图: