2015年的Android案例之旅
案例九:文件管理器
知识点:
- 功能设计到手机文件、SD卡文件的增删改查功能,目前实现了增查。。
- JAVA中对文件的操作
- Adapter的使用,无论是SimpleAdapter,还是BaseAdapter
- AlertDialog的使用
- 还有一些监听事件的使用
涉及文件:
- res->layout->main.xml主界面布局文件
- res->layout->item_toolbar.xml适配器布局文件,用于菜单选项
- res->layout->list_child.xml 适配器布局文件,用于显示文件列表
- res->layout->create_dialog.xml弹出框布局文件,用于创建文件或文件夹
- res->layout->search_dialog.xml弹出框布局文件,用于搜索文件
- res-layout->AndroidManifest.xml系统清单文件,主要申明涉及组件,权限
- src->package->MainActivity.javajava文件
- src->package->FileService.javajava文件
- src->package->SearcgBroadCast.javajava文件
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"); } }}
- 1楼jdsjlzx昨天 15:55
- 缺乏图片啊
- Re: w324821962昨天 16:15
- 回复jdsjlzxn嗯 后续的案例我会把效果图一起放上来