我的Android案例—文件管理器

2015年的Android案例之旅

案例九:文件管理器

知识点:
  1. 功能设计到手机文件、SD卡文件的增删改查功能,目前实现了增查。。
  2. JAVA中对文件的操作
  3. Adapter的使用,无论是SimpleAdapter,还是BaseAdapter
  4. AlertDialog的使用
  5. 还有一些监听事件的使用
涉及文件:
  1. res->layout->main.xml
    主界面布局文件
  2. res->layout->item_toolbar.xml
    适配器布局文件,用于菜单选项
  3. res->layout->list_child.xml
      适配器布局文件,用于显示文件列表
  4. res->layout->create_dialog.xml
    弹出框布局文件,用于创建文件或文件夹
  5. res->layout->search_dialog.xml
    弹出框布局文件,用于搜索文件
  6. res-layout->AndroidManifest.xml
    系统清单文件,主要申明涉及组件,权限
  7. src->package->MainActivity.java
    java文件
  8. src->package->FileService.java
    java文件
  9. src->package->SearcgBroadCast.java
    java文件
main.xml
<!-- 相对布局
	 -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/background">

    <!--文本控件
    显示当前路径 -->
    <TextView
        android:id="@+id/show"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:singleLine="true"/>

    <!-- 列表视图
    显示当前目录的内容 -->
    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/show"
        android:divider="@drawable/line"
        android:cacheColorHint="#000"
        android:layout_marginBottom="70dp"></ListView>

    <!-- 网格视图
    显示菜单,创建、修改等菜单项 -->
    <GridView
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"></GridView>
</RelativeLayout>
item_toolbar.xml
<!-- 菜单适配器布局 -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/toolbar_item"
    android:paddingBottom="5dp">

    <!-- 图片控件
    	用于显示菜单图片 -->
    <ImageView
        android:id="@+id/toolbarImage"
        android:layout_width="wrap_content"
        android:layout_height="45dp"
        android:layout_centerHorizontal="true"
        />

    <!-- 文本控件
    	用于显示菜单文字 -->
    	<TextView
    	    android:id="@+id/toolbarTitle"
    	    android:layout_width="wrap_content"
    	    android:layout_height="wrap_content"
    	    android:layout_below="@+id/toolbarImage"
    	    android:layout_centerHorizontal="true"
    	    android:textColor="#fff"/>
</RelativeLayout>
list_child.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="38dp"
    android:layout_gravity="left|center">

    <!-- 图标 -->
    <ImageView
        android:id="@+id/image_list_child"
        android:layout_width="40dip"
        android:layout_height="40dip"/>"
    <!-- 文本 -->
    <TextView
        android:id="@+id/text_list_child"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:singleLine="true"
        android:ellipsize="marquee"
        android:marqueeRepeatLimit="marquee_forever"/>
</LinearLayout>
create_dialog.xml
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical" >
  <!-- 二选一 -->
<RadioGroup
	android:id="@+id/radiogroup_create"
	android:layout_width="fill_parent"
	android:layout_height="wrap_content">
	<!-- 创建文件选项 -->
	<RadioButton
	android:layout_height="wrap_content"
	android:layout_width="fill_parent"
	android:text="创建文件夹"
	android:id="@+id/create_file" />
	<!-- 创建文件夹选项 -->
	<RadioButton
	android:layout_height="wrap_content"
	android:layout_width="fill_parent"
	android:text="创建文件"
	android:id="@+id/create_folder" />
</RadioGroup>
	<!-- 文本框,供用户填写文件名称 -->
	<EditText
	android:layout_height="wrap_content"
	android:id="@+id/new_filename"
	android:layout_width="fill_parent"
	android:hint="请输入名称"
	android:singleLine="true" />
</LinearLayout>
search_dialog.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <!-- 单选列表
    	用于判断搜索范围 -->
    <RadioGroup
        android:id="@+id/radiogroup_search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <!-- 当前路径下搜索 -->
        <RadioButton
            android:id="@+id/radio_currentpath"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="在当前路径下搜索"/>
        <!-- 在整个目录下搜索 -->
        <RadioButton
            android:id="@+id/radio_wholepath"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="在整个目录下搜索"/>
    </RadioGroup>
    <EditText
        android:id="@+id/edit_search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入搜索关键字"
        android:singleLine="true"/>
</LinearLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- 系统清单文件
	声明版本号,所包含组件等等 -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.filemanager.myfilemanager"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.filemanager.myfilemanager.MainActivity"
            android:label="@string/app_name" >
            <!-- 程序入口声明 -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".FileService">
			<intent-filter>
				<action android:name="com.android.service.FILE_SEARCH_START" />
				<category android:name="android.intent.category.DEFAULT" />
			</intent-filter>
		</service>
    </application>

    <!-- 对SD卡读写的权限 -->
    <uses-permission  android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <uses-permission  android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
</manifest>
MainActivity.java
public class MainActivity extends Activity {

