com.haibison.android.anhuu.FileChooserActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.haibison.android.anhuu.FileChooserActivity.java

Source

/*
 *    Copyright (c) 2012 Hai Bison
 *
 *    See the file LICENSE at the root directory of this project for copying
 *    permission.
 */

package com.haibison.android.anhuu;

import java.util.ArrayList;

import android.content.Context;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.GridView;
import android.widget.ListView;

import com.haibison.android.anhuu.Settings.Display;
import com.haibison.android.anhuu.providers.BaseFileProviderUtils;
import com.haibison.android.anhuu.providers.basefile.BaseFileContract.BaseFile;
import com.haibison.android.anhuu.providers.localfile.LocalFileContract;
import com.haibison.android.anhuu.providers.localfile.LocalFileProvider;
import com.haibison.android.anhuu.utils.ui.Dlg;
import com.haibison.android.anhuu.utils.ui.UI;

/**
 * Main activity for this library.
 * <p/>
 * <h1>Usage</h1>
 * </p>
 * Use {@link #ACTION_CHOOSE} to choose a file, or {@link #ACTION_SAVE} to
 * choose a file to save.
 * <p/>
 * <h1>Notes</h1>
 * <p/>
 * <ol>
 * <li>About keys {@link FileChooserActivity#EXTRA_ROOTPATH},
 * {@link FileChooserActivity#EXTRA_SELECT_FILE} and preference
 * {@link Display#isRememberLastLocation(Context)}, the priorities of them are:
 * <ol>
 * <li>{@link FileChooserActivity#EXTRA_SELECT_FILE}</li>
 * <li>{@link FileChooserActivity#EXTRA_ROOTPATH}</li>
 * <li>{@link Display#isRememberLastLocation(Context)}</li>
 * </ol>
 * </li>
 * <li>{@link #ACTION_CHOOSE} will return {@link #EXTRA_RESULTS} as an
 * {@link ArrayList} of {@link Uri}. If the selection mode is single, the list
 * contains one URI.</li>
 * <li>{@link #ACTION_SAVE} will return {@link #EXTRA_RESULTS} as a {@link Uri}.
 * </li>
 * </ol>
 * 
 * @author Hai Bison
 */
public class FileChooserActivity extends FragmentActivity {

    /**
     * The full name of this class. Generally used for debugging.
     */
    private static final String CLASSNAME = FileChooserActivity.class.getName();

    /**
     * Types of view.
     * 
     * @author Hai Bison
     * @since v4.0 beta
     */
    public static enum ViewType {
        /**
         * Use {@link ListView} to display file list.
         */
        LIST,
        /**
         * Use {@link GridView} to display file list.
         */
        GRID
    }// ViewType

    /**
     * Use this action to choose file(s).
     * 
     * @since v5.4.4 beta
     */
    public static final String ACTION_CHOOSE = CLASSNAME + ".action_choose";

    /**
     * Use this action to save file.
     * 
     * @since v5.4.4 beta
     */
    public static final String ACTION_SAVE = CLASSNAME + ".action_save";

    /*---------------------------------------------
     * KEYS
     */

    /**
     * Sets value of this key to a theme which is one of {@code AnHuu_Theme_*}
     * or their descendant.
     * 
     * @since v4.3 beta
     */
    public static final String EXTRA_THEME = CLASSNAME + ".theme";

    /**
     * Key to hold the root path.
     * <p/>
     * If {@link LocalFileProvider} is used, then default is SD card, if SD card
     * is not available, {@code "/"} will be used.
     * <p/>
     * <b>Note</b>: The value of this key is a file provider's {@link Uri}. For
     * example with {@link LocalFileProvider}, you can use this command:
     * 
     * <pre>
     * <code>...
     *  intent.putExtra(FileChooserActivity.EXTRA_ROOTPATH,
     *          BaseFile.genContentIdUriBase(LocalFileContract.getAuthority())
     *          .buildUpon().appendPath("/sdcard").build())
     * </code>
     * </pre>
     */
    public static final String EXTRA_ROOTPATH = CLASSNAME + ".rootpath";

    /**
     * Key to hold the authority of file provider.
     * <p/>
     * Default is {@link LocalFileContract#getAuthority(Context)}.
     */
    public static final String EXTRA_FILE_PROVIDER_AUTHORITY = CLASSNAME + ".file_provider_authority";

    // ---------------------------------------------------------

    /**
     * Key to hold filter mode, can be one of
     * {@link BaseFile#FILTER_DIRECTORIES_ONLY},
     * {@link BaseFile#FILTER_FILES_AND_DIRECTORIES},
     * {@link BaseFile#FILTER_FILES_ONLY}.
     * <p/>
     * Default is {@link BaseFile#FILTER_FILES_ONLY}.
     */
    public static final String EXTRA_FILTER_MODE = CLASSNAME + ".filter_mode";

    // flags

    // ---------------------------------------------------------

