<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.SET_PREFERRED_APPLICATIONS" />
+ <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<application
android:name="ExplorerApplication"
android:label="@string/app_name"
android:launchMode="singleTop"
android:uiOptions="none"
- android:windowSoftInputMode="adjustNothing" >
+ android:windowSoftInputMode="adjustNothing"
+ android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
android:name=".activities.BookmarksActivity"
android:label="@string/bookmarks"
android:uiOptions="none"
- android:windowSoftInputMode="adjustNothing" >
+ android:windowSoftInputMode="adjustNothing"
+ android:exported="false">
</activity>
<activity
android:name=".activities.HistoryActivity"
android:label="@string/history"
android:uiOptions="none"
- android:windowSoftInputMode="adjustNothing" >
+ android:windowSoftInputMode="adjustNothing"
+ android:exported="false">
</activity>
<activity
android:label="@string/search"
android:launchMode="singleTop"
android:uiOptions="none"
- android:windowSoftInputMode="adjustNothing" >
+ android:windowSoftInputMode="adjustNothing"
+ android:exported="false">
</activity>
<activity
android:name=".activities.PickerActivity"
android:label="@string/picker"
android:uiOptions="none"
- android:theme="@style/Explorer.Theme.Holo.Ligth.Overlay">
+ android:theme="@style/Explorer.Theme.Holo.Ligth.Overlay"
+ android:exported="true">
<intent-filter>
<action android:name="android.intent.action.GET_CONTENT" />
<category android:name="android.intent.category.OPENABLE" />
</intent-filter>
</activity>
+ <activity
+ android:name=".activities.ShortcutActivity"
+ android:label="@string/app_name"
+ android:uiOptions="none"
+ android:theme="@style/Explorer.Theme.Holo.Ligth.Overlay"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ </intent-filter>
+ </activity>
+
</application>
</manifest>
android:id="@+id/mnu_actions_add_to_bookmarks_current_folder"
android:showAsAction="ifRoom"
android:title="@string/actions_menu_add_to_bookmarks"/>
+ <item
+ android:id="@+id/mnu_actions_add_shortcut_current_folder"
+ android:showAsAction="ifRoom"
+ android:title="@string/actions_menu_add_shortcut"/>
</group>
<!-- FileSystemObject Actions -->
android:showAsAction="ifRoom"
android:title="@string/actions_menu_add_to_bookmarks"/>
<item
+ android:id="@+id/mnu_actions_add_shortcut"
+ android:showAsAction="ifRoom"
+ android:title="@string/actions_menu_add_shortcut"/>
+ <item
android:id="@+id/mnu_actions_open_parent_folder"
android:showAsAction="ifRoom"
android:title="@string/actions_menu_open_parent_folder"/>
<string name="actions_menu_properties">Properties</string>
<!-- Actions Dialog * Menu * Add to bookmarks -->
<string name="actions_menu_add_to_bookmarks">Add to bookmarks</string>
+ <!-- Actions Dialog * Menu * Add shortcut -->
+ <string name="actions_menu_add_shortcut">Add shortcut</string>
<!-- Actions Dialog * Menu * Open parent folder -->
<string name="actions_menu_open_parent_folder">Open parent</string>
<string name="compression_mode_gzip" translatable="false">Gzip (gz)</string>
<string name="compression_mode_bzip" translatable="false">Bzip (bz2)</string>
+ <!-- Shortcut. Failed to handle the shortcut -->
+ <string name="shortcut_failed_msg">Failed to handle the shortcut</string>
+ <!-- Shortcut. The shortcut was created -->
+ <string name="shortcut_creation_success_msg">Shortcut created sucessfully</string>
+ <!-- Shortcut. The shortcut wasn't created -->
+ <string name="shortcut_creation_failed_msg">Shortcut creation failed</string>
+
<!-- Preferences title -->
<string name="pref">Settings</string>
<!-- Preferences * General title -->
public static final String EXTRA_SEARCH_LAST_SEARCH_DATA =
"extra_search_last_search_data"; //$NON-NLS-1$
+ /**
+ * Constant for extra information for request a navigation to the passed path.
+ */
+ public static final String EXTRA_NAVIGATE_TO =
+ "extra_navigate_to"; //$NON-NLS-1$
+
// The timeout needed to reset the exit status for back button
// After this time user need to tap 2 times the back button to
// exit, and the toast is shown again after the first tap.
initialDir = FileHelper.ROOT_DIRECTORY;
}
- //Change the current directory to the preference initial directory
- navigationView.changeCurrentDir(initialDir);
+ // Change the current directory to the preference initial directory or the
+ // request if exists
+ String navigateTo = getIntent().getStringExtra(EXTRA_NAVIGATE_TO);
+ if (navigateTo != null && navigateTo.length() > 0) {
+ navigationView.changeCurrentDir(navigateTo);
+ } else {
+ navigationView.changeCurrentDir(initialDir);
+ }
}
}
});
android.speech.RecognizerIntent.EXTRA_RESULTS, extraResults);
}
startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
+ return;
+ }
+
+ // Navigate to the requested path
+ String navigateTo = intent.getStringExtra(EXTRA_NAVIGATE_TO);
+ if (navigateTo != null && navigateTo.length() >= 0) {
+ getCurrentNavigationView().changeCurrentDir(navigateTo);
}
}
case INTENT_REQUEST_BOOKMARK:
if (resultCode == RESULT_OK) {
FileSystemObject fso =
- (FileSystemObject)data.getSerializableExtra(EXTRA_BOOKMARK_SELECTION);
+ (FileSystemObject)data.
+ getSerializableExtra(EXTRA_BOOKMARK_SELECTION);
if (fso != null) {
//Open the fso
getCurrentNavigationView().open(fso);
// Open with
else if (this.mDefaultLongClickAction.compareTo(
DefaultLongClickAction.OPEN_WITH) == 0) {
- IntentsActionPolicy.openFileSystemObject(this, fso, true);
+ IntentsActionPolicy.openFileSystemObject(this, fso, true, null, null);
}
// Show properties
} else {
// Open the file here, so when focus back to the app, the search activity
// its in top of the stack
- IntentsActionPolicy.openFileSystemObject(this, fso, false);
+ IntentsActionPolicy.openFileSystemObject(this, fso, false, null, null);
return;
}
} else {
--- /dev/null
+/*
+ * 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.cyanogenmod.explorer.activities;
+
+import android.app.Activity;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
+import android.content.DialogInterface.OnDismissListener;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.cyanogenmod.explorer.R;
+import com.cyanogenmod.explorer.console.ConsoleBuilder;
+import com.cyanogenmod.explorer.model.FileSystemObject;
+import com.cyanogenmod.explorer.ui.policy.IntentsActionPolicy;
+import com.cyanogenmod.explorer.util.CommandHelper;
+import com.cyanogenmod.explorer.util.DialogHelper;
+import com.cyanogenmod.explorer.util.ExceptionUtil;
+
+/**
+ * The activity for handle the desktop shortcuts create by the app.
+ */
+public class ShortcutActivity extends Activity implements OnCancelListener, OnDismissListener {
+
+ private static final String TAG = "ShortcutActivity"; //$NON-NLS-1$
+
+ private static boolean DEBUG = false;
+
+ /**
+ * Constant for extra information about the type of the shortcut.<br/>
+ * <br/>
+ * <ul>
+ * <li><code>navigate</code>. For folders</li>
+ * <li><code>open</code>. For files</li>
+ * </ul>
+ */
+ public static final String EXTRA_TYPE = "extra_shortcut_type"; //$NON-NLS-1$
+
+ /**
+ * Constant for extra information about the absolute path
+ */
+ public static final String EXTRA_FSO = "extra_shortcut_fso"; //$NON-NLS-1$
+
+ /**
+ * Navigable shortcut type.
+ */
+ public static final String SHORTCUT_TYPE_NAVIGATE = "navigate"; //$NON-NLS-1$
+
+ /**
+ * Openable shortcut type.
+ */
+ public static final String SHORTCUT_TYPE_OPEN = "open"; //$NON-NLS-1$
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void onCreate(Bundle state) {
+ if (DEBUG) {
+ Log.d(TAG, "PickerActivity.onCreate"); //$NON-NLS-1$
+ }
+
+ //Save state
+ super.onCreate(state);
+
+ init();
+ }
+
+ /**
+ * Initialize the activity. This method handles the passed intent, opens
+ * the appropriate activity and ends.
+ */
+ private void init() {
+ try {
+ String type = getIntent().getStringExtra(EXTRA_TYPE);
+ String path = getIntent().getStringExtra(EXTRA_FSO);
+
+ // Check that i have a valid information
+ if (type == null || type.length() == 0 || path == null || path.length() == 0) {
+ // Something is wrong
+ Log.w(TAG,
+ String.format(
+ "The shortcut intent couldn't be handled. Intent: %s", //$NON-NLS-1$
+ getIntent()));
+ DialogHelper.showToast(this, R.string.shortcut_failed_msg, Toast.LENGTH_SHORT);
+ finish();
+ return;
+ }
+ if (type.compareTo(SHORTCUT_TYPE_NAVIGATE) != 0 &&
+ type.compareTo(SHORTCUT_TYPE_OPEN) != 0) {
+ // Something is wrong
+ Log.w(TAG,
+ String.format(
+ "The shortcut intent type is unknown: %s", type)); //$NON-NLS-1$
+ DialogHelper.showToast(this, R.string.shortcut_failed_msg, Toast.LENGTH_SHORT);
+ finish();
+ return;
+ }
+
+ // Initializes the console
+ initializeConsole();
+
+ // Retrieve the fso
+ FileSystemObject fso =
+ CommandHelper.getFileInfo(getApplicationContext(), path, true, null);
+ if (fso == null) {
+ // Something is wrong
+ Log.w(TAG,
+ String.format(
+ "The fso not exists: %s", path)); //$NON-NLS-1$
+ DialogHelper.showToast(this, R.string.shortcut_failed_msg, Toast.LENGTH_SHORT);
+ finish();
+ return;
+ }
+
+
+
+ // Check what type of shortcut is registered and apply the best action
+ if (type.compareTo(SHORTCUT_TYPE_NAVIGATE) == 0) {
+ // We have to finish here; this activity is only a wrapper
+ finish();
+
+ // Forward to the NavigationActivity
+ Intent intent = new Intent(this, NavigationActivity.class);
+ intent.putExtra(NavigationActivity.EXTRA_NAVIGATE_TO, fso.getFullPath());
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(intent);
+
+
+
+ } else {
+ // Open the file. Delegate in action policy
+ IntentsActionPolicy.openFileSystemObject(this, fso, false, this, this);
+ }
+
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to handle the shortcut intent.", e); //$NON-NLS-1$
+ DialogHelper.showToast(this, R.string.shortcut_failed_msg, Toast.LENGTH_SHORT);
+ finish();
+ }
+ }
+
+ /**
+ * Method that initializes a console
+ */
+ private boolean initializeConsole() {
+ try {
+ // Is there a console allocate
+ if (!ConsoleBuilder.isAlloc()) {
+ // Create a console
+ ConsoleBuilder.getConsole(this, true);
+ }
+ // 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
+ public void onDismiss(DialogInterface dialog) {
+ // We have to finish here; this activity is only a wrapper
+ finish();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ // We have to finish here; this activity is only a wrapper
+ finish();
+ }
+
+}
//- Open
case R.id.mnu_actions_open:
- IntentsActionPolicy.openFileSystemObject(this.mContext, this.mFso, false);
+ IntentsActionPolicy.openFileSystemObject(
+ this.mContext, this.mFso, false, null, null);
break;
//- Open with
case R.id.mnu_actions_open_with:
- IntentsActionPolicy.openFileSystemObject(this.mContext, this.mFso, true);
+ IntentsActionPolicy.openFileSystemObject(
+ this.mContext, this.mFso, true, null, null);
break;
//- Execute
//- Send
case R.id.mnu_actions_send:
- IntentsActionPolicy.sendFileSystemObject(this.mContext, this.mFso);
+ IntentsActionPolicy.sendFileSystemObject(
+ this.mContext, this.mFso, null, null);
break;
BookmarksActionPolicy.addToBookmarks(this.mContext, this.mFso);
break;
+ //- Add shortcut
+ case R.id.mnu_actions_add_shortcut:
+ case R.id.mnu_actions_add_shortcut_current_folder:
+ IntentsActionPolicy.createShortcut(this.mContext, this.mFso);
+ break;
+
//- Properties
case R.id.mnu_actions_properties:
case R.id.mnu_actions_properties_current_folder:
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.pm.PackageManager;
* @param intents The list of available intents that can handle an action
* @param preferred The preferred intent. null if no preferred exists
* @param allowPreferred If allow the user to mark the selected app as preferred
+ * @param onCancelListener The cancel listener
+ * @param onDismissListener The dismiss listener
*/
public AssociationsDialog(
Context context, int icon, String title, String action,
Intent requestIntent, List<ResolveInfo> intents, ResolveInfo preferred,
- boolean allowPreferred) {
+ boolean allowPreferred, OnCancelListener onCancelListener,
+ OnDismissListener onDismissListener) {
super();
//Save the data
this.mLoaded = false;
//Initialize dialog
- init(icon, title, action);
+ init(icon, title, action, onCancelListener, onDismissListener);
}
/**
* @param icon The icon of the dialog
* @param title The title of the dialog
* @param action The title of the action button
+ * @param onCancelListener The cancel listener
+ * @param onCancelListener The dismiss listener
*/
- private void init(int icon, String title, String action) {
+ private void init(int icon, String title, String action,
+ OnCancelListener onCancelListener, OnDismissListener onDismissListener) {
boolean isPlatformSigned =
ExplorerApplication.isAppPlatformSignature(this.mContext);
DialogInterface.BUTTON_NEGATIVE,
this.mContext.getString(android.R.string.cancel),
(DialogInterface.OnClickListener)null);
+ this.mDialog.setOnCancelListener(onCancelListener);
+ this.mDialog.setOnDismissListener(onDismissListener);
}
/**
* @hide
*/
protected static void showOperationSuccessMsg(Context ctx, int res, String dst) {
- DialogHelper.showToast(ctx, ctx.getString(res, dst), Toast.LENGTH_LONG);
+ DialogHelper.showToast(ctx, ctx.getString(res, dst), Toast.LENGTH_SHORT);
}
}
\ No newline at end of file
package com.cyanogenmod.explorer.ui.policy;
import android.content.Context;
+import android.content.DialogInterface.OnCancelListener;
+import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
+import android.util.Log;
import android.widget.Toast;
import com.cyanogenmod.explorer.R;
+import com.cyanogenmod.explorer.activities.ShortcutActivity;
import com.cyanogenmod.explorer.model.FileSystemObject;
import com.cyanogenmod.explorer.ui.dialogs.AssociationsDialog;
import com.cyanogenmod.explorer.util.DialogHelper;
import com.cyanogenmod.explorer.util.ExceptionUtil;
+import com.cyanogenmod.explorer.util.FileHelper;
import com.cyanogenmod.explorer.util.MimeTypeHelper;
import java.io.File;
*/
public final class IntentsActionPolicy extends ActionsPolicy {
+ private static final String TAG = "IntentsActionPolicy"; //$NON-NLS-1$
+
private static boolean DEBUG = false;
/**
* @param ctx The current context
* @param fso The file system object
* @param choose If allow the user to select the application to open with
+ * @param onCancelListener The cancel listener
+ * @param onDismissListener The dismiss listener
*/
public static void openFileSystemObject(
- final Context ctx, final FileSystemObject fso, final boolean choose) {
+ final Context ctx, final FileSystemObject fso, final boolean choose,
+ OnCancelListener onCancelListener, OnDismissListener onDismissListener) {
try {
// Create the intent to
Intent intent = new Intent();
R.drawable.ic_holo_light_open,
R.string.associations_dialog_openwith_title,
R.string.associations_dialog_openwith_action,
- true);
+ true, onCancelListener, onDismissListener);
} catch (Exception e) {
ExceptionUtil.translateException(ctx, e);
*
* @param ctx The current context
* @param fso The file system object
+ * @param onCancelListener The cancel listener
+ * @param onDismissListener The dismiss listener
*/
public static void sendFileSystemObject(
- final Context ctx, final FileSystemObject fso) {
+ final Context ctx, final FileSystemObject fso,
+ OnCancelListener onCancelListener, OnDismissListener onDismissListener) {
try {
// Create the intent to
Intent intent = new Intent();
R.drawable.ic_holo_light_send,
R.string.associations_dialog_sendwith_title,
R.string.associations_dialog_sendwith_action,
- false);
+ false, onCancelListener, onDismissListener);
} catch (Exception e) {
ExceptionUtil.translateException(ctx, e);
* @param title The title of the dialog
* @param action The button title of the dialog
* @param allowPreferred If allow the user to mark the selected app as preferred
+ * @param onCancelListener The cancel listener
+ * @param onDismissListener The dismiss listener
*/
private static void resolveIntent(
Context ctx, Intent intent, boolean choose,
- int icon, int title, int action, boolean allowPreferred) {
+ int icon, int title, int action, boolean allowPreferred,
+ OnCancelListener onCancelListener, OnDismissListener onDismissListener) {
//Retrieve the activities that can handle the file
final PackageManager packageManager = ctx.getPackageManager();
if (DEBUG) {
intent,
info,
mPreferredInfo,
- allowPreferred);
+ allowPreferred,
+ onCancelListener,
+ onDismissListener);
dialog.show();
}
+
+ /**
+ * Method that creates a shortcut in the desktop of the device of {@link FileSystemObject}.
+ *
+ * @param ctx The current context
+ * @param fso The file system object
+ */
+ public static void createShortcut(Context ctx, FileSystemObject fso) {
+ try {
+ // Create the intent that will handle the shortcut
+ Intent shortcutIntent = new Intent(ctx, ShortcutActivity.class);
+ shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ if (FileHelper.isDirectory(fso)) {
+ shortcutIntent.putExtra(
+ ShortcutActivity.EXTRA_TYPE,ShortcutActivity.SHORTCUT_TYPE_NAVIGATE);
+ } else {
+ shortcutIntent.putExtra(
+ ShortcutActivity.EXTRA_TYPE, ShortcutActivity.SHORTCUT_TYPE_OPEN);
+ }
+ shortcutIntent.putExtra(ShortcutActivity.EXTRA_FSO, fso.getFullPath());
+
+ // The intent to send to broadcast for register the shortcut intent
+ Intent intent = new Intent();
+ intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
+ intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, fso.getName());
+ intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
+ Intent.ShortcutIconResource.fromContext(
+ ctx, MimeTypeHelper.getIcon(ctx, fso)));
+ intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT"); //$NON-NLS-1$
+ ctx.sendBroadcast(intent);
+
+ // Show the confirmation
+ DialogHelper.showToast(
+ ctx, R.string.shortcut_creation_success_msg, Toast.LENGTH_SHORT);
+
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to create the shortcut", e); //$NON-NLS-1$
+ DialogHelper.showToast(
+ ctx, R.string.shortcut_creation_failed_msg, Toast.LENGTH_SHORT);
+ }
+ }
}
\ No newline at end of file
// Open with
else if (this.mDefaultLongClickAction.compareTo(
DefaultLongClickAction.OPEN_WITH) == 0) {
- IntentsActionPolicy.openFileSystemObject(getContext(), fso, true);
+ IntentsActionPolicy.openFileSystemObject(getContext(), fso, true, null, null);
}
// Show properties
changeCurrentDir(fso.getFullPath(), searchInfo);
} else {
// Open the file with the preferred registered app
- IntentsActionPolicy.openFileSystemObject(getContext(), fso, false);
+ IntentsActionPolicy.openFileSystemObject(getContext(), fso, false, null, null);
}
}
} else {
if (this.mNavigationMode.compareTo(NAVIGATION_MODE.BROWSABLE) == 0) {
// Open the file with the preferred registered app
- IntentsActionPolicy.openFileSystemObject(getContext(), fso, false);
+ IntentsActionPolicy.openFileSystemObject(getContext(), fso, false, null, null);
} else {
// Request a file pick selection
if (this.mOnFilePickedListener != null) {