Android Open Source - FilePicker File System Adapter






From Project

Back to project page FilePicker.

License

The source code is released under:

Apache License

If you think the Android project FilePicker listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.tonicartos.component.internal;
//  w  ww. j av  a2s. c  o m
import com.tonicartos.component.FilePickerFragment.HeaderMapper;
import com.tonicartos.component.R;
import com.tonicartos.widget.stickygridheaders.StickyGridHeadersBaseAdapter;

import android.annotation.SuppressLint;
import android.os.AsyncTask;
import android.os.FileObserver;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class FileSystemAdapter extends ArrayAdapter<String> implements StickyGridHeadersBaseAdapter {
    private static FilenameFilter sDefaultFilter = new FilenameFilter() {
        @Override
        public boolean accept(File dir, String filename) {
            File file = new File(dir, filename);
            if (file.isHidden()) {
                return false;
            }
            if (file.isDirectory()) {
                return true;
            }
            return true;
        }
    };

    private boolean mCaseInsensitive;

    /**
     * So the file observer events can update on the UI thread.
     */
    private FragmentActivity mContext;

    private File mDir;

    private FileComparator mFileComparator = new FileComparator();

    private DirObserver mFileObserver;

    private FilenameFilter mFilter;

    private Map<String, HeaderData> mHeaderMap;

    private List<HeaderData> mHeaders;

    private LayoutInflater mInflater;

    private HeaderMapper mHeaderMapper;

    private View mContainer;

    private View mLoadingView;

    private View mEmptyView;

    public FileSystemAdapter(FragmentActivity context, File file, HeaderMapper headerMapper,
            View container) {
        this(context, file, headerMapper, container, sDefaultFilter, false);
    }

    public FileSystemAdapter(FragmentActivity context, File file, HeaderMapper headerMapper,
            View container, boolean caseInsensitive) {
        this(context, file, headerMapper, container, sDefaultFilter, caseInsensitive);
    }

    public FileSystemAdapter(FragmentActivity context, File file, HeaderMapper headerMapper,
            View container, FilenameFilter filter) {
        this(context, file, headerMapper, container, filter, false);
    }

    public FileSystemAdapter(FragmentActivity context, File file, HeaderMapper headerMapper,
            View container, final FilenameFilter filter, boolean caseInsensitive) {
        super(context, android.R.layout.simple_list_item_1, android.R.id.text1);

        mHeaderMapper = headerMapper;

        mContainer = container;

        mDir = file;
        mFilter = filter;

        mInflater = LayoutInflater.from(context);
        mContext = context;
        mCaseInsensitive = caseInsensitive;
        mHeaders = new ArrayList<HeaderData>();

        mFileObserver = new DirObserver(mDir.getPath());
        mFileObserver.startWatching();
        mLoadingView = mContainer.findViewById(R.id.loading);
        mEmptyView = mContainer.findViewById(R.id.empty);
        ((AbsListView)mContainer.findViewById(R.id.list_files)).setEmptyView(mContainer
                .findViewById(android.R.id.empty));

        new AsyncTask<File, Void, ArrayList<String>>() {
            @Override
            protected ArrayList<String> doInBackground(File... files) {
                String[] fs = files[0].list(filter);
                if (fs == null) {
                    return new ArrayList<String>();
                }
                // Do the initial sort in a background thread.
                Arrays.sort(fs, mFileComparator);
                return new ArrayList<String>(Arrays.asList(fs));
            }

            @Override
            protected void onPostExecute(ArrayList<String> result) {
                if (result.size() == 0) {
                    mEmptyView.setVisibility(View.VISIBLE);
                    mLoadingView.setVisibility(View.GONE);
                }
                FileSystemAdapter.this.addAll(result);
                buildHeaders();
            };

            @Override
            protected void onPreExecute() {
                mEmptyView.setVisibility(View.GONE);
                mLoadingView.setVisibility(View.VISIBLE);
            }
        }.execute(file);
    }

    @Override
    public int getCountForHeader(int header) {
        return mHeaders.get(header).count;
    }

    public File getFile(int position) {
        return new File(mDir, getItem(position));
    }

    @Override
    @SuppressLint("DefaultLocale")
    public View getHeaderView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.header, parent, false);
            holder = new ViewHolder();
            holder.textView = (TextView)convertView.findViewById(android.R.id.text1);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder)convertView.getTag();
        }

        holder.textView.setText(mHeaders.get(position).header.toUpperCase());

        return convertView;
    }

    @Override
    public int getNumHeaders() {
        return mHeaders.size();
    }

    public void stopWatching() {
        mFileObserver.stopWatching();
    }

    /**
     * Build header data from initial load of files.
     */
    private void buildHeaders() {
        mHeaderMap = new HashMap<String, HeaderData>();
        for (int i = 0; i < getCount(); i++) {
            File file = new File(mDir, getItem(i));
            String header = getFileSectionHeader(file);
            HeaderData hd = mHeaderMap.get(header);
            if (hd == null) {
                hd = new HeaderData();
                hd.header = header;
                hd.count = 0;

                mHeaders.add(hd);
            }
            hd.count += 1;
            mHeaderMap.put(header, hd);
        }
    }

    /**
     * Compare two strings. Checks adapter settings to select a case sensitive
     * or insensitive comparison.
     * 
     * @param lhs Left hand side.
     * @param rhs Right hand side.
     * @return -ve if lhs before rhs, 0 if the same. +ve if lhs after rhs.
     */
    protected int compareCis(String lhs, String rhs) {
        if (mCaseInsensitive) {
            return lhs.compareToIgnoreCase(rhs);
        }
        return lhs.compareTo(rhs);
    }

    /**
     * Decrement the count for the file extension. Removes data for an extension
     * should the count reach 0.
     * 
     * @param ext File extension to update header data for.
     */
    protected void decrementHeader(String ext) {
        HeaderData hd = mHeaderMap.get(ext);
        if (hd == null) {
            return;
        }
        hd.count--;
        if (hd.count == 0) {
            mHeaders.remove(hd);
            mHeaderMap.remove(ext);
        }
    }

    /**
     * Get file extension for given file.
     * 
     * @param file File to get extension for.
     * @return File extension.
     */
    protected String getFileSectionHeader(File file) {
        if (file.isDirectory()) {
            return "Folders";
        }
        String mime = ExtensionMapper.getHeader(file);
        if (mime == null) {
            mime = "Unknown";
        }

        if (mHeaderMapper == null) {
            return mime;
        }
        return mHeaderMapper.getHeaderFor(mime, file);
    }

    /**
     * Increment the count for the file extension. Creates and adds new data for
     * a new extension maintaining the sorted order of the headers list.
     * 
     * @param ext File extension to update header data for.
     */
    protected void incrementHeader(String ext) {
        HeaderData hd = mHeaderMap.get(ext);
        if (hd == null) {
            hd = new HeaderData();
            hd.header = ext;
            mHeaderMap.put(ext, hd);

            // Insert header in correct place.
            boolean added = false;
            for (int i = 0; i < mHeaders.size(); i++) {
                if (compareCis(ext, mHeaders.get(i).header) < 0) {
                    mHeaders.add(i, hd);
                    added = true;
                    break;
                }
            }
            if (!added) {
                mHeaders.add(hd);
            }
        }
        hd.count++;

    }

    /**
     * File observer to watch a directory and update adapter accordingly.
     */
    private final class DirObserver extends FileObserver {
        private DirObserver(String path) {
            super(path, CREATE | DELETE | MOVED_TO | MOVED_FROM);
        }

        @Override
        public void onEvent(final int event, final String path) {
            if (event == 0x8000) {
                return;
            }

            if (!mFilter.accept(mDir, path)) {
                return;
            }
            mContext.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    switch (event & ALL_EVENTS) {
                        case MOVED_TO:
                        case CREATE:
                            incrementHeader(getFileSectionHeader(new File(mDir, path)));
                            add(path); // Notifies data set changed.
                            sort(mFileComparator);

                            break;
                        case MOVED_FROM:
                        case DELETE:
                            decrementHeader(getFileSectionHeader(new File(mDir, path)));
                            remove(path); // Notifies data set changed.
                            sort(mFileComparator);
                            break;

                        default:
                            break;
                    }

                }
            });
        }
    }

    /**
     * Compare two files sorting directories first, then by file extension, and
     * finally by name alphabetically.
     */
    private final class FileComparator implements Comparator<String> {
        @Override
        public int compare(String lhsPath, String rhsPath) {
            File lhs = new File(mDir, lhsPath), rhs = new File(mDir, rhsPath);
            if (lhs.isDirectory() && rhs.isDirectory()) {
                return compareCis(lhs.getName(), rhs.getName());
            }

            if (lhs.isDirectory()) {
                return -1;
            }

            if (rhs.isDirectory()) {
                return 1;
            }
            String lhsExtension = getFileSectionHeader(lhs);
            String rhsExtension = getFileSectionHeader(rhs);

            // Compare extensions, if they are the same then compare by name.
            int extResult = compareCis(lhsExtension, rhsExtension);
            return extResult == 0 ? compareCis(lhs.getName(), rhs.getName()) : extResult;
        }

    }

    /**
     * Data for a section header.
     */
    private final class HeaderData {
        public int count;

        public String header;
    }

    /**
     * View holder for header views.
     */
    private final class ViewHolder {
        public TextView textView;
    }
}




Java Source Code List

com.tonicartos.component.FilePickerFragment.java
com.tonicartos.component.internal.DirFragment.java
com.tonicartos.component.internal.DirNode.java
com.tonicartos.component.internal.DirPagerAdapter.java
com.tonicartos.component.internal.ExtensionMapper.java
com.tonicartos.component.internal.FileSystemAdapter.java
com.tonicartos.component.internal.IconPagerAdapter.java
com.tonicartos.component.internal.IcsLinearLayout.java
com.tonicartos.component.internal.MediaStoreFilesAdapter.java
com.tonicartos.component.internal.PageIndicator.java
com.tonicartos.component.internal.TabPageIndicator.java