	//定义Log标签
	private static final String TAG = "FILEMANAGER";
	private String mAction;
	//声明成员变量
	private TextView show;
	private ListView list;
	private GridView toolbar;
	private boolean isAddBackUp = false;
	// 代表手机或SD卡,1代表手机,2代表SD卡
	private int position = 1;
	//手机起始目录“/”
	private String mRootPath = java.io.File.separator;
	// SD卡根目录
	private String mSDCard = Environment.getExternalStorageDirectory().toString();
	//用静态变量存储 当前目录路径信息
    public static String mCurrentFilePath = "";
    //文件列表
  	List<String> mFileName;
  	//文件路径列表
  	List<String> mFilePath;
	//菜单项对应的图片和文字
	private int[] toolbarImage = {R.drawable.menu_phone,R.drawable.menu_sdcard,R.drawable.menu_search,
							R.drawable.menu_create,R.drawable.menu_palse,R.drawable.menu_exit};
	private String[] toolbarTitle = {"手机","SD卡","搜索","创建","黏贴","退出"};
	//显示搜索的区域  1:当前路径  2:整个目录
	private int mRadioChecked;
	//搜索内容
	private String keyWords;

	//BroadCastReceiver的标识
	public static final String KEYWORD_BROADCAST = "com.filemanager.file.KEYWORD_BROADCAST";
	//标识是否取消搜索
	public static boolean isComeBackFromNotification = false;
	//标识创建文件还是创建文件夹	1标识文件,2标识文件夹
	private static int mChecked;
	private String mNewFolderName = "";
	private File mCreateFile;

	//黏贴文件的新和旧路径
	private String mOldFilePath = "";
	private String mNewFilePath = "";
	private boolean isCopy = false;
	private String mCopyFileName;

