org.arakhne.afc.ui.android.filechooser.FileChooserActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.arakhne.afc.ui.android.filechooser.FileChooserActivity.java

Source

/*
 * $Id$
 * This file is a part of the Arakhne Foundation Classes, http://www.arakhne.org/afc
 *
 * Copyright (c) 2000-2012 Stephane GALLAND.
 * Copyright (c) 2005-10, Multiagent Team, Laboratoire Systemes et Transports,
 *                        Universite de Technologie de Belfort-Montbeliard.
 * Copyright (c) 2013-2016 The original authors, and other authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.arakhne.afc.ui.android.filechooser;

import java.io.File;
import java.io.FileFilter;

import org.arakhne.afc.ui.android.R;
import org.arakhne.afc.vmutil.FileSystem;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentManager.BackStackEntry;
import android.support.v4.app.FragmentManager.OnBackStackChangedListener;
import android.support.v4.app.FragmentTransaction;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;

/**
 * File chooser embedded inside an activity fragment. 
 * 
 * @author $Author: sgalland$
 * @version $Name$ $Revision$ $Date$
 * @mavengroupid $GroupId$
 * @mavenartifactid $ArtifactId$
 * @deprecated see JavaFX API
 */
@Deprecated
public class FileChooserActivity extends FragmentActivity implements OnBackStackChangedListener {

    /** Name of the extra data that is containing the options of the file chooser.
     */
    static final String ACTIVITY_OPTIONS = "fileChooserActivityOptions";

    /** Name of the attribute that permits to save the path in the activity.
     */
    public static final String SAVED_PATH_NAME = "path";

    /** Name of the attribute that permits to save the icon selector in the activity.
     */
    public static final String SAVED_ICON_SELECTOR = "iconSelector";

    /** Name of the attribute that permits to save the file filter in the activity.
     */
    public static final String SAVED_FILE_FILTER = "fileFilter";

    /** Name of the attribute that permits to indicates if the chooser is for opening a file.
     */
    public static final String SAVED_IS_OPEN = "isOpen";

    /** Name of the preference that permits to store the path.
     */
    private static final String PREFERENCE_FILE_PATH = "lastSelectedPath";

    private static File getFileParameter(String name, File defaultValue, Bundle... bundles) {
        for (Bundle b : bundles) {
            if (b != null) {
                String absPath = b.getString(name);
                if (absPath != null)
                    return new File(absPath);
            }
        }
        return defaultValue;
    }

    private static FileFilter getFileFilterParameter(String name, FileFilter defaultValue, Bundle... bundles) {
        for (Bundle b : bundles) {
            if (b != null) {
                String classname = b.getString(name);
                if (classname != null) {
                    try {
                        Class<?> type = Class.forName(classname);
                        if (FileFilter.class.isAssignableFrom(type)) {
                            return (FileFilter) type.newInstance();
                        }
                    } catch (Throwable e) {
                        Log.d("FILE_CHOOSER", e.getLocalizedMessage(), e);
                    }
                }
            }
        }
        return defaultValue;
    }

    private static FileChooserIconSelector getIconSelectorParameter(String name,
            FileChooserIconSelector defaultValue, Bundle... bundles) {
        for (Bundle b : bundles) {
            if (b != null) {
                String classname = b.getString(name);
                if (classname != null) {
                    try {
                        Class<?> type = Class.forName(classname);
                        if (FileChooserIconSelector.class.isAssignableFrom(type)) {
                            return (FileChooserIconSelector) type.newInstance();
                        }
                    } catch (Throwable e) {
                        Log.d("FILE_CHOOSER", e.getLocalizedMessage(), e);
                    }
                }
            }
        }
        return defaultValue;
    }

