今天复习一下ListView实现安卓文件管理器,包括文件的筛选、apk的安装,以及BaseAdapter的应用等。
直接上代码:

  • 应用实现部分
public class MainActivity extends ListActivity {
    private static final String ROOT_PATH = "/storage/sdcard1/tencent"; // 存储文件名称
    private ArrayList<String> names = null; // 存储文件路径
    private ArrayList<String> paths = null;
    private ArrayList<String> states = null;
    private View view;
    private EditText editText;
    private String[] menu;
    String packageName = null;
    String className = null;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main); // 显示文件列表
        showFileDir(ROOT_PATH);
    }

    private void showFileDir(String path) {
        names = new ArrayList<String>();
        paths = new ArrayList<String>();
        states = new ArrayList<String>();
        File file = new File(path);
        File[] files = file.listFiles();
        if (!ROOT_PATH.equals(path)) {// 如果当前目录不是根目录
            names.add("@1");
            paths.add(ROOT_PATH);
            states.add("");
            names.add("@2");
            paths.add(file.getParent());
            states.add("");
        }
        if(files!=null)
        for (File f : files) {// 添加所有文件
            if (f.getName().indexOf(".apk") > -1) {//此处用来筛选文件,可以专门写一个接口
                if (ifApkInstall(f)) {
                    states.add(KeyStringConst.APK_HASINSTALL);
                } else {
                    states.add(KeyStringConst.APK_NOINSTALL);
                }
                names.add(f.getName());
                paths.add(f.getPath());
            } else if (f.isDirectory()) {
                names.add(f.getName());
                paths.add(f.getPath());
                states.add("");
            } else {// 普通文件
                names.add(f.getName());
                paths.add(f.getPath());
                states.add("");
            }
        }
        this.setListAdapter(new MyAdapter(this, names, paths, states));
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        String path = paths.get(position);
        File file = new File(path); // 文件存在并可读
        if (file.exists() && file.canRead()) {
            if (file.isDirectory()) { // 显示子目录及文件
                showFileDir(path);
            } else { // 处理文件
                fileHandle(file);
            }
        } else {// 没有权限
            Resources res = getResources();
            new AlertDialog.Builder(this).setTitle("Message")
                    .setMessage(res.getString(R.string.no_permission))
                    .setPositiveButton("OK", new OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    }).show();
        }
        super.onListItemClick(l, v, position, id);
    }

    // 对文件进行增删改
    private void fileHandle(final File file) {
        String dialogTitle = "";
        OnClickListener listener = new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // 打开文件
                if (which == 0) {
                    if (menu[0].equals(KeyStringConst.OPEN_FILE)) {// 打开文件
                        openFile(file);
                    } else if (menu[0].equals(KeyStringConst.OPEN_APP)) {// 打开应用
                        Intent intent = getPackageManager()
                                .getLaunchIntentForPackage(packageName);
                        startActivity(intent);
                        finish();
                    } else if (menu[0].equals(KeyStringConst.INSTALL_APK)) {//安装apk
                         Intent intent = new Intent();
                         // 设置目标应用安装包路径
                         intent.setDataAndType(Uri.fromFile(file),
                         "application/vnd.android.package-archive");
                         startActivity(intent);
                    }
                } else if (which == 1) {
                    // 修改文件名
                    LayoutInflater factory = LayoutInflater
                            .from(MainActivity.this);
                    view = factory.inflate(R.layout.rename_dialog, null);
                    editText = (EditText) view.findViewById(R.id.editText);
                    editText.setText(file.getName());
                    OnClickListener listener2 = new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            // TODO Auto-generated method stub
                            String modifyName = editText.getText().toString();
                            final String fpath = file.getParentFile().getPath();
                            final File newFile = new File(fpath + "/"
                                    + modifyName);
                            if (newFile.exists()) {
                                // 排除没有修改情况
                                if (!modifyName.equals(file.getName())) {
                                    new AlertDialog.Builder(MainActivity.this)
                                            .setTitle("注意!")
                                            .setMessage("文件名已存在,是否覆盖?")
                                            .setPositiveButton(
                                                    "确定",
                                                    new DialogInterface.OnClickListener() {
                                                        @Override
                                                        public void onClick(
                                                                DialogInterface dialog,
                                                                int which) {
                                                            if (file.renameTo(newFile)) {
                                                                showFileDir(fpath);
                                                                displayToast("重命名成功!");
                                                            } else {
                                                                displayToast("重命名失败!");
                                                            }
                                                        }
                                                    })
                                            .setNegativeButton(
                                                    "取消",
                                                    new DialogInterface.OnClickListener() {
                                                        @Override
                                                        public void onClick(
                                                                DialogInterface dialog,
                                                                int which) {
                                                        }
                                                    }).show();
                                }
                            } else {
                                if (file.renameTo(newFile)) {
                                    showFileDir(fpath);
                                    displayToast("重命名成功!");
                                } else {
                                    displayToast("重命名失败!");
                                }
                            }
                        }
                    };
                    AlertDialog renameDialog = new AlertDialog.Builder(
                            MainActivity.this).create();
                    renameDialog.setView(view);
                    renameDialog.setButton(DialogInterface.BUTTON_POSITIVE,
                            "确定", listener2);
                    renameDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
                            "取消", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog,
                                        int which) {
                                    // TODO Auto-generated method stub
                                }
                            });
                    renameDialog.show();
                } else {
                    // 删除文件
                    new AlertDialog.Builder(MainActivity.this)
                            .setTitle("注意!")
                            .setMessage("确定要删除此文件吗?")
                            .setPositiveButton("确定",
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(
                                                DialogInterface dialog,
                                                int which) {
                                            if (file.delete()) {
                                                // 更新文件列表
                                                showFileDir(file.getParent());
                                                displayToast("删除成功!");
                                            } else {
                                                displayToast("删除失败!");
                                            }
                                        }
                                    })
                            .setNegativeButton("取消",
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(
                                                DialogInterface dialog,
                                                int which) {
                                        }
                                    }).show();
                }
            }
        };
        // 选择文件时,弹出增删该操作选项对话框
        menu = new String[3];
        if (file.getName().indexOf(".apk") > -1) {
            if (ifApkInstall(file)) {
                menu[0] = KeyStringConst.OPEN_APP;
                menu[1] = KeyStringConst.RENAME_FILE;
                menu[2] = KeyStringConst.DELETE_FILE;
                dialogTitle = "该应用已安装,";
            } else {
                menu[0] = KeyStringConst.INSTALL_APK;
                menu[1] = KeyStringConst.RENAME_FILE;
                menu[2] = KeyStringConst.DELETE_FILE;
                dialogTitle = "该文件为安装包,";
            }
        } else {
            menu[0] = KeyStringConst.OPEN_FILE;
            menu[1] = KeyStringConst.RENAME_FILE;
            menu[2] = KeyStringConst.DELETE_FILE;
            dialogTitle = "普通文件,";
        }
        new AlertDialog.Builder(MainActivity.this)
                .setTitle(dialogTitle + "请选择您要进行的操作!").setItems(menu, listener)
                .setPositiveButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                    }
                }).show();
    }

    public boolean ifApkInstall(File file) {
        boolean ifApkInstall = false;
        String ppackageName = null;
        ArrayList<AppInfo> appInfos = getAppList();
        PackageManager pm = this.getPackageManager();
        PackageInfo info = pm.getPackageArchiveInfo(file.getAbsolutePath(),
                PackageManager.GET_ACTIVITIES);
        ApplicationInfo appInfo = null;
        if (info != null) {
            appInfo = info.applicationInfo;
            ppackageName = appInfo.packageName;
            className = appInfo.className;
        }
        for (int i = 0; i < appInfos.size(); i++) {
            if (appInfos.get(i).packagename.equals(ppackageName)) {
                packageName = appInfos.get(i).packagename;
                className = appInfos.get(i).classname;
                ifApkInstall = true;
                break;
            }
        }
        return ifApkInstall;
    }

    /**
     * 获取非系统应用信息列表
     */
    private ArrayList<AppInfo> getAppList() {
        ArrayList<AppInfo> appList = new ArrayList<AppInfo>();
        PackageManager pm = this.getPackageManager();
        // Return a List of all packages that are installed on the device.
        List<PackageInfo> packages = pm.getInstalledPackages(0);
        for (PackageInfo packageInfo : packages) {
            // 判断系统/非系统应用
            // if ((packageInfo.applicationInfo.flags &
            // ApplicationInfo.FLAG_SYSTEM) <= 0) //判断是否为非系统预装的应用程序 ==0是非系统应用
            // {
            AppInfo tmpInfo = new AppInfo();

            tmpInfo.appname = packageInfo.applicationInfo.loadLabel(
                    getPackageManager()).toString();
            // The name of this package. From the <manifest> tag's "name"
            // attribute.
            tmpInfo.packagename = packageInfo.applicationInfo.packageName;
            // The version name of this package, as specified by the <manifest>
            // tag's versionName attribute.
            tmpInfo.versionName = packageInfo.versionName;
            // The version number of this package, as specified by the
            // <manifest> tag's versionCode attribute.
            tmpInfo.versionCode = packageInfo.versionCode;
            // Class implementing the Application object. From the "class"
            // attribute.
            tmpInfo.classname = packageInfo.applicationInfo.className;
            // Log.i("MainActivity activities", tmpInfo.activitys.toString());
            // tmpInfo.appicon =
            // packageInfo.applicationInfo.loadIcon(getPackageManager());
            appList.add(tmpInfo);
            // }
        }
        return appList;
    }

    protected class AppInfo {
        protected int versionCode = 0; // 名称
        protected String appname = ""; // 包
        protected String packagename = "";
        protected String classname = "";
        protected String versionName = ""; // 图标
    }

    // 打开文件
    private void openFile(File file) {
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setAction(android.content.Intent.ACTION_VIEW);
        String type = getMIMEType(file);
        intent.setDataAndType(Uri.fromFile(file), type);
        startActivity(intent);
    }

    // 获取文件mimetype
    private String getMIMEType(File file) {
        String type = "";
        String name = file.getName();
        // 文件扩展名
        String end = name.substring(name.lastIndexOf(".") + 1, name.length())
                .toLowerCase();
        if (end.equals("m4a") || end.equals("mp3") || end.equals("wav")) {
            type = "audio";
        } else if (end.equals("mp4") || end.equals("3gp")) {
            type = "video";
        } else if (end.equals("jpg") || end.equals("png") || end.equals("jpeg")
                || end.equals("bmp") || end.equals("gif")) {
            type = "image";
        } else {
            // 如果无法直接打开,跳出列表由用户选择
            type = "*";
        }
        type += "/*";
        return type;
    }

    private void displayToast(String message) {
        Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
    }
}