	//程序创建
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		Log.i(TAG, "test------ FILEMANAGER is oncreate");
		//初始化菜单视图
		initGridViewData();
		//初始化菜单监听器
		initToolbarListener();
		show = (TextView)findViewById(R.id.show);
		//一开始程序的时候加载手机目录下的文件列表
		initFileListInfo(mRootPath);
		//初始化列表监听事件
		initListListener();

	}

	/**
	 * @param	初始化菜单视图
	 */
	private void initGridViewData(){
		toolbar = (GridView)this.findViewById(R.id.toolbar);
		//设置背景图片
		toolbar.setBackgroundResource(R.drawable.menu_background);
		//设置点击时的背景图片
		toolbar.setSelector(R.drawable.menu_item_selected);
		//设置列数
		toolbar.setNumColumns(6);
		//设置居中对齐
		toolbar.setGravity(Gravity.CENTER);
		 //设置水平,垂直间距为10
		toolbar.setVerticalSpacing(10);
		toolbar.setHorizontalSpacing(10);
		//添加适配器
		toolbar.setAdapter(getToolbarAdapter(toolbarTitle,toolbarImage));
	}

	/**
	 * @param	菜单适配器
	 * @return
	 */
	private SimpleAdapter getToolbarAdapter(String[] toolbarTitle,int[] toolbarImage){
		ArrayList<HashMap<String,Object>> mData = new ArrayList<HashMap<String,Object>>();
		for(int i = 0; i < toolbarTitle.length; i++){
			HashMap<String,Object> map = new HashMap<String,Object>();
			//将“image”映射成图片资源
			map.put("image", toolbarImage[i]);
			//将“title”映射成标题
			map.put("title", toolbarTitle[i]);
			mData.add(map);
		}
		//新建简单适配器,设置适配器的布局文件,映射关系
		return new SimpleAdapter(this, mData, R.layout.item_toolbar, new String[]{"image","title"}, new int[]{R.id.toolbarImage,R.id.toolbarTitle});
	}

	/**
	 * @param	初始化监听事件
	 */
	private void initToolbarListener(){
		toolbar.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> arg0, View v, int code,
					long arg3) {
				switch(code){
					//手机文件目录
					case 0:
						position = 1;
						initFileListInfo(mRootPath);
						break;
					//SD卡目录
					case 1:
						position = 2;
						initFileListInfo(mSDCard);
						break;
					//搜索
					case 2:
						searchDilalog();
						break;
					//创建
					case 3:
						createFolder();
						break;
					//黏贴
					case 4:
						palseFile();
						break;
					//退出
					case 5:
						MainActivity.this.finish();
						break;
				}

			}
		});
	}

	/**
	 * @param	初始化目录内容
	 * @param path
	 */
	private void initFileListInfo(String filePath){
		isAddBackUp = false;
		mCurrentFilePath = filePath;
		//显示当前路径
		show.setText(filePath);
		//文件列表
		mFileName = new ArrayList<String>();
		//文件路径列表
		mFilePath = new ArrayList<String>();
		File mFile = new File(filePath);
		//遍历出该文件夹路径下的所有文件/文件夹
		File[] allFiles = mFile.listFiles();
		//只要当前路径不是手机根目录或者是sd卡根目录则显示“返回根目录”和“返回上一级”
		if(position == 1&&!mCurrentFilePath.equals(mRootPath)){
    		initAddBackUp(filePath,mRootPath);
    	}else if(position == 2&&!mCurrentFilePath.equals(mSDCard)){
        	initAddBackUp(filePath,mSDCard);
    	}
		/*将所有文件信息添加到集合中*/
		for(File mCurrentFile:allFiles){
    		mFileName.add(mCurrentFile.getName());
    		mFilePath.add(mCurrentFile.getPath());
    	}
		//适配数据
		list = (ListView)this.findViewById(R.id.list);
		list.setAdapter(new FileAdapter(MainActivity.this,mFileName,mFilePath));
	}

	 /*
	  * 根据点击“手机”还是“SD卡”来加“返回根目录”和“返回上一级”
	  */
    private void initAddBackUp(String filePath,String phone_sdcard){

    	if(!filePath.equals(phone_sdcard)){
    		/*列表项的第一项设置为返回根目录*/
    		mFileName.add("BacktoRoot");
    		mFilePath.add(phone_sdcard);
    		/*列表项的第二项设置为返回上一级*/
    		mFileName.add("BacktoUp");
    		//回到当前目录的父目录即回到上级
    		mFilePath.add(new File(filePath).getParent());
    		//将添加返回按键标识位置为true
    		isAddBackUp = true;
    	}

    }

    //自定义Adapter内部类
    class FileAdapter extends BaseAdapter{
    	//返回键,各种格式的文件的图标
    	private Bitmap mBackRoot;
    	private Bitmap mBackUp;
    	private Bitmap mImage;
    	private Bitmap mAudio;
    	private Bitmap mRar;
    	private Bitmap mVideo;
    	private Bitmap mFolder;
    	private Bitmap mApk;
    	private Bitmap mOthers;
    	private Bitmap mTxt;
    	private Bitmap mWeb;

    	private Context mContext;
    	//文件名列表
    	private List<String> mFileNameList;
    	//文件对应的路径列表
    	private List<String> mFilePathList;

    	public FileAdapter(Context context,List<String> fileName,List<String> filePath){
    		mContext = context;
    		mFileNameList = fileName;
    		mFilePathList = filePath;
    		//初始化图片资源
    		//返回到根目录
    		mBackRoot = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.back_to_root);
    		//返回到上一级目录
    		mBackUp = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.back_to_up);
    		//图片文件对应的icon
    		mImage = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.image);
    		//音频文件对应的icon
    		mAudio = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.audio);
    		//视频文件对应的icon
    		mVideo = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.video);
    		//可执行文件对应的icon
    		mApk = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.apk);
    		//文本文档对应的icon
    		mTxt = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.txt);
    		//其他类型文件对应的icon
    		mOthers = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.others);
    		//文件夹对应的icon
    		mFolder = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.folder);
    		//zip文件对应的icon
    		mRar = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.zip_icon);
    		//网页文件对应的icon
    		mWeb = BitmapFactory.decodeResource(mContext.getResources(),R.drawable.web_browser);
    	}

    	//获得文件的总数
		@Override
		public int getCount() {
			return mFilePathList.size();
		}

		//获得当前位置对应的文件名
		@Override
		public Object getItem(int position) {
			return mFileNameList.get(position);
		}

		//获得当前的位置
		@Override
		public long getItemId(int position) {
			return position;
		}

		//获得视图
		@Override
		public View getView(int position, View convertView, ViewGroup viewgroup) {
			ViewHolder viewHolder = null;
			if (convertView == null) {
				viewHolder = new ViewHolder();
				LayoutInflater mLI = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				//初始化列表元素界面
				convertView = mLI.inflate(R.layout.list_child, null);
				//获取列表布局界面元素
				viewHolder.mIV = (ImageView)convertView.findViewById(R.id.image_list_child);
				viewHolder.mTV = (TextView)convertView.findViewById(R.id.text_list_child);
				//将每一行的元素集合设置成标签
				convertView.setTag(viewHolder);
			} else {
				//获取视图标签
				viewHolder = (ViewHolder) convertView.getTag();
			}
			File mFile = new File(mFilePathList.get(position).toString());
			//如果
			if(mFileNameList.get(position).toString().equals("BacktoRoot")){
				//添加返回根目录的按钮
				viewHolder.mIV.setImageBitmap(mBackRoot);
				viewHolder.mTV.setText("返回根目录");
			}else if(mFileNameList.get(position).toString().equals("BacktoUp")){
				//添加返回上一级菜单的按钮
				viewHolder.mIV.setImageBitmap(mBackUp);
				viewHolder.mTV.setText("返回上一级");
			}else if(mFileNameList.get(position).toString().equals("BacktoSearchBefore")){
				//添加返回搜索之前目录的按钮
				viewHolder.mIV.setImageBitmap(mBackRoot);
				viewHolder.mTV.setText("返回搜索之前目录");
			}else{
				String fileName = mFile.getName();
				viewHolder.mTV.setText(fileName);
				if(mFile.isDirectory()){
					viewHolder.mIV.setImageBitmap(mFolder);
				}else{
			    	String fileEnds = fileName.substring(fileName.lastIndexOf(".")+1,fileName.length()).toLowerCase();//取出文件后缀名并转成小写
			    	if(fileEnds.equals("m4a")||fileEnds.equals("mp3")||fileEnds.equals("mid")||fileEnds.equals("xmf")||fileEnds.equals("ogg")||fileEnds.equals("wav")){
			    		viewHolder.mIV.setImageBitmap(mVideo);
			    	}else if(fileEnds.equals("3gp")||fileEnds.equals("mp4")){
			    		viewHolder.mIV.setImageBitmap(mAudio);
			    	}else if(fileEnds.equals("jpg")||fileEnds.equals("gif")||fileEnds.equals("png")||fileEnds.equals("jpeg")||fileEnds.equals("bmp")){
			    		viewHolder.mIV.setImageBitmap(mImage);
			    	}else if(fileEnds.equals("apk")){
			    		viewHolder.mIV.setImageBitmap(mApk);
			    	}else if(fileEnds.equals("txt")){
			    		viewHolder.mIV.setImageBitmap(mTxt);
			    	}else if(fileEnds.equals("zip")||fileEnds.equals("rar")){
			    		viewHolder.mIV.setImageBitmap(mRar);
			    	}else if(fileEnds.equals("html")||fileEnds.equals("htm")||fileEnds.equals("mht")){
			    		viewHolder.mIV.setImageBitmap(mWeb);
			    	}else {
			    		viewHolder.mIV.setImageBitmap(mOthers);
			    	}
				}
			}
			return convertView;
		}

		//用于存储列表每一行元素的图片和文本
		class ViewHolder {
				ImageView mIV;
				TextView mTV;
			}

    }

    Intent serviceIntent;
    /**
     * @param 搜索
     */
    private void searchDilalog(){
    	//用于确定是在当前目录搜索或者是在整个目录搜索的标志
    	mRadioChecked = 1;
    	//加载布局文件
    	LayoutInflater mLI = LayoutInflater.from(MainActivity.this);
    	final View mView = mLI.inflate(R.layout.search_dialog, null);
    	//获取单选表对象
    	RadioGroup rg = (RadioGroup)mView.findViewById(R.id.radiogroup_search);
    	final RadioButton mCurrentPathButton = (RadioButton)mView.findViewById(R.id.radio_currentpath);
    	final RadioButton mWholePathButton = (RadioButton)mView.findViewById(R.id.radio_wholepath);
    	//设置默认选择在当前路径搜索
    	mCurrentPathButton.setChecked(true);
    	rg.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(RadioGroup radiogroup, int checkId) {
				//当前路径的标志为1
				if(checkId == mCurrentPathButton.getId()){
					mRadioChecked = 1;
					//整个目录的标志为2
				}else if(checkId == mWholePathButton.getId()){
					mRadioChecked = 2;
				}

			}
		});

    	//AlertDialog
    	Builder builder =new AlertDialog.Builder(MainActivity.this)
    						.setTitle("搜索").setView(mView)
    						.setPositiveButton("确定", new OnClickListener() {

								@Override
								public void onClick(DialogInterface arg0, int arg1) {
									// 获取搜索框的内容
									keyWords = ((EditText)mView.findViewById(R.id.edit_search)).getText().toString();
									if(keyWords.length() == 0){
										Toast.makeText(MainActivity.this, "关键字不能为空", Toast.LENGTH_SHORT).show();
									}else{
										if(position == 1){
											show.setText(mRootPath);
										}else{
											show.setText(mSDCard);
										}
										//获取用户输入的关键字并发送广播-开始
										Intent keywordIntent = new Intent();
										keywordIntent.setAction(KEYWORD_BROADCAST);
										//传递搜索的范围区间:1.当前路径下搜索 2.SD卡下搜索
										if(mRadioChecked == 1){
											keywordIntent.putExtra("searchpath", mCurrentFilePath);
										}else{
											keywordIntent.putExtra("searchpath", mSDCard);
										}
										//传递关键字
										keywordIntent.putExtra("keyword", keyWords);
										//到这里为止是携带关键字信息并发送了广播,会在Service服务当中接收该广播并提取关键字进行搜索
										getApplicationContext().sendBroadcast(keywordIntent);
										//开启服务,启动搜索
										serviceIntent = new Intent("com.android.service.FILE_SEARCH_START");
										MainActivity.this.startService(serviceIntent);
										isComeBackFromNotification = false;
									}
								}
							})
							.setPositiveButton("取消", null);
    	builder.create().show();
    }

    class FileBroadcast extends BroadcastReceiver{

		@Override
		public void onReceive(Context context, Intent intent) {
			mAction = intent.getAction();
			//搜索完毕
			if(FileService.FILE_SEARCH_COMPLETED.equals(mAction)){
				mFileName = intent.getStringArrayListExtra("mFileNameList");
				mFilePath = intent.getStringArrayListExtra("mFilePathsList");
				Toast.makeText(MainActivity.this, "搜索完毕!", Toast.LENGTH_SHORT).show();
				//这里搜索完毕之后应该弹出一个弹出框提示用户要不要显示数据
				searchCompletedDialog("搜索完毕,是否马上显示结果?");
			}
			//点击通知栏跳转过来的广播
			else if(FileService.FILE_NOTIFICATION.equals(mAction)){
				String mNotification = intent.getStringExtra("notification");
				Toast.makeText(MainActivity.this, mNotification, Toast.LENGTH_LONG).show();
			}
			searchCompletedDialog("你确定要取消搜索吗?");
		}

    }

    //搜索完毕和点击通知过来时的提示框
    private void searchCompletedDialog(String message){
    	Builder searchDialog = new AlertDialog.Builder(MainActivity.this)
		.setTitle("提示")
		.setMessage(message)
		.setPositiveButton("确定", new OnClickListener(){
			public void onClick(DialogInterface dialog,int which) {
				//当弹出框时,需要对这个确定按钮进行一个判断,因为要对不同的情况做不同的处理(2种情况)
				// 1.搜索完毕
				// 2.取消搜索
				if(FileService.FILE_SEARCH_COMPLETED.equals(mAction)){
					if(mFileName.size() == 0){
			    		Toast.makeText(MainActivity.this, "无相关文件/文件夹!", Toast.LENGTH_SHORT).show();
			    		//清空列表
			    		list.setAdapter(new FileAdapter(MainActivity.this,mFileName,mFilePath));
			    	}else{
			    		//显示文件列表
			    		list.setAdapter(new FileAdapter(MainActivity.this,mFileName,mFilePath));
			    	}
				}else{
					//设置搜索标志为true,
					isComeBackFromNotification = true;
					//关闭服务,取消搜索
					getApplicationContext().stopService(serviceIntent);
				}
			}
		})
		.setNegativeButton("取消", null);
		searchDialog.create();
		searchDialog.show();
    }

    /**注册广播*/
    private IntentFilter mFilter;
    private FileBroadcast mFileBroadcast;
    private IntentFilter mIntentFilter;
	private SearcgBroadCast mServiceBroadCast;
	@Override
    protected void onStart() {
    	super.onStart();
    	mFilter = new IntentFilter();
    	mFilter.addAction(FileService.FILE_SEARCH_COMPLETED);
    	mFilter.addAction(FileService.FILE_NOTIFICATION);
    	mIntentFilter = new IntentFilter();
    	mIntentFilter.addAction(KEYWORD_BROADCAST);
    	if(mFileBroadcast == null){
    		mFileBroadcast = new FileBroadcast();
    	}
    	if(mServiceBroadCast == null){
    		mServiceBroadCast = new SearcgBroadCast();
    	}
    	//动态注册广播
    	this.registerReceiver(mFileBroadcast, mFilter);
    	this.registerReceiver(mServiceBroadCast, mIntentFilter);
    }

	/**注销广播*/
    @Override
	protected void onDestroy() {
		super.onDestroy();
		mFileName.clear();
		mFilePath.clear();
    	this.unregisterReceiver(mFileBroadcast);
    	this.unregisterReceiver(mServiceBroadCast);
	}

    /**创建文件夹的方法:当用户点击软件下面的创建菜单的时候,是在当前目录下创建的一个文件夹
     * 静态变量mCurrentFilePath存储的就是当前路径
     * java.io.File.separator是JAVA给我们提供的一个File类中的静态成员,它会根据系统的不同来创建分隔符
     * mNewFolderName正是我们要创建的新文件的名称,从EditText组件上得到的*/
    private void createFolder(){
    	//用于标识当前选中的是文件或者文件夹
    	mChecked = 2;
    	LayoutInflater mLI = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    	//初始化对话框布局
    	final LinearLayout mLL = (LinearLayout)mLI.inflate(R.layout.create_dialog, null);
    	RadioGroup mCreateRadioGroup = (RadioGroup)mLL.findViewById(R.id.radiogroup_create);
    	final RadioButton mCreateFileButton = (RadioButton)mLL.findViewById(R.id.create_file);
    	final RadioButton mCreateFolderButton = (RadioButton)mLL.findViewById(R.id.create_folder);
    	//设置默认为创建文件夹
    	mCreateFolderButton.setChecked(true);
    	//为按钮设置监听器
    	mCreateRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener(){
    		//当选择改变时触发
			public void onCheckedChanged(RadioGroup arg0, int arg1) {
				if(arg1 == mCreateFileButton.getId()){
					mChecked = 1;
				}else if(arg1 == mCreateFolderButton.getId()){
					mChecked = 2;
				}
			}
    	});
    	//显示对话框
    	Builder mBuilder = new AlertDialog.Builder(MainActivity.this)
    	.setTitle("新建")
    	.setView(mLL)
    	.setPositiveButton("创建", new DialogInterface.OnClickListener(){
			public void onClick(DialogInterface dialog, int which) {
				//或者用户输入的名称
				mNewFolderName = ((EditText)mLL.findViewById(R.id.new_filename)).getText().toString();
				if(mChecked == 1){
					try {
						mCreateFile = new File(mCurrentFilePath+java.io.File.separator+mNewFolderName+".txt");
						mCreateFile.createNewFile();
						//刷新当前目录文件列表
						initFileListInfo(mCurrentFilePath);
					} catch (IOException e) {
						Toast.makeText(MainActivity.this, "文件名拼接出错..!!", Toast.LENGTH_SHORT).show();
					}
				}else if(mChecked == 2){
					mCreateFile = new File(mCurrentFilePath+java.io.File.separator+mNewFolderName);
					if(!mCreateFile.exists()&&!mCreateFile.isDirectory()&&mNewFolderName.length() != 0){
						if(mCreateFile.mkdirs()){
							//刷新当前目录文件列表
							initFileListInfo(mCurrentFilePath);
						}else{
							Toast.makeText(MainActivity.this, "创建失败,可能是系统权限不够,root一下?!", Toast.LENGTH_SHORT).show();
						}
					}else{
						Toast.makeText(MainActivity.this, "文件名为空,还是重名了呢?", Toast.LENGTH_SHORT).show();
					}
				}
			}
    	}).setNeutralButton("取消", null);
    	mBuilder.show();
    }

    /**
     * @param 黏贴
     */
    private void palseFile(){
    	mNewFilePath = mCurrentFilePath+java.io.File.separator+mCopyFileName;//得到新路径
		if(!mOldFilePath.equals(mNewFilePath)&&isCopy == true){//在不同路径下复制才起效
			if(!new File(mNewFilePath).exists()){
				copyFile(mOldFilePath,mNewFilePath);
				Toast.makeText(MainActivity.this, "执行了粘贴", Toast.LENGTH_SHORT).show();
				initFileListInfo(mCurrentFilePath);
			}else{
				new AlertDialog.Builder(MainActivity.this)
				.setTitle("提示!")
				.setMessage("该文件名已存在,是否要覆盖?")
				.setPositiveButton("确定", new DialogInterface.OnClickListener(){
					public void onClick(DialogInterface dialog,int which){
						copyFile(mOldFilePath,mNewFilePath);
						initFileListInfo(mCurrentFilePath);
					}
				})
				.setNegativeButton("取消", null).show();
			}
		}else{
			Toast.makeText(MainActivity.this, "未复制文件!", Toast.LENGTH_LONG).show();
		}
    }

    private int i;
    FileInputStream fis;
	FileOutputStream fos;
    //复制文件
    private void copyFile(String oldFile,String newFile){
    	try {
			fis =  new FileInputStream(oldFile);
			fos = new FileOutputStream(newFile);
			do{
				//逐个byte读取文件,并写入另一个文件中
				if((i = fis.read()) != -1){
					fos.write(i);
				}
			}while(i != -1);
			//关闭输入文件流
			if(fis != null){
				fis.close();
			}
			//关闭输出文件流
			if(fos != null){
				fos.close();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
    }

    /**长按文件或文件夹时弹出的带ListView效果的功能菜单*/
	private void initItemLongClickListener(final File file){
		OnClickListener listener = new DialogInterface.OnClickListener(){
			//item的值就是从0开始的索引值(从列表的第一项开始)
			public void onClick(DialogInterface dialog, int item) {
				if(file.canRead()){//注意,所有对文件的操作必须是在该文件可读的情况下才可以,否则报错
					if(item == 0){//复制
						if(file.isFile()&&"txt".equals((file.getName().substring(file.getName().lastIndexOf(".")+1, file.getName().length())).toLowerCase())){
							Toast.makeText(MainActivity.this, "已复制!", Toast.LENGTH_SHORT).show();
							//复制标志位,表明已复制文件
							isCopy = true;
							//取得复制文件的名字
							mCopyFileName = file.getName();
							//记录复制文件的路径
							mOldFilePath = mCurrentFilePath+java.io.File.separator+mCopyFileName;
						}else{
							Toast.makeText(MainActivity.this, "对不起,目前只支持复制文本文件!", Toast.LENGTH_SHORT).show();
						}
					}
				}else{
					Toast.makeText(MainActivity.this, "对不起,您的访问权限不足!", Toast.LENGTH_SHORT).show();
				}
			}
    	};
		//列表项名称
    	String[] mMenu = {"复制","重命名","删除"};
    	//显示操作选择对话框
    	new AlertDialog.Builder(MainActivity.this)
    								.setTitle("请选择操作!")
    								.setItems(mMenu, listener)
    								.setPositiveButton("取消",null).show();

	}

	private void initListListener(){

		//这里还缺少单击打开文件和文件夹的功能。。。。

		//设置长按监听器
		list.setOnItemLongClickListener(new OnItemLongClickListener() {

			@Override
			public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
					int position, long arg3) {
				if(isAddBackUp == true){//说明存在返回根目录和返回上一级两列,接下来要对这两列进行屏蔽
					if(position != 0 && position != 1){
						initItemLongClickListener(new File(mFilePath.get(position)));
					}
				}
				if(mCurrentFilePath.equals(mRootPath)||mCurrentFilePath.equals(mSDCard)){
					initItemLongClickListener(new File(mFilePath.get(position)));
				}
				return false;
			}
		});
	}

}
FileService.java
/**
 * @param	用于后台搜索文件
 * @author Administrator
 *
 */