    /** Listener on the external storage state.
     */
    private BroadcastReceiver storageListener = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            onValidatedFile(null);
        }
    };

    /** Current selected file.
     */
    private File path = null;

    /** File filter.
     */
    private FileFilter fileFilter = null;

    /** Icon selector.
     */
    private FileChooserIconSelector iconSelector = null;

    /** Manager of fragments.
     */
    private FragmentManager fragmentManager = null;

    /** Indicates if the file chooser is for opening (<code>true</code>)
     * or saving (<code>false</code>) a file.
     */
    private boolean isOpen = true;

    /** Reference to the save menu item.
     */
    private MenuItem saveItem = null;

    /** Reference to the up-directory menu item.
     */
    private MenuItem upDirectoryItem = null;

    /** Options given to the activity.
     */
    private Bundle activityOptions = null;

    /**
     * {@inheritDoc}
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent intent = getIntent();
        this.activityOptions = intent.getBundleExtra(ACTIVITY_OPTIONS);

        this.path = getFileParameter(SAVED_PATH_NAME, null, this.activityOptions, savedInstanceState);

        if (this.path == null) {
            SharedPreferences preferences = getPreferences(DEFAULT_KEYS_SEARCH_LOCAL);
            String filePath = preferences.getString(PREFERENCE_FILE_PATH, null);
            if (filePath != null && !filePath.isEmpty()) {
                this.path = new File(filePath);
                if (!this.path.isDirectory()) {
                    this.path = this.path.getParentFile();
                }
            }
            if (this.path == null) {
                this.path = Environment.getExternalStorageDirectory();
            }
        }

        this.fileFilter = getFileFilterParameter(SAVED_FILE_FILTER, null, this.activityOptions, savedInstanceState);

        this.iconSelector = getIconSelectorParameter(SAVED_ICON_SELECTOR, null, this.activityOptions,
                savedInstanceState);

        if (this.activityOptions != null) {
            this.isOpen = this.activityOptions.getBoolean(SAVED_IS_OPEN,
                    savedInstanceState != null ? savedInstanceState.getBoolean(SAVED_IS_OPEN, true) : true);
        }

        String basename = null;
        if (!this.isOpen && !this.path.isDirectory()) {
            basename = this.path.getName();
        }

        while (this.path != null && !this.path.isDirectory()) {
            this.path = this.path.getParentFile();
        }

        if (this.path == null) {
            this.path = Environment.getExternalStorageDirectory();
        }

        if (this.isOpen) {
            setContentView(R.layout.filechooser_open);
        } else {
            setContentView(R.layout.filechooser_save);
            EditText editor = (EditText) findViewById(R.id.fileChooserFilenameField);
            if (basename != null)
                editor.setText(basename);
            editor.addTextChangedListener(new Listener());
        }

        this.fragmentManager = getSupportFragmentManager();
        this.fragmentManager.addOnBackStackChangedListener(this);

        setTitle(this.path.getAbsolutePath());

        // Start to listen on directory changes.
        FileListFragment explorerFragment = FileListFragment.newInstance(this.path, this.fileFilter,
                this.iconSelector);
        FragmentTransaction transaction = this.fragmentManager.beginTransaction();
        transaction.add(R.id.fileChooserExplorerFragment, explorerFragment).commit();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        if (this.isOpen) {
            getMenuInflater().inflate(R.menu.filechooser_open_menu, menu);
        } else {
            getMenuInflater().inflate(R.menu.filechooser_save_menu, menu);
            this.saveItem = menu.findItem(R.id.fileChooserSaveMenu);
        }
        this.upDirectoryItem = menu.findItem(R.id.fileChooserParentDirectoryMenu);
        return true;
    }

    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) {
        if (item.getItemId() == R.id.fileChooserParentDirectoryMenu) {
            onSelectedFile(this.path.getParentFile());
            return true;
        }
        if (!this.isOpen && item.getItemId() == R.id.fileChooserSaveMenu) {
            EditText editor = (EditText) findViewById(R.id.fileChooserFilenameField);
            String basename = editor.getText().toString();
            basename = FileSystem.basename(basename);
            onValidatedFile(new File(this.path, basename));
            return true;
        }
        return super.onMenuItemSelected(featureId, item);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        updateUpDirectoryAction();
        if (!this.isOpen) {
            updateSaveAction();
        }
        return true;
    }

    /** Update the state of the up-directory action.
     */
    protected void updateUpDirectoryAction() {
        if (this.upDirectoryItem != null) {
            this.upDirectoryItem.setEnabled(this.path.getParentFile() != null);
        }
    }

    /** Update the state of the save action.
     */
    protected void updateSaveAction() {
        if (this.saveItem != null) {
            EditText editor = (EditText) findViewById(R.id.fileChooserFilenameField);
            String text = editor.getText().toString();
            this.saveItem.setEnabled(this.path.isDirectory() && !text.isEmpty());
        }
    }

    /** Set the file filter to use in the chooser.
     * 
     * @param fileFilter
     */
    public void setFileFilter(FileFilter fileFilter) {
        this.fileFilter = fileFilter;
    }

    /** Replies the file filter to use in the chooser.
     * 
     * @return the file filter.
     */
    public FileFilter getFileFilter() {
        return this.fileFilter;
    }

    /** Set the selector of icon
     * 
     * @param iconSelector
     */
    public void setIconSelector(FileChooserIconSelector iconSelector) {
        this.iconSelector = iconSelector;
    }

    /** Replies the selector of icon.
     * 
     * @return the icon selector.
     */
    public FileChooserIconSelector getIconSelector() {
        return this.iconSelector;
    }

    /** Invoked when the SD card state has changed.
     */
    @Override
    public void onBackStackChanged() {
        this.path = Environment.getExternalStorageDirectory();

        int count = this.fragmentManager.getBackStackEntryCount();
        if (count > 0) {
            BackStackEntry fragment = this.fragmentManager.getBackStackEntryAt(count - 1);
            String path = fragment.getName();
            if (path != null)
                this.path = new File(path);
        }

        setTitle(this.path.getAbsolutePath());
        invalidateOptionsMenu();
    }

    /** {@inheritDoc}
     */
    @Override
    protected void onPause() {
        super.onPause();
        unregisterStorageListener();
    }

    /** {@inheritDoc}
     */
    @Override
    protected void onResume() {
        super.onResume();
        registerStorageListener();
    }

    /** {@inheritDoc}
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        if (this.path != null) {
            outState.putString(SAVED_PATH_NAME, this.path.getAbsolutePath());
        } else {
            outState.remove(SAVED_PATH_NAME);
        }
        if (this.fileFilter != null) {
            outState.putString(SAVED_FILE_FILTER, this.fileFilter.getClass().getName());
        } else {
            outState.remove(SAVED_FILE_FILTER);
        }
        if (this.iconSelector != null) {
            outState.putString(SAVED_ICON_SELECTOR, this.iconSelector.getClass().getName());
        } else {
            outState.remove(SAVED_ICON_SELECTOR);
        }
        outState.putBoolean(SAVED_IS_OPEN, this.isOpen);
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        this.isOpen = savedInstanceState.getBoolean(SAVED_IS_OPEN);
        String fileFilterClassname = savedInstanceState.getString(SAVED_FILE_FILTER);
        if (fileFilterClassname != null) {
            try {
                Class<?> type = Class.forName(fileFilterClassname);
                if (FileFilter.class.isAssignableFrom(type)) {
                    this.fileFilter = (FileFilter) type.newInstance();
                }
            } catch (Throwable exception) {
                //
            }
        }
        String iconSelectorClassname = savedInstanceState.getString(SAVED_ICON_SELECTOR);
        if (iconSelectorClassname != null) {
            try {
                Class<?> type = Class.forName(iconSelectorClassname);
                if (FileChooserIconSelector.class.isAssignableFrom(type)) {
                    this.iconSelector = (FileChooserIconSelector) type.newInstance();
                }
            } catch (Throwable exception) {
                //
            }
        }
        String path = savedInstanceState.getString(SAVED_PATH_NAME);
        if (path != null) {
            this.path = new File(path);
        }
    }

    /**
     * Invoked when the activity is finished with a selected file.
     * 
     * @param file is the selected file.
     */
    protected void onValidatedFile(File file) {
        // Force to close the soft keyboard
        if (!this.isOpen) {
            InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0);
        }
        File validatedFile = file;
        if (validatedFile != null) {
            //         if (!this.isOpen && this.fileFilter instanceof FileFilter) {
            //            if (!this.fileFilter.accept(validatedFile)) {
            //               String ext = ((org.arakhne.afc.io.filefilter.FileFilter)this.fileFilter).getExtensions()[0];
            //               validatedFile = FileSystem.addExtension(validatedFile, ext);
            //            }
            //         }

            if (this.path != null) {
                File preferencePath = this.path;
                while (preferencePath != null && !preferencePath.isDirectory())
                    preferencePath = preferencePath.getParentFile();
                if (preferencePath != null) {
                    SharedPreferences preferences = getPreferences(DEFAULT_KEYS_SEARCH_LOCAL);
                    Editor preferenceEditor = preferences.edit();
                    preferenceEditor.putString(PREFERENCE_FILE_PATH, preferencePath.getAbsolutePath());
                    preferenceEditor.commit();
                    preferenceEditor.apply();
                }
            }

            Intent data = new Intent();
            data.setData(Uri.fromFile(validatedFile));

            if (this.activityOptions != null) {
                data.putExtras(this.activityOptions);
            }

            setResult(RESULT_OK, data);
            finish();
        } else {
            setResult(RESULT_CANCELED);
            finish();
        }
    }

    /**
     * Called when the user selects a File.
     * 
     * @param file is the selected file.
     */
    protected void onSelectedFile(File file) {
        if (file != null) {
            this.path = file;

            if (file.isDirectory()) {
                FileListFragment explorerFragment = FileListFragment.newInstance(this.path, this.fileFilter,
                        this.iconSelector);
                FragmentTransaction transaction = this.fragmentManager.beginTransaction();
                transaction.replace(R.id.fileChooserExplorerFragment, explorerFragment)
                        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                        .addToBackStack(this.path.getAbsolutePath()).commit();
            } else {
                onValidatedFile(file);
            }
        }
    }

    /**
     * Register the external storage BroadcastReceiver.
     */
    private void registerStorageListener() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_MEDIA_REMOVED);
        registerReceiver(this.storageListener, filter);
    }

    /**
     * Unregister the external storage BroadcastReceiver.
     */
    private void unregisterStorageListener() {
        unregisterReceiver(this.storageListener);
    }

    /**
     * @author $Author: sgalland$
     * @version $Name$ $Revision$ $Date$
     * @mavengroupid $GroupId$
     * @mavenartifactid $ArtifactId$
     */
    private class Listener implements TextWatcher {

        /**
         */
        public Listener() {
            //
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            //
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            //
        }

        @Override
        public void afterTextChanged(Editable s) {
            updateSaveAction();
        }

    } // class Listener

}