/** * 920 Text Editor is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 920 Text Editor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 920 Text Editor. If not, see <http://www.gnu.org/licenses/>. */ package com.jecelyin.util; import android.app.AlertDialog; import android.app.ListActivity; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.view.*; import android.view.ContextMenu.ContextMenuInfo; import android.view.View.OnClickListener; import android.widget.*; import com.jecelyin.editor.EditorSettings; import com.jecelyin.editor.EncodingList; import com.jecelyin.editor.JecApp; import com.jecelyin.editor.JecEditor; import com.jecelyin.editor.R; import com.jecelyin.widget.JecButton; import com.stericson.RootTools.RootTools; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; //import java.text.SimpleDateFormat; /** * 文件选择器 * * @author jecelyin * */ public class FileBrowser extends ListActivity { private ArrayList<File> files; //当前文件列表 private FileListAdapter fileListAdapter; private LinearLayout pathButtons; private String default_filename = ""; private int request_mode = 0; //0打开, 1保存模式,2选择路径 private String current_path = ""; //当前路径 private boolean isRoot = false; private EditText editTextFilename; private Intent mIntent; private Button saveButton; private Spinner linebreakSpinner; private Spinner encoding_list; private static int OPEN_WITH_CODE = 0; private int lastPos; public static final int MODE_BROWSE = 2; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); JecApp.addActivity(this); setContentView(R.layout.file_bowsers); getListView().setFastScrollEnabled(true); registerForContextMenu(getListView()); pathButtons = (LinearLayout)findViewById(R.id.pathButtons); editTextFilename = (EditText)findViewById(R.id.editTextFilename); saveButton = (Button)findViewById(R.id.btnSave); saveButton.setOnClickListener(onSaveBtnClickListener); linebreakSpinner = (Spinner)findViewById(R.id.linebreak_list); LinearLayout linebreakLinearLayout = (LinearLayout)findViewById(R.id.linebreakLinearLayout); LinearLayout encodingLinearLayout = (LinearLayout)findViewById(R.id.encodingLinearLayout); encoding_list = (Spinner)findViewById(R.id.encoding_list); String[] lists = EncodingList.list; lists[0] = getString(R.string.auto_detection); encoding_list.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, lists)); int position = 0; if(!"".equals(EditorSettings.DEFAULT_ENCODING)) for(int i=0; i<lists.length; i++) if(EditorSettings.DEFAULT_ENCODING.equals(lists[i])) { position = i; break; } encoding_list.setSelection(position); JecLog.d("pos="+position); File file = android.os.Environment.getExternalStorageDirectory(); current_path = EditorSettings.HIGHLIGHT_LAST_PATH.length()==0 ? file.getPath() : EditorSettings.HIGHLIGHT_LAST_PATH; //获取传来的数据 mIntent = getIntent(); default_filename = mIntent.getStringExtra("filename"); request_mode = mIntent.getIntExtra("mode", 0); isRoot = mIntent.getBooleanExtra("isRoot", false); editTextFilename.setText(default_filename); LinearLayout filenameLinearLayout = (LinearLayout)findViewById(R.id.filenameLinearLayout); if(request_mode == JecEditor.FILE_BROWSER_OPEN_CODE) { filenameLinearLayout.setVisibility(View.GONE); linebreakLinearLayout.setVisibility(View.VISIBLE); encodingLinearLayout.setVisibility(View.VISIBLE); } else if(request_mode == MODE_BROWSE) { LinearLayout okLinearLayout = (LinearLayout)findViewById(R.id.okLinearLayout); okLinearLayout.setVisibility(View.VISIBLE); filenameLinearLayout.setVisibility(View.GONE); linebreakLinearLayout.setVisibility(View.GONE); encodingLinearLayout.setVisibility(View.GONE); Button btnOK = (Button)findViewById(R.id.btnOK); btnOK.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mIntent.putExtra("path", current_path); setResult(RESULT_OK, mIntent); finish(); } }); } //requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); showFileList(new File(current_path)); } protected void onDestroy() { super.onDestroy(); JecApp.removeActivity(this); } private OnClickListener onSaveBtnClickListener = new OnClickListener() { @Override public void onClick(View v) { String filename = editTextFilename.getText().toString().trim(); if("".equals(filename)) { Toast.makeText(getApplicationContext(), R.string.filename_is_empty, Toast.LENGTH_LONG).show(); }else{ mIntent.putExtra("file", current_path+File.separator+filename); mIntent.putExtra("linebreak", linebreakSpinner.getSelectedItemPosition()); mIntent.putExtra("encoding", encoding_list.getSelectedItemPosition()); setResult(RESULT_OK, mIntent); finish(); } } }; @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); //打开方式... menu.add(0, R.string.open_with, 0, R.string.open_with); //重命名 menu.add(0, R.string.rename, 0, R.string.rename); //删除 menu.add(0, R.string.delete, 0, R.string.delete); //创建目录 menu.add(0, R.string.new_folder, 0, R.string.new_folder); } public boolean onContextItemSelected(MenuItem item) { AdapterView.AdapterContextMenuInfo info; try { info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); } catch (ClassCastException e) { return false; } int position = info.position; final File f; try { f = files.get(position); if(f == null) return false; } catch (Exception e) { return false; } lastPos = position; int itemId = item.getItemId(); switch(itemId) { case R.string.open_with: Uri uri = Uri.fromFile(f); try { if(f.isDirectory()) { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setDataAndType(uri, "file/*"); //startActivityForResult(intent, OPEN_WITH_CODE); startActivity(intent); } else { Intent it = new Intent(Intent.ACTION_VIEW); it.setDataAndType(uri, "*/*"); startActivity(it); } }catch (Exception e) { } return false; case R.string.rename: final EditText lineEditText = new EditText(this); lineEditText.setText(f.getName()); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.rename).setView(lineEditText) .setNegativeButton(android.R.string.cancel, null); builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { try { dialog.dismiss(); String newname = lineEditText.getText().toString().trim(); String newfile = f.getParent() + File.separator + newname; if("".equals(newname) || !f.renameTo(new File(newfile))) { Toast.makeText(FileBrowser.this, R.string.rename_failed, Toast.LENGTH_LONG).show(); } else { refresh(); } }catch(Exception e) { } } }); builder.show(); return true; case R.string.delete: new AlertDialog.Builder(this).setTitle(R.string.delete).setMessage(R.string.confirm_delete) .setNegativeButton(android.R.string.cancel, null) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { FileUtil.remove(f); refresh(); } }) .show(); return true; case R.string.new_folder: final EditText filenameEditText = new EditText(this); filenameEditText.setText(f.getName()); AlertDialog.Builder fbuilder = new AlertDialog.Builder(this); fbuilder.setTitle(R.string.new_folder).setView(filenameEditText) .setNegativeButton(android.R.string.cancel, null); fbuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { try { dialog.dismiss(); String newname = filenameEditText.getText().toString().trim(); String newfile = (f.isFile() ? f.getParent() : f.getPath()) + File.separator + newname; if("".equals(newname) || !(new File(newfile)).mkdirs()) { Toast.makeText(FileBrowser.this, R.string.create_folder_fail, Toast.LENGTH_LONG).show(); } else { refresh(); } }catch(Exception e) { } } }); fbuilder.show(); return true; } return super.onContextItemSelected(item); } @Override public void startActivityForResult (Intent intent, int requestCode) { if(requestCode == OPEN_WITH_CODE) { refresh(); return; } super.startActivityForResult(intent, requestCode); } public void refresh() { showFileList(new File(current_path)); } @Override public void finish() { //记住最后打开的路径 EditorSettings.setString("last_path", current_path); super.finish(); } /** * 显示文件列表 * * @param path */ private void showFileList(File path) { String curPath; try { curPath = path.getCanonicalPath(); }catch (IOException e) { curPath = path.getPath().replaceAll("/./", "/"); } //设置标题 setTitle(curPath); current_path = curPath; //处理顶部路径按钮 String[] paths=curPath.split(File.separator); JecButton mButton; StringBuilder mStringBuilder = new StringBuilder(); pathButtons.removeAllViews(); //始终显示根按钮 if(paths.length < 1) paths = new String[]{File.separator}; for(String p: paths) { mButton = new JecButton(this); if(p == null || "".equals(p)) { p = File.separator; } mButton.setText(p); mStringBuilder.append(File.separator).append(p); mButton.putString("path", mStringBuilder.toString()); mButton.setOnClickListener(new PathOnClickListener()); pathButtons.addView(mButton); } //不能读取的才开启ROOT权限访问 files = FileUtil.getFileList(curPath, isRoot && !path.canRead() && RootTools.isAccessGiven()); //path.listFiles(); if(files == null) { Toast.makeText(FileBrowser.this, R.string.can_not_list_file, Toast.LENGTH_LONG).show(); return; } try { fileListAdapter = new FileListAdapter(this, R.layout.file_list, files); setListAdapter(fileListAdapter); if(lastPos > 0) { if(files.size() > lastPos) { setSelection(lastPos); }else if(--lastPos < files.size()){ setSelection(lastPos); } } } catch(OutOfMemoryError ome) { Toast.makeText(FileBrowser.this, R.string.out_of_memory, Toast.LENGTH_LONG).show(); return; } } /* private Comparator<FileLists> comparator = new Comparator<FileLists>() { public int compare(FileLists fl1, FileLists fl2) { return fl1.file.getName().compareToIgnoreCase(fl2.file.getName()); } };*/ protected void onListItemClick(ListView listView, View view, int position, long id) { File file = fileListAdapter.getItem(position); if(file.isDirectory()) { showFileList(file); }else if(request_mode == MODE_BROWSE) {//same btnOK button mIntent.putExtra("path", file.getPath()); setResult(RESULT_OK, mIntent); finish(); }else { mIntent.putExtra("file", file.getPath()); mIntent.putExtra("linebreak", linebreakSpinner.getSelectedItemPosition()); mIntent.putExtra("encoding", encoding_list.getSelectedItemPosition()); setResult(RESULT_OK, mIntent); finish(); } } private class PathOnClickListener implements View.OnClickListener { public void onClick(View paramView) { JecButton mButton = (JecButton)paramView; FileBrowser.this.showFileList(new File(mButton.getString("path"))); } } } class FileListAdapter extends ArrayAdapter<File> { private LayoutInflater mInflater; private Bitmap mIcon_folder; private Bitmap mIcon_file; private Bitmap mIcon_image; private Bitmap mIcon_audio; private Bitmap mIcon_video; private Bitmap mIcon_apk; private ViewHolder holder; //各种类型图标 private String[] type_audio = { ".m4a", ".mp3", ".wma", ".mid", ".xmf", ".ogg", ".wav" }; private String[] type_video = { ".3gp", ".mp4", ".avi", ".rm", ".rmvb" }; private String[] type_image = { ".jpg", ".gif", ".png", ".bmp", ".jpeg" }; private String[] type_app = { ".apk" }; public FileListAdapter(Context context, int Resource,List<File> objects) { super(context,Resource,objects); mInflater = LayoutInflater.from(context); Resources res = context.getResources(); mIcon_folder = BitmapFactory.decodeResource(res, R.drawable.folder); // 文件夹的图文件 mIcon_file = BitmapFactory.decodeResource(res, R.drawable.file); // 文件的图文件 mIcon_image = BitmapFactory.decodeResource(res, R.drawable.image); // 图片的图文件 mIcon_audio = BitmapFactory.decodeResource(res, R.drawable.audio); // 音频的图文件 mIcon_video = BitmapFactory.decodeResource(res, R.drawable.video); // 视频的图文件 mIcon_apk = BitmapFactory.decodeResource(res, R.drawable.apk); // apk文件 } @Override public View getView(int position, View convertView, ViewGroup parent) { //Log.d("FileBrowser", (convertView==null ? "convertView==null" : "convertView!=null")); File file = getItem(position); String title = file.getName(); if(convertView == null) { /* 使用自定义的list_items作为Layout */ convertView = mInflater.inflate(R.layout.file_list, null); /* 初始化holder的text与icon */ holder = new ViewHolder(); holder.f_title = (TextView) convertView.findViewById(R.id.f_title); holder.f_text = (TextView) convertView.findViewById(R.id.f_text); holder.f_icon = (ImageView) convertView.findViewById(R.id.f_icon); convertView.setTag(holder); }else { holder = (ViewHolder) convertView.getTag(); } String f_type = getMimeType(file.getName()); holder.f_title.setText(title); if (file.isDirectory()) { holder.f_icon.setImageBitmap(mIcon_folder); } else { if ("image".equals(f_type)) { holder.f_icon.setImageBitmap(mIcon_image); } else if ("audio".equals(f_type)) { holder.f_icon.setImageBitmap(mIcon_audio); } else if ("video".equals(f_type)) { holder.f_icon.setImageBitmap(mIcon_video); } else if ("apk".equals(f_type)) { holder.f_icon.setImageBitmap(mIcon_apk); } else { holder.f_icon.setImageBitmap(mIcon_file); } } //底部内容 最后修改时间及大小 StringBuilder textStringBuilder = new StringBuilder(); //textStringBuilder.append((new SimpleDateFormat("yyyy-MM-dd hh:mm:ss")).format(new Date(file.lastModified()))) //.append(" "); if(!"..".equals(title)) textStringBuilder.append(TimeUtil.getDate(file.lastModified())).append(" "); //textStringBuilder.append(new Date(file.lastModified()).toLocaleString()).append(" "); if(file.length() > 0) textStringBuilder.append(FileUtil.byteCountToDisplaySize(file.length())); holder.f_text.setText(textStringBuilder.toString()); return convertView; } private class ViewHolder { public TextView f_title; public TextView f_text; public ImageView f_icon; } /** * @param file * 文件名 */ private String getMimeType(String file) { for(String ext:type_audio) { if(file.endsWith(ext)) return "audio"; } for(String ext:type_video) { if(file.endsWith(ext)) return "video"; } for(String ext:type_image) { if(file.endsWith(ext)) return "image"; } for(String ext:type_app) { if(file.endsWith(ext)) return "app"; } return ""; } }