public class FileService extends Service{
	private Looper mLooper;
	private FileHandler mFileHandler;
	private ArrayList<String> mFileName = null;
	private ArrayList<String> mFilePaths = null;
	public static final String FILE_SEARCH_COMPLETED = "com.filemanager.file.FILE_SEARCH_COMPLETED";
	public static final String FILE_NOTIFICATION = "com.filemanager.file.FILE_NOTIFICATION";
	private int m = -1;
	public NotificationManager mNF;
	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}

	//创建服务
	@Override
	public void onCreate() {
		super.onCreate();
		//新建处理线程
		HandlerThread mHT = new HandlerThread("FileService",HandlerThread.NORM_PRIORITY);
		mHT.start();
		mLooper = mHT.getLooper();
		mFileHandler = new FileHandler(mLooper);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		//取消通知
		mNF.cancel(R.string.app_name);
	}

	@SuppressWarnings("deprecation")
	@Override
	public void onStart(Intent intent, int startId){
		super.onStart(intent, startId);
		mFileName = new ArrayList<String>();
		mFilePaths = new ArrayList<String>();
		mFileHandler.sendEmptyMessage(0);
		//发出通知表明正在进行搜索
		fileSearchNotification();
	}

	class FileHandler extends Handler{
		public FileHandler(Looper looper){
			super(looper);
		}
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			//在指定范围搜索
			initFileArray(new File(SearcgBroadCast.mServiceSearchPath));
			//当用户点击了取消搜索则不发生广播
			if(!MainActivity.isComeBackFromNotification == true){
				Intent intent = new Intent(FILE_SEARCH_COMPLETED);
				intent.putStringArrayListExtra("mFileNameList", mFileName);
				intent.putStringArrayListExtra("mFilePathsList", mFilePaths);
				//搜索完毕之后携带数据并发送广播
				sendBroadcast(intent);
			}
		}
	}

    /**具体做搜索事件的可回调函数*/
    private void initFileArray(File file){
    	Log.d("FileService", "currentArray is "+file.getPath());
    	//只能遍历可读的文件夹,否则会报错
    	if(file.canRead()){
    		File[] mFileArray = file.listFiles();
        	for(File currentArray:mFileArray){
        		if(currentArray.getName().indexOf(SearcgBroadCast.mServiceKeyword) != -1){
        			if (m == -1) {
						m++;
						// 返回搜索之前目录
						mFileName.add("BacktoSearchBefore");
						mFilePaths.add(MainActivity.mCurrentFilePath);
					}
        			mFileName.add(currentArray.getName());
        			mFilePaths.add(currentArray.getPath());
        		}
        		//如果是文件夹则回调该方法
        		if(currentArray.exists()&¤tArray.isDirectory()){
        			//如果用户取消了搜索,应该停止搜索的过程
        			if(MainActivity.isComeBackFromNotification == true){
        				return;
        			}
        			initFileArray(currentArray);
        		}
        	}
    	}
    }    

    /**通知*/
    private void fileSearchNotification(){
    	Notification mNotification = new Notification(R.drawable.logo,"后台搜索中...",System.currentTimeMillis());
    	Intent intent = new Intent(FILE_NOTIFICATION);
    	//打开notice时的提示内容
    	intent.putExtra("notification", "当通知还存在,说明搜索未完成,可以在这里触发一个事件,当点击通知回到Activity之后,可以弹出一个框,提示是否取消搜索!");
    	PendingIntent mPI = PendingIntent.getBroadcast(this,0,intent,0);
    	mNotification.setLatestEventInfo(this, "在"+SearcgBroadCast.mServiceSearchPath+"下搜索", "搜索关键字为"+SearcgBroadCast.mServiceKeyword+"【点击可取消搜索】", mPI);
    	if(mNF == null){
    		mNF = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
    	}
    	mNF.notify(R.string.app_name, mNotification);
    }
}
SearcgBroadCast.java
public class SearcgBroadCast extends BroadcastReceiver{