<>

  • Adapter实现部分
      这里说一下为什么要用BaseAdapter(抽象类),BaseAdapter的灵活性就在于它要重写很多方法。只要实现了对一个控件(如本文中的ListView)数据的适配,那其它的只需要稍作修改就可以用到别如GridView等上:
      1.BaseAdapter也是Android应用程序中经常用到的基础数据适配器,它的主要用途是将一组数据传到像ListView、Spinner、Gallery及GridView等UI显示组件,它是继承自接口类Adapter,自定义Adapter子类,就需要实现上面几个方法,其中最重要的是getView()方法,它是将获取数据后的View组件返回,如ListView中每一行里的TextView、Gallery等中的每个ImageView。
      2.Adapter在Android应用程序中起着非常重要的作用,应用也非常广泛,它可看作是数据源和UI组件之间的桥梁,其中Adapter、数据和UI之间的关系,可以用下图表示:
        
  • android文件管理 mac Android文件管理器的实现方案_ide

  •     
      3.Adapter的常用子类,如下图:
      
  • android文件管理 mac Android文件管理器的实现方案_android_02

  •   代码如下:
public class MyAdapter extends BaseAdapter {
    private LayoutInflater inflater;
    private Bitmap directory, file;
    // 存储文件名称
    private ArrayList<String> names = null;
    // 存储文件路径
    private ArrayList<String> paths = null;
    // 存储文件路径
    private ArrayList<String> states = null;

