Java tutorial
/* * Copyright (C) 2012 The CyanogenMod Project * * 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 com.brandroidtools.filemanager.activities; import android.app.Activity; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnDismissListener; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.FragmentActivity; import android.util.DisplayMetrics; import android.util.Log; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.FrameLayout; import android.widget.ListPopupWindow; import android.widget.Toast; import com.brandroidtools.filemanager.R; import com.brandroidtools.filemanager.adapters.CheckableListAdapter; import com.brandroidtools.filemanager.adapters.CheckableListAdapter.CheckableItem; import com.brandroidtools.filemanager.console.ConsoleBuilder; import com.brandroidtools.filemanager.fragments.NavigationFragment; import com.brandroidtools.filemanager.model.FileSystemObject; import com.brandroidtools.filemanager.model.FileSystemStorageVolume; import com.brandroidtools.filemanager.preferences.DisplayRestrictions; import com.brandroidtools.filemanager.preferences.FileManagerSettings; import com.brandroidtools.filemanager.preferences.Preferences; import com.brandroidtools.filemanager.ui.ThemeManager; import com.brandroidtools.filemanager.ui.ThemeManager.Theme; import com.brandroidtools.filemanager.ui.widgets.Breadcrumb; import com.brandroidtools.filemanager.ui.widgets.ButtonItem; import com.brandroidtools.filemanager.fragments.NavigationFragment.OnDirectoryChangedListener; import com.brandroidtools.filemanager.fragments.NavigationFragment.OnFilePickedListener; import com.brandroidtools.filemanager.util.DialogHelper; import com.brandroidtools.filemanager.util.ExceptionUtil; import com.brandroidtools.filemanager.util.FileHelper; import com.brandroidtools.filemanager.util.MimeTypeHelper; import com.brandroidtools.filemanager.util.StorageHelper; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * The activity for allow to use a {@link FragmentActivity} like, to pick a file from other * application. */ public class PickerActivity extends FragmentActivity implements OnCancelListener, OnDismissListener, OnFilePickedListener, OnDirectoryChangedListener { private static final String TAG = "PickerActivity"; //$NON-NLS-1$ private static boolean DEBUG = false; private final BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent != null) { if (intent.getAction().compareTo(FileManagerSettings.INTENT_THEME_CHANGED) == 0) { applyTheme(); } } } }; // The result code private static final int RESULT_CROP_IMAGE = 1; // The component that holds the crop operation. We use Gallery3d because we are confidence // of his input parameters private static final ComponentName CROP_COMPONENT = new ComponentName("com.android.gallery3d", //$NON-NLS-1$ "com.android.gallery3d.app.CropImage"); //$NON-NLS-1$ // Gallery crop editor action private static final String ACTION_CROP = "com.android.camera.action.CROP"; //$NON-NLS-1$ // Extra data for Gallery CROP action private static final String EXTRA_CROP = "crop"; //$NON-NLS-1$ // Scheme for file and directory picking private static final String FILE_URI_SCHEME = "file"; //$NON-NLS-1$ private static final String FOLDER_URI_SCHEME = "folder"; //$NON-NLS-1$ private static final String DIRECTORY_URI_SCHEME = "directory"; //$NON-NLS-1$ FileSystemObject mFso; // The picked item FileSystemObject mCurrentDirectory; private AlertDialog mDialog; private Handler mHandler; /** * @hide */ NavigationFragment mNavigationFragment; private View mRootView; /** * {@inheritDoc} */ @Override protected void onCreate(Bundle state) { if (DEBUG) { Log.d(TAG, "PickerActivity.onCreate"); //$NON-NLS-1$ } // Register the broadcast receiver IntentFilter filter = new IntentFilter(); filter.addAction(FileManagerSettings.INTENT_THEME_CHANGED); registerReceiver(this.mNotificationReceiver, filter); // Initialize the activity init(); //Save state super.onCreate(state); } /** * {@inheritDoc} */ @Override protected void onDestroy() { if (DEBUG) { Log.d(TAG, "PickerActivity.onDestroy"); //$NON-NLS-1$ } // Unregister the receiver try { unregisterReceiver(this.mNotificationReceiver); } catch (Throwable ex) { /**NON BLOCK**/ } //All destroy. Continue super.onDestroy(); } /** * {@inheritDoc} */ @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); measureHeight(); } /** * Method that displays a dialog with a {@link NavigationFragment} to select the * proposed file */ private void init() { final boolean pickingDirectory; final Intent intent = getIntent(); if (isFilePickIntent(intent)) { // ok Log.d(TAG, "PickerActivity: got file pick intent: " + String.valueOf(intent)); //$NON-NLS-1$ pickingDirectory = false; } else if (isDirectoryPickIntent(getIntent())) { // ok Log.d(TAG, "PickerActivity: got folder pick intent: " + String.valueOf(intent)); //$NON-NLS-1$ pickingDirectory = true; } else { Log.d(TAG, "PickerActivity got unrecognized intent: " + String.valueOf(intent)); //$NON-NLS-1$ setResult(Activity.RESULT_CANCELED); finish(); return; } // Display restrictions Map<DisplayRestrictions, Object> restrictions = new HashMap<DisplayRestrictions, Object>(); //- Mime/Type restriction String mimeType = getIntent().getType(); if (mimeType != null) { if (!MimeTypeHelper.isMimeTypeKnown(this, mimeType)) { Log.i(TAG, String.format("Mime type %s unknown, falling back to wildcard.", //$NON-NLS-1$ mimeType)); mimeType = MimeTypeHelper.ALL_MIME_TYPES; } restrictions.put(DisplayRestrictions.MIME_TYPE_RESTRICTION, mimeType); } // Other restrictions Bundle extras = getIntent().getExtras(); Log.d(TAG, "PickerActivity. extras: " + String.valueOf(extras)); //$NON-NLS-1$ if (extras != null) { //-- File size if (extras.containsKey(android.provider.MediaStore.Audio.Media.EXTRA_MAX_BYTES)) { long size = extras.getLong(android.provider.MediaStore.Audio.Media.EXTRA_MAX_BYTES); restrictions.put(DisplayRestrictions.SIZE_RESTRICTION, Long.valueOf(size)); } //-- Local filesystems only if (extras.containsKey(Intent.EXTRA_LOCAL_ONLY)) { boolean localOnly = extras.getBoolean(Intent.EXTRA_LOCAL_ONLY); restrictions.put(DisplayRestrictions.LOCAL_FILESYSTEM_ONLY_RESTRICTION, Boolean.valueOf(localOnly)); } } if (pickingDirectory) { restrictions.put(DisplayRestrictions.DIRECTORY_ONLY_RESTRICTION, Boolean.TRUE); } // Create or use the console if (!initializeConsole()) { // Something when wrong. Display a message and exit DialogHelper.showToast(this, R.string.msgs_cant_create_console, Toast.LENGTH_SHORT); cancel(); return; } // Create the root file this.mRootView = getLayoutInflater().inflate(R.layout.picker, null, false); this.mRootView.post(new Runnable() { @Override public void run() { measureHeight(); } }); // Breadcrumb Breadcrumb breadcrumb = (Breadcrumb) this.mRootView.findViewById(R.id.breadcrumb_view); // Set the free disk space warning level of the breadcrumb widget String fds = Preferences.getSharedPreferences().getString( FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(), (String) FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue()); breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds)); // Navigation view this.mNavigationFragment = (NavigationFragment) getSupportFragmentManager() .findFragmentById(R.id.navigation_fragment); this.mNavigationFragment.setRestrictions(restrictions); this.mNavigationFragment.setOnFilePickedListener(this); this.mNavigationFragment.setOnDirectoryChangedListener(this); this.mNavigationFragment.setBreadcrumb(breadcrumb); // Apply the current theme applyTheme(); // Create the dialog this.mDialog = DialogHelper.createDialog(this, R.drawable.ic_launcher, pickingDirectory ? R.string.directory_picker_title : R.string.picker_title, this.mRootView); this.mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dlg, int which) { dlg.cancel(); } }); if (pickingDirectory) { this.mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.select), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dlg, int which) { PickerActivity.this.mFso = PickerActivity.this.mCurrentDirectory; dlg.dismiss(); } }); } this.mDialog.setCancelable(true); this.mDialog.setOnCancelListener(this); this.mDialog.setOnDismissListener(this); DialogHelper.delegateDialogShow(this, this.mDialog); // Set content description of storage volume button ButtonItem fs = (ButtonItem) this.mRootView.findViewById(R.id.ab_filesystem_info); fs.setContentDescription(getString(R.string.actionbar_button_storage_cd)); final File initialDir = getInitialDirectoryFromIntent(getIntent()); final String rootDirectory; if (initialDir != null) { rootDirectory = initialDir.getAbsolutePath(); } else { rootDirectory = FileHelper.ROOT_DIRECTORY; } this.mHandler = new Handler(); this.mHandler.post(new Runnable() { @Override public void run() { // Navigate to. The navigation view will redirect to the appropriate directory PickerActivity.this.mNavigationFragment.changeCurrentDir(rootDirectory); } }); } /** * Method that measure the height needed to avoid resizing when * change to a new directory. This method fixed the height of the window * @hide */ void measureHeight() { // Calculate the dialog size based on the window height DisplayMetrics displaymetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); final int height = displaymetrics.heightPixels; Configuration config = getResources().getConfiguration(); int percent = config.orientation == Configuration.ORIENTATION_LANDSCAPE ? 55 : 70; FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, (height * percent) / 100); this.mRootView.setLayoutParams(params); } /** * Method that initializes a console */ private boolean initializeConsole() { try { // Create a ChRooted console ConsoleBuilder.createDefaultConsole(this, false, false); // There is a console allocated. Use it. return true; } catch (Throwable _throw) { // Capture the exception ExceptionUtil.translateException(this, _throw, true, false); } return false; } /** * {@inheritDoc} */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case RESULT_CROP_IMAGE: // Return what the callee activity returns setResult(resultCode, data); finish(); return; default: break; } // The response is not understood Log.w(TAG, String.format("Ignore response. requestCode: %s, resultCode: %s, data: %s", //$NON-NLS-1$ Integer.valueOf(requestCode), Integer.valueOf(resultCode), data)); DialogHelper.showToast(this, R.string.msgs_operation_failure, Toast.LENGTH_SHORT); } /** * {@inheritDoc} */ @Override public void onDismiss(DialogInterface dialog) { if (this.mFso != null) { File src = new File(this.mFso.getFullPath()); if (getIntent().getExtras() != null) { // Some AOSP applications use the gallery to edit and crop the selected image // with the Gallery crop editor. In this case pass the picked file to the // CropActivity with the requested parameters // Expected result is on onActivityResult Bundle extras = getIntent().getExtras(); String crop = extras.getString(EXTRA_CROP); if (Boolean.parseBoolean(crop)) { // We want to use the Gallery3d activity because we know about it, and his // parameters. At least we have a compatible one. Intent intent = new Intent(ACTION_CROP); if (getIntent().getType() != null) { intent.setType(getIntent().getType()); } intent.setData(Uri.fromFile(src)); intent.putExtras(extras); intent.setComponent(CROP_COMPONENT); startActivityForResult(intent, RESULT_CROP_IMAGE); return; } } // Return the picked file, as expected (this activity should fill the intent data // and return RESULT_OK result) Intent result = new Intent(); result.setData(getResultUriForFileFromIntent(src, getIntent())); setResult(Activity.RESULT_OK, result); finish(); } else { cancel(); } } private boolean isFilePickIntent(Intent intent) { final String action = intent.getAction(); if (Intent.ACTION_GET_CONTENT.equals(action)) { return true; } if (Intent.ACTION_PICK.equals(action)) { final Uri data = intent.getData(); if (data != null && FILE_URI_SCHEME.equals(data.getScheme())) { return true; } } return false; } private boolean isDirectoryPickIntent(Intent intent) { if (Intent.ACTION_PICK.equals(intent.getAction()) && intent.getData() != null) { String scheme = intent.getData().getScheme(); if (FOLDER_URI_SCHEME.equals(scheme) || DIRECTORY_URI_SCHEME.equals(scheme)) { return true; } } return false; } private File getInitialDirectoryFromIntent(Intent intent) { if (!Intent.ACTION_PICK.equals(intent.getAction())) { return null; } final Uri data = intent.getData(); if (data == null) { return null; } final String path = data.getPath(); if (path == null) { return null; } final File file = new File(path); if (!file.exists() || !file.isAbsolute()) { return null; } if (file.isDirectory()) { return file; } return file.getParentFile(); } private Uri getResultUriForFileFromIntent(File src, Intent intent) { Uri result = Uri.fromFile(src); if (Intent.ACTION_PICK.equals(intent.getAction()) && intent.getData() != null) { String scheme = intent.getData().getScheme(); if (scheme != null) { result = result.buildUpon().scheme(scheme).build(); } } return result; } /** * {@inheritDoc} */ @Override public void onCancel(DialogInterface dialog) { cancel(); } /** * {@inheritDoc} */ @Override public void onFilePicked(FileSystemObject item) { this.mFso = item; this.mDialog.dismiss(); } /** * {@inheritDoc} */ @Override public void onDirectoryChanged(FileSystemObject item) { this.mCurrentDirectory = item; } /** * Method invoked when an action item is clicked. * * @param view The button pushed */ public void onActionBarItemClick(View view) { switch (view.getId()) { //###################### //Breadcrumb Actions //###################### case R.id.ab_filesystem_info: //Show a popup with the storage volumes to select showStorageVolumesPopUp(view); break; default: break; } } /** * Method that cancels the activity */ private void cancel() { setResult(Activity.RESULT_CANCELED); finish(); } /** * Method that shows a popup with the storage volumes * * @param anchor The view on which anchor the popup */ private void showStorageVolumesPopUp(View anchor) { // Create a list (but not checkable) final FileSystemStorageVolume[] volumes = StorageHelper.getStorageVolumes(PickerActivity.this); List<CheckableItem> descriptions = new ArrayList<CheckableItem>(); if (volumes != null) { int cc = volumes.length; for (int i = 0; i < cc; i++) { String desc = StorageHelper.getStorageVolumeDescription(this, volumes[i]); CheckableItem item = new CheckableItem(desc, false, false); descriptions.add(item); } } CheckableListAdapter adapter = new CheckableListAdapter(getApplicationContext(), descriptions); //Create a show the popup menu final ListPopupWindow popup = DialogHelper.createListPopupWindow(this, adapter, anchor); popup.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View v, int position, long id) { popup.dismiss(); if (volumes != null) { PickerActivity.this.mNavigationFragment.changeCurrentDir(volumes[position].getPath()); } } }); popup.show(); } /** * Method that applies the current theme to the activity * @hide */ void applyTheme() { Theme theme = ThemeManager.getCurrentTheme(this); theme.setBaseTheme(this, true); // View theme.setBackgroundDrawable(this, this.mRootView, "background_drawable"); //$NON-NLS-1$ this.mNavigationFragment.applyTheme(); } }