	//接收搜索关键字的静态变量
	public static  String mServiceKeyword = "";
	//接收搜索路径的静态变量
    public static  String mServiceSearchPath = "";
	@Override
	public void onReceive(Context context, Intent intent) {
		//取得intent
		String mAction = intent.getAction();
		if(MainActivity.KEYWORD_BROADCAST.equals(mAction)){
			//取得intent传递过来的信息
			mServiceKeyword = intent.getStringExtra("keyword");
			mServiceSearchPath = intent.getStringExtra("searchpath");
		}

	}

}
时间: 2024-08-02 23:59:13

我的Android案例—文件管理器的相关文章

Android文件管理器项目(三)

? 一句话分享:觉得食物不好吃就不要吃,因为大脑会记住这个味道,从而让你形成习惯,越来越糟. 概述:写到这里我已经开始怀疑这个项目是不是文件管理器项目了--我只是看了看 GitHub 这个项目的主页的几张图片,貌似只是一个查看pdf和doc 文档的项目.这就是英语不好又没有去翻译的错吧.目前还剩下一个 fragment 类没有处理了.而这个没有处理的类里面的方法名我已经写出来了. 吐槽一下 : 原项目写的真是糟糕啊.全部挤在一起成一块,内部类,内部接口,这些东西还不止一个. 我一直反感这种写法,

