/* * $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 }