    // 参数初始化
    public MyAdapter(Context context, ArrayList<String> name,
            ArrayList<String> path, ArrayList<String> state) {
        names = name;
        paths = path;
        states = state;
        directory = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.directory);
        file = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.file);
        // 缩小图片
        directory = small(directory, 0.16f);
        file = small(file, 0.1f);
        inflater = LayoutInflater.from(context);
    }


    @Override
    public int getCount() {
        return names.size();
    }

    @Override
    public Object getItem(int position) {
        return names.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (null == convertView) {
            convertView = inflater.inflate(R.layout.file, null);
            holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.textView);
            holder.image = (ImageView) convertView.findViewById(R.id.imageView);
            holder.state = (TextView) convertView.findViewById(R.id.stateView);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        File f = new File(paths.get(position).toString());
        if (names.get(position).equals("@1")) {
            holder.text.setText("/");
            holder.image.setImageBitmap(directory);
        } else if (names.get(position).equals("@2")) {
            holder.text.setText("..");
            holder.image.setImageBitmap(directory);
        } else {
            holder.text.setText(f.getName());
            if (f.isDirectory()) {
                holder.image.setImageBitmap(directory);
                holder.state.setText(states.get(position));
            } else if (f.isFile()) {
                holder.image.setImageBitmap(file);
                holder.state.setText(states.get(position));
            } else {
                System.out.println(f.getName());
            }
        }
        return convertView;
    }

    private class ViewHolder {
        private TextView text;
        private ImageView image;
        private TextView state;
    }

    private Bitmap small(Bitmap map, float num) {
        Matrix matrix = new Matrix();
        matrix.postScale(num, num);
        return Bitmap.createBitmap(map, 0, 0, map.getWidth(), map.getHeight(),
                matrix, true);
    }
}
  • 界面中文字集合部分
      本应该在xml中编写,但太频繁的通过getString来获取xml文件中的内容其实会慢于直接在JAVA文件中(直接在内存中取String常量,但缺点也很明显,当常量太多的时候,会有不必要数据的加载进内存,且不便于统一字符编码格式,以及国际化):
      
    KeyStringConst.java