Android 文件管理器项目(一)

? 开场白:最近领悟到不能总是学习什么小的知识点,应该全局去思考一下.所以就去找开源项目,然后找到了这个文件管理器的项目.看了源码,其实也说不上是管理吧,毕竟很简单.但好歹是一个完整的项目.界面也非常漂亮,并且没有用什么图片资源,非常适合自学. 上链接,有兴趣的同学可以去看一些,几个月前最后更新,看来修改幅度不大了. https://github.com/dibakarece/AndroidFileExplorer 今晚就写了res下面那些文件,因为在编写逻辑的时候如果资源文件夹没有的话,会非常

XC文件管理器(Android应用)

XC文件管理器,是基于Android4.4开发的一个方便易用的文件管理器,具有文件的目录管理和文件的管理,主要包括文件的新建.删除.重命名.复制,移动剪切以及文件详情查看等文件和目录的功能,同时支持文件和目录的批量管理,应该功能较全,视图提供两种:网格视图以及列表视图,应用界面简洁美观,易用性强,是较好易用的一款Android文件管理应用. 下载地址:http://download.csdn.net/detail/jczmdeveloper/7364093 应用截图如下: XC文件管理器(And

发现一个好用的Android文件访问工具--es文件管理器,可以在同局域网下的浏览器中查看手机中的文件