    /**
     * Key to hold max file count that's allowed to be listed, default =
     * {@code 1000}.
     */
    public static final String EXTRA_MAX_FILE_COUNT = CLASSNAME + ".max_file_count";
    /**
     * Key to hold multi-selection mode, default = {@code false}.
     */
    public static final String EXTRA_MULTI_SELECTION = CLASSNAME + ".multi_selection";
    /**
     * Key to hold the positive regex to filter files (<b><i>not</i></b>
     * directories), default is {@code null}.
     * 
     * @since v5.1 beta
     */
    public static final String EXTRA_POSITIVE_REGEX_FILTER = CLASSNAME + ".positive_regex_filter";
    /**
     * Key to hold the negative regex to filter files (<b><i>not</i></b>
     * directories), default is {@code null}.
     * 
     * @since v5.1 beta
     */
    public static final String EXTRA_NEGATIVE_REGEX_FILTER = CLASSNAME + ".negative_regex_filter";
    /**
     * Key to hold display-hidden-files, default = {@code false}.
     */
    public static final String EXTRA_DISPLAY_HIDDEN_FILES = CLASSNAME + ".display_hidden_files";
    /**
     * Sets this to {@code true} to enable double tapping to choose files/
     * directories. In older versions, double tapping is default. However, since
     * v4.7 beta, single tapping is default. So if you want to keep the old way,
     * please set this key to {@code true}.
     * 
     * @since v4.7 beta
     */
    public static final String EXTRA_DOUBLE_TAP_TO_CHOOSE_FILES = CLASSNAME + ".double_tap_to_choose_files";
    /**
     * Sets the file you want to select when starting this activity. This is a
     * file provider's {@link Uri}. For example with {@link LocalFileProvider},
     * you can use this command:
     * <p/>
     * 
     * <pre>
     * <code>...
     *   intent.putExtra(FileChooserActivity.EXTRA_SELECT_FILE,
     *           BaseFile.genContentIdUriBase(LocalFileContract.getAuthority())
     *           .buildUpon().appendPath("/sdcard").build())
     * </code>
     * </pre>
     * <p/>
     * <b>Notes:</b>
     * <ul>
     * <li>Currently this key is only used for single selection mode.</li>
     * <li>If you use save dialog mode, this key will override key
     * {@link #EXTRA_DEFAULT_FILENAME}.</li>
     * </ul>
     * 
     * @since v4.7 beta
     */
    public static final String EXTRA_SELECT_FILE = CLASSNAME + ".select_file";

    // ---------------------------------------------------------

    /**
     * Key to hold default filename, default = {@code null}.
     */
    public static final String EXTRA_DEFAULT_FILENAME = CLASSNAME + ".default_filename";
    /**
     * Key to hold default file extension (<b>without</b> the period prefix),
     * default = {@code null}.
     * <p/>
     * Note that this will be compared to the user's input value as
     * case-insensitive. For example if you provide "csv" and the user types
     * "CSV" then it is OK to use "CSV".
     */
    public static final String EXTRA_DEFAULT_FILE_EXT = CLASSNAME + ".default_file_ext";

    /**
     * Key to hold results.
     * <p/>
     * <ul>
     * <li>If you use {@link #ACTION_CHOOSE}, this is an {@link ArrayList} of
     * {@link Uri}. It can contain one or multiple files.</li>
     * <li>If you use {@link #ACTION_SAVE}, this is a {@link Uri}.</li>
     * </ul>
     */
    public static final String EXTRA_RESULTS = CLASSNAME + ".results";

    /**
     * If you use {@link #ACTION_SAVE}, this extra indicates that the selected
     * file exists or not. This is the same as
     * {@link BaseFileProviderUtils#fileExists(Context, Uri)}. However it
     * reduces the calls to file provider, which is convenient for custom file
     * providers working with network.
     * <p/>
     * Type: {@link Boolean}.
     * 
     * @author Philipp Crocoll
     */
    public static final String EXTRA_RESULT_FILE_EXISTS = CLASSNAME + ".result_file_exists";

    /*
     * CONTROLS
     */

    FragmentFiles mFragmentFiles;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        /*
         * EXTRA_THEME
         */

        if (getIntent().hasExtra(EXTRA_THEME))
            setTheme(getIntent().getIntExtra(EXTRA_THEME, R.style.AnHuu_f5be488d_Theme_Dark));

        super.onCreate(savedInstanceState);
        setContentView(R.layout.anhuu_f5be488d_activity_filechooser);
        UI.adjustDialogSizeForLargeScreens(getWindow());

        /*
         * Make sure RESULT_CANCELED is default.
         */
        setResult(RESULT_CANCELED);

        mFragmentFiles = FragmentFiles.newInstance(getIntent());
        mFragmentFiles.getArguments().putString(FragmentFiles.EXTRA_ACTION, getIntent().getAction());
        getSupportFragmentManager().beginTransaction().add(R.id.anhuu_f5be488d_fragment_files, mFragmentFiles)
                .commit();
    }// onCreate()

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        UI.adjustDialogSizeForLargeScreens(getWindow());
    }// onConfigurationChanged()

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (BuildConfig.DEBUG)
            Log.d(CLASSNAME, String.format("onKeyDown() >> %,d", keyCode));

        if (keyCode == KeyEvent.KEYCODE_BACK) {
            /*
             * Use this hook instead of onBackPressed(), because onBackPressed()
             * is not available in API 4.
             */
            if (mFragmentFiles.isLoading()) {
                if (BuildConfig.DEBUG)
                    Log.d(CLASSNAME, "onKeyDown() >> KEYCODE_BACK >> cancelling previous query...");
                mFragmentFiles.cancelPreviousLoader();
                Dlg.toast(this, R.string.anhuu_f5be488d_msg_cancelled, Dlg.LENGTH_SHORT);
                return true;
            }
        }

        return super.onKeyDown(keyCode, event);
    }// onKeyDown()

}