public class KeyStringConst {
    public static final String INSTALL_APK = "安装";
    public static final String UNINSTALL_APK = "卸载";
    public static final String RENAME_FILE = "重命名";
    public static final String DELETE_FILE = "删除文件";
    public static final String OPEN_APP = "打开";
    public static final String OPEN_FILE = "打开文件";
    public static final String APK_HASINSTALL = "hasinstall";
    public static final String APK_NOINSTALL = "notinstall";
    public static final String APK_INSTALLFAILL = "应用安装成功!";
    public static final String APK_INSTALLSUCCESS = "应用安装失败!";
}
  • 主要布局文件部分

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <ListView android:id="@android:id/list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

file.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_gravity="center_horizontal|bottom"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >

    <RelativeLayout android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        >

        <ImageView android:id="@+id/imageView"
            android:layout_height="30dip"
            android:layout_width="wrap_content"
            android:layout_marginLeft="20dip">
        </ImageView>
        <TextView android:id="@+id/textView"
            android:layout_width="600dip"
            android:layout_height="30dip"
            android:layout_gravity="bottom"
            android:gravity="bottom"
            android:singleLine="true"
            android:textSize="14sp"
            android:layout_marginLeft="100dip"
            >
        </TextView>
        <TextView android:id="@+id/stateView"
            android:layout_width="60dip"
            android:layout_height="30dip"
            android:textSize="9sp"
            android:layout_gravity="bottom"
            android:gravity="bottom"
            android:singleLine="true"
            android:layout_marginLeft="750dip"
            >
        </TextView>
    </RelativeLayout>
</LinearLayout>

现在21:46,加班快要结束了,没办法,零碎的事情太多了。客户也是这边那边都在催,这边说APP有问题要改要优化,那边又接了个新的活。