如题,发现一个好用的Android文件访问工具--es文件管理器,可以在同局域网下的浏览器中查看手机中的文件 1.在手机上打开es文件管理器的远程管理器,如图:                   2.保证手机和电脑在同一个局域网下(有线或者Wifi都可以) 贴一下我的地址: (1)我电脑的IP地址(有线宽带连接): (2)手机的地址(Wifi): 3.在别的手机或者电脑上打开上面的Url(我的是:ftp://192.168.1.115:3721/),打开后就是这样的: 3. 看一下刚才在手机上

Android调用系统自带的文件管理器进行文件选择

http://blog.csdn.net/zqchn/article/details/8770913的补充 FileUtils文件 public class FileUtils {     public static String getPath(Context context, Uri uri) {         if ("content".equalsIgnoreCase(uri.getScheme())) {             String[] projection =

android XML解析器全解案例

1.使用pull解析 1 package com.example.myxml; 2 3 import java.io.InputStream; 4 import java.util.ArrayList; 5 import java.util.List; 6 7 import org.xmlpull.v1.XmlPullParser; 8 import org.xmlpull.v1.XmlPullParserFactory; 9 10 import android.util.Log; 11 imp

Android MediaProvider--文件管理:必现,文件管理器中新建几个文件夹,批量删除后,连接电脑查看仍有部分文件夹未删除

问题描述: [测试步骤]:1.进入文件管理器中,新建几个文件夹,然后批量全选这些文件夹--删除: 2.手机连接电脑,在电脑端查看文件显示. [测试结果]:电脑端查看仍有部分文件夹未删除.插拔USB线几次,在电脑端重新查看,仍显示. [预期结果]:电脑端不应显示已删除的文件夹. [复现概率]:100%(若第一次未复现,步骤1.2重新操作即可复现) [备注]:在文件管理中点击"搜索",也能搜索出这些文件夹. 按以下步骤更容易复现 1.添加一个本地文件夹,删除新添加的文件夹 2.再新建另一文

解决Android Studio 将String类型保存为.txt文件,按下button跳转到文件管理器(解决了保存txt文件到文件管理后,手机打开是乱码的问题)

不知道为什么保存文件后之前打开一直都OK,就突然打开看到变成乱码了,最后解决了 关键:outStream.write(finalContent.getBytes("gbk")); write的时候设置一下:转换格式(UFT-8在android不能用,只能用gbk)!!!我之前试过utf-8,还是乱码,没什么用,就是gbk! 从项目里面抽取了这个把String保存为txt到本地的方法: String sdCardDir =Environment.getExternalStorageDir

小米开源文件管理器MiCodeFileExplorer初步研究

2011年对着书本Android应用开发揭秘,写了2个月的HelloWorld. 现在想复习并深入,我没有耐心再去一点点地敲代码了. 4年前自己是个学生,实习,现在有工作,只能业余时间研究. 这一点是非常不同的. 我希望通过研究别人的"成熟产品",更好地全面学习. 以目标为导向,具体来说,通过研究别人的一个产品,进而全面掌握,在研究的过程中, 把若干问题都解决了,从而达成"快速进步"的目标. 我们学习Java,学习Android开发,不是为了玩玩而已,也不能紧紧是&