Refactor DocsUI to break out a new ManageRootActivity.
- Split all ACTION_MANAGE-related functionality off from
DocumentsActivity, into a new activity.
- Create new full-screen layouts for said activity.
- Fix some styling issues in {Documents,Files}Activity.
Change-Id: I0384715ad3c7d70a3a3daf510f1a09e8c5732348
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index d578769..97bc8fd 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -36,12 +36,18 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
- <action android:name="android.provider.action.MANAGE_ROOT" />
+ <action android:name="android.provider.action.BROWSE_DOCUMENT_ROOT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.document/root" />
</intent-filter>
+ </activity>
+
+ <activity
+ android:name=".ManageRootActivity"
+ android:theme="@style/DocumentsNonDialogTheme"
+ android:icon="@drawable/ic_doc_text">
<intent-filter>
- <action android:name="android.provider.action.BROWSE_DOCUMENT_ROOT" />
+ <action android:name="android.provider.action.MANAGE_ROOT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.document/root" />
</intent-filter>
diff --git a/res/layout/directory_cluster.xml b/res/layout/directory_cluster.xml
new file mode 100644
index 0000000..e47e196
--- /dev/null
+++ b/res/layout/directory_cluster.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <com.android.documentsui.DirectoryContainerView
+ android:id="@+id/container_directory"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+ <FrameLayout
+ android:id="@+id/container_save"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@color/material_grey_50"
+ android:elevation="8dp" />
+
+</LinearLayout>
diff --git a/res/layout/drawer_layout.xml b/res/layout/drawer_layout.xml
index 32431e3..dec4e92 100644
--- a/res/layout/drawer_layout.xml
+++ b/res/layout/drawer_layout.xml
@@ -30,7 +30,8 @@
android:layout_height="?android:attr/actionBarSize"
android:background="?android:attr/colorPrimary"
android:elevation="8dp"
- android:theme="?android:attr/actionBarTheme">
+ android:theme="?actionBarTheme"
+ android:popupTheme="?actionBarPopupTheme">
<Spinner
android:id="@+id/stack"
@@ -41,18 +42,7 @@
</com.android.documentsui.DocumentsToolBar>
- <com.android.documentsui.DirectoryContainerView
- android:id="@+id/container_directory"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1" />
-
- <FrameLayout
- android:id="@+id/container_save"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@color/material_grey_50"
- android:elevation="8dp" />
+ <include layout="@layout/directory_cluster"/>
</LinearLayout>
@@ -71,7 +61,8 @@
android:layout_height="?android:attr/actionBarSize"
android:background="?android:attr/colorPrimary"
android:elevation="8dp"
- android:theme="?android:attr/actionBarTheme" />
+ android:theme="?actionBarTheme"
+ android:popupTheme="?actionBarPopupTheme" />
<FrameLayout
android:id="@+id/container_roots"
diff --git a/res/layout/fixed_layout.xml b/res/layout/fixed_layout.xml
index 9769f26..eba9af4 100644
--- a/res/layout/fixed_layout.xml
+++ b/res/layout/fixed_layout.xml
@@ -51,28 +51,11 @@
android:layout_width="256dp"
android:layout_height="match_parent" />
- <LinearLayout
+ <include layout="@layout/directory_cluster"
android:layout_width="0dp"
- android:layout_height="match_parent"
android:layout_weight="1"
- android:orientation="vertical"
- android:background="@color/material_grey_50"
- android:elevation="8dp">
-
- <com.android.documentsui.DirectoryContainerView
- android:id="@+id/container_directory"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1" />
-
- <FrameLayout
- android:id="@+id/container_save"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@color/material_grey_50"
- android:elevation="8dp" />
-
- </LinearLayout>
+ android:elevation="8dp"
+ android:background="@color/material_grey_50" />
</LinearLayout>
diff --git a/res/layout/single_pane_layout.xml b/res/layout/single_pane_layout.xml
new file mode 100644
index 0000000..20c3232
--- /dev/null
+++ b/res/layout/single_pane_layout.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <com.android.documentsui.DocumentsToolBar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/actionBarSize"
+ android:background="?android:attr/colorPrimary"
+ android:elevation="8dp"
+ android:theme="?actionBarTheme"
+ android:popupTheme="?actionBarPopupTheme">
+
+ <Spinner
+ android:id="@+id/stack"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="4dp"
+ android:overlapAnchor="true" />
+
+ </com.android.documentsui.DocumentsToolBar>
+
+ <include layout="@layout/directory_cluster"/>
+
+</LinearLayout>
diff --git a/res/menu/activity.xml b/res/menu/activity.xml
index e1f6562..7df152f 100644
--- a/res/menu/activity.xml
+++ b/res/menu/activity.xml
@@ -26,7 +26,8 @@
android:id="@+id/menu_create_dir"
android:title="@string/menu_create_dir"
android:icon="@drawable/ic_menu_new_folder"
- android:showAsAction="always" />
+ android:showAsAction="always"
+ android:visible="false" />
<item
android:id="@+id/menu_sort"
android:title="@string/menu_sort"
@@ -62,10 +63,12 @@
android:visible="false" />
<item
android:id="@+id/menu_advanced"
- android:showAsAction="never" />
+ android:showAsAction="never"
+ android:visible="false" />
<item
android:id="@+id/menu_file_size"
- android:showAsAction="never" />
+ android:showAsAction="never"
+ android:visible="false" />
<item
android:id="@+id/menu_settings"
android:title="@string/menu_settings"
diff --git a/res/values/layouts.xml b/res/values/layouts.xml
index c73a1cb..8ac1ac2 100644
--- a/res/values/layouts.xml
+++ b/res/values/layouts.xml
@@ -17,4 +17,5 @@
<resources>
<item name="docs_activity" type="layout">@layout/drawer_layout</item>
<item name="files_activity" type="layout">@layout/drawer_layout</item>
+ <item name="manage_roots_activity" type="layout">@layout/single_pane_layout</item>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 22add98..e67f956 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -57,6 +57,10 @@
<item name="android:colorPrimaryDark">@color/primary_dark</item>
<item name="android:colorPrimary">@color/primary</item>
<item name="android:colorAccent">@color/accent</item>
+
+ <item name="android:actionModeStyle">@style/ActionModeStyle</item>
+
+ <item name="android:alertDialogTheme">@style/AlertDialogTheme</item>
</style>
<style name="ActionModeStyle" parent="@android:style/Widget.Material.Light.ActionMode">
diff --git a/src/com/android/documentsui/BaseActivity.java b/src/com/android/documentsui/BaseActivity.java
index 2835106..1e7a42f 100644
--- a/src/com/android/documentsui/BaseActivity.java
+++ b/src/com/android/documentsui/BaseActivity.java
@@ -16,6 +16,13 @@
package com.android.documentsui;
+import static com.android.documentsui.BaseActivity.State.ACTION_BROWSE;
+import static com.android.documentsui.BaseActivity.State.ACTION_CREATE;
+import static com.android.documentsui.BaseActivity.State.ACTION_GET_CONTENT;
+import static com.android.documentsui.BaseActivity.State.ACTION_MANAGE;
+import static com.android.documentsui.BaseActivity.State.ACTION_OPEN;
+import static com.android.documentsui.BaseActivity.State.ACTION_OPEN_COPY_DESTINATION;
+import static com.android.documentsui.BaseActivity.State.ACTION_OPEN_TREE;
import static com.android.documentsui.DirectoryFragment.ANIM_DOWN;
import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
import static com.android.documentsui.DirectoryFragment.ANIM_SIDE;
@@ -47,7 +54,6 @@
import android.view.MenuItem.OnActionExpandListener;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewStub;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.BaseAdapter;
@@ -85,7 +91,6 @@
private int mLayoutId;
private final String mTag;
- public abstract State getDisplayState();
public abstract void onDocumentPicked(DocumentInfo doc, @Nullable DocumentContext siblings);
public abstract void onDocumentsPicked(List<DocumentInfo> docs);
@@ -93,7 +98,7 @@
abstract void onDirectoryChanged(int anim);
abstract void updateActionBar();
abstract void saveStackBlocking();
- abstract State buildDefaultState();
+ abstract State buildState();
public BaseActivity(@LayoutRes int layoutId, String tag) {
mLayoutId = layoutId;
@@ -106,7 +111,7 @@
mState = (icicle != null)
? icicle.<State>getParcelable(EXTRA_STATE)
- : buildDefaultState();
+ : buildState();
setContentView(mLayoutId);
@@ -154,30 +159,46 @@
final MenuItem sortSize = menu.findItem(R.id.menu_sort_size);
final MenuItem grid = menu.findItem(R.id.menu_grid);
final MenuItem list = menu.findItem(R.id.menu_list);
-
final MenuItem advanced = menu.findItem(R.id.menu_advanced);
final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
+ final MenuItem settings = menu.findItem(R.id.menu_settings);
mSearchManager.update(root);
// Search uses backend ranking; no sorting
sort.setVisible(cwd != null && !mSearchManager.isSearching());
- State state = getDisplayState();
- grid.setVisible(state.derivedMode != State.MODE_GRID);
- list.setVisible(state.derivedMode != State.MODE_LIST);
-
- // Only sort by size when visible
- sortSize.setVisible(state.showSize);
-
advanced.setTitle(LocalPreferences.getDisplayAdvancedDevices(this)
? R.string.menu_advanced_hide : R.string.menu_advanced_show);
fileSize.setTitle(LocalPreferences.getDisplayFileSize(this)
? R.string.menu_file_size_hide : R.string.menu_file_size_show);
+ State state = getDisplayState();
+
+ sortSize.setVisible(state.showSize); // Only sort by size when visible
+ grid.setVisible(state.derivedMode != State.MODE_GRID);
+ list.setVisible(state.derivedMode != State.MODE_LIST);
+ settings.setVisible((root.flags & Root.FLAG_HAS_SETTINGS) != 0);
+
return shown;
}
+ State buildDefaultState() {
+ State state = new State();
+
+ final Intent intent = getIntent();
+ final String action = intent.getAction();
+
+ state.localOnly = intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false);
+ state.forceAdvanced = intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false);
+ state.showAdvanced = state.forceAdvanced ||
+ LocalPreferences.getDisplayAdvancedDevices(this);
+
+ state.excludedAuthorities = getExcludedAuthorities();
+
+ return state;
+ }
+
void onStackRestored(boolean restored, boolean external) {}
void onRootPicked(RootInfo root) {
@@ -344,6 +365,10 @@
return (BaseActivity) fragment.getActivity();
}
+ public State getDisplayState() {
+ return mState;
+ }
+
public static abstract class DocumentsIntent {
/** Intent action name to open copy destination. */
public static String ACTION_OPEN_COPY_DESTINATION =
@@ -664,6 +689,33 @@
}
}
+ final class RestoreRootTask extends AsyncTask<Void, Void, RootInfo> {
+ private Uri mRootUri;
+
+ public RestoreRootTask(Uri rootUri) {
+ mRootUri = rootUri;
+ }
+
+ @Override
+ protected RootInfo doInBackground(Void... params) {
+ final String rootId = DocumentsContract.getRootId(mRootUri);
+ return mRoots.getRootOneshot(mRootUri.getAuthority(), rootId);
+ }
+
+ @Override
+ protected void onPostExecute(RootInfo root) {
+ if (isDestroyed()) return;
+ mState.restored = true;
+
+ if (root != null) {
+ onRootPicked(root);
+ } else {
+ Log.w(mTag, "Failed to find root: " + mRootUri);
+ finish();
+ }
+ }
+ }
+
final class ItemSelectedListener implements OnItemSelectedListener {
boolean mIgnoreNextNavigation;
diff --git a/src/com/android/documentsui/DirectoryFragment.java b/src/com/android/documentsui/DirectoryFragment.java
index 93921dd..4ce404b 100644
--- a/src/com/android/documentsui/DirectoryFragment.java
+++ b/src/com/android/documentsui/DirectoryFragment.java
@@ -77,6 +77,7 @@
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import android.util.TypedValue;
import android.view.ActionMode;
import android.view.DragEvent;
import android.view.GestureDetector;
@@ -650,8 +651,12 @@
if (mActionMode != null) {
mActionMode.finish();
}
- getActivity().getWindow().setStatusBarColor(
- getResources().getColor(R.color.status_bar_background));
+ // Obtain the original status bar color from the theme, and restore it.
+ TypedValue color = new TypedValue();
+ getActivity().getTheme().resolveAttribute(
+ android.R.attr.colorPrimaryDark, color, true);
+ getActivity().getWindow().setStatusBarColor(color.data);
+
}
if (mActionMode != null) {
diff --git a/src/com/android/documentsui/DocumentsActivity.java b/src/com/android/documentsui/DocumentsActivity.java
index fdc4bb0..1de1c6a 100644
--- a/src/com/android/documentsui/DocumentsActivity.java
+++ b/src/com/android/documentsui/DocumentsActivity.java
@@ -19,7 +19,6 @@
import static com.android.documentsui.BaseActivity.State.ACTION_BROWSE;
import static com.android.documentsui.BaseActivity.State.ACTION_CREATE;
import static com.android.documentsui.BaseActivity.State.ACTION_GET_CONTENT;
-import static com.android.documentsui.BaseActivity.State.ACTION_MANAGE;
import static com.android.documentsui.BaseActivity.State.ACTION_OPEN;
import static com.android.documentsui.BaseActivity.State.ACTION_OPEN_COPY_DESTINATION;
import static com.android.documentsui.BaseActivity.State.ACTION_OPEN_TREE;
@@ -67,7 +66,7 @@
public class DocumentsActivity extends BaseActivity {
private static final int CODE_FORWARD = 42;
- public static final String TAG = "Documents";
+ private static final String TAG = "DocumentsActivity";
private boolean mShowAsDialog;
@@ -90,8 +89,7 @@
super.onCreate(icicle);
final Resources res = getResources();
- mShowAsDialog = res.getBoolean(R.bool.show_as_dialog) && mState.action != ACTION_MANAGE &&
- mState.action != ACTION_BROWSE;
+ mShowAsDialog = res.getBoolean(R.bool.show_as_dialog) && mState.action != ACTION_BROWSE;
if (!mShowAsDialog) {
setTheme(R.style.DocumentsNonDialogTheme);
@@ -119,8 +117,6 @@
mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
- mToolbar.setTitleTextAppearance(context,
- android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
mStackAdapter = new StackAdapter();
mStackListener = new ItemSelectedListener();
@@ -128,15 +124,11 @@
mToolbarStack.setOnItemSelectedListener(mStackListener);
mRootsToolbar = (Toolbar) findViewById(R.id.roots_toolbar);
- if (mRootsToolbar != null) {
- mRootsToolbar.setTitleTextAppearance(context,
- android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
- }
setActionBar(mToolbar);
// Hide roots when we're managing a specific root
- if (mState.action == ACTION_MANAGE || mState.action == ACTION_BROWSE) {
+ if (mState.action == ACTION_BROWSE) {
mDrawer.lockClosed();
if (mShowAsDialog) {
findViewById(R.id.container_roots).setVisibility(View.GONE);
@@ -168,7 +160,7 @@
// In this case, we set the activity title in AsyncTask.onPostExecute(). To prevent
// talkback from reading aloud the default title, we clear it here.
setTitle("");
- if (mState.action == ACTION_MANAGE || mState.action == ACTION_BROWSE) {
+ if (mState.action == ACTION_BROWSE) {
final Uri rootUri = getIntent().getData();
new RestoreRootTask(rootUri).executeOnExecutor(getCurrentExecutor());
} else {
@@ -180,8 +172,8 @@
}
@Override
- State buildDefaultState() {
- State state = new State();
+ State buildState() {
+ State state = buildDefaultState();
final Intent intent = getIntent();
final String action = intent.getAction();
@@ -193,8 +185,6 @@
state.action = ACTION_GET_CONTENT;
} else if (Intent.ACTION_OPEN_DOCUMENT_TREE.equals(action)) {
state.action = ACTION_OPEN_TREE;
- } else if (DocumentsContract.ACTION_MANAGE_ROOT.equals(action)) {
- state.action = ACTION_MANAGE;
} else if (DocumentsContract.ACTION_BROWSE_DOCUMENT_ROOT.equals(action)) {
state.action = ACTION_BROWSE;
} else if (DocumentsIntent.ACTION_OPEN_COPY_DESTINATION.equals(action)) {
@@ -206,7 +196,7 @@
Intent.EXTRA_ALLOW_MULTIPLE, false);
}
- if (state.action == ACTION_MANAGE || state.action == ACTION_BROWSE) {
+ if (state.action == ACTION_BROWSE) {
state.acceptMimes = new String[] { "*/*" };
state.allowMultiple = true;
} else if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
@@ -215,12 +205,7 @@
state.acceptMimes = new String[] { intent.getType() };
}
- state.localOnly = intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false);
- state.forceAdvanced = intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false);
- state.showAdvanced = state.forceAdvanced
- | LocalPreferences.getDisplayAdvancedDevices(this);
-
- if (state.action == ACTION_MANAGE || state.action == ACTION_BROWSE) {
+ if (state.action == ACTION_BROWSE) {
state.showSize = true;
} else {
state.showSize = LocalPreferences.getDisplayFileSize(this);
@@ -232,38 +217,9 @@
CopyService.TRANSFER_MODE_NONE);
}
- state.excludedAuthorities = getExcludedAuthorities();
-
return state;
}
- private class RestoreRootTask extends AsyncTask<Void, Void, RootInfo> {
- private Uri mRootUri;
-
- public RestoreRootTask(Uri rootUri) {
- mRootUri = rootUri;
- }
-
- @Override
- protected RootInfo doInBackground(Void... params) {
- final String rootId = DocumentsContract.getRootId(mRootUri);
- return mRoots.getRootOneshot(mRootUri.getAuthority(), rootId);
- }
-
- @Override
- protected void onPostExecute(RootInfo root) {
- if (isDestroyed()) return;
- mState.restored = true;
-
- if (root != null) {
- onRootPicked(root);
- } else {
- Log.w(TAG, "Failed to find root: " + mRootUri);
- finish();
- }
- }
- }
-
@Override
void onStackRestored(boolean restored, boolean external) {
// Show drawer when no stack restored, but only when requesting
@@ -405,8 +361,11 @@
final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
final MenuItem settings = menu.findItem(R.id.menu_settings);
- boolean fileSizeVisible = !(mState.action == ACTION_MANAGE
- || mState.action == ACTION_BROWSE);
+ // File size is locked visible for browse because that is the action triggered by Settings,
+ // where the user is trying to find large files to clean up.
+ // TODO: instead of setting this according to the action, use a local preference, but
+ // provide a @hide extra to let callers like Settings force-enable size visibility.
+ boolean fileSizeVisible = mState.action != ACTION_BROWSE;
if (mState.action == ACTION_CREATE
|| mState.action == ACTION_OPEN_TREE
|| mState.action == ACTION_OPEN_COPY_DESTINATION) {
@@ -428,11 +387,10 @@
createDir.setVisible(false);
}
- advanced.setVisible(!(mState.action == ACTION_MANAGE || mState.action == ACTION_BROWSE) &&
- !mState.forceAdvanced);
+ advanced.setVisible(mState.action != ACTION_BROWSE && !mState.forceAdvanced);
fileSize.setVisible(fileSizeVisible);
- settings.setVisible((mState.action == ACTION_MANAGE || mState.action == ACTION_BROWSE)
+ settings.setVisible(mState.action == ACTION_BROWSE
&& (root.flags & Root.FLAG_HAS_SETTINGS) != 0);
return true;
@@ -444,11 +402,6 @@
}
@Override
- public State getDisplayState() {
- return mState;
- }
-
- @Override
void onDirectoryChanged(int anim) {
final FragmentManager fm = getFragmentManager();
final RootInfo root = getCurrentRoot();
@@ -523,26 +476,6 @@
} else if (mState.action == ACTION_CREATE) {
// Replace selected file
SaveFragment.get(fm).setReplaceTarget(doc);
- } else if (mState.action == ACTION_MANAGE) {
- // First try managing the document; we expect manager to filter
- // based on authority, so we don't grant.
- final Intent manage = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENT);
- manage.setData(doc.derivedUri);
-
- try {
- startActivity(manage);
- } catch (ActivityNotFoundException ex) {
- // Fall back to viewing
- final Intent view = new Intent(Intent.ACTION_VIEW);
- view.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- view.setData(doc.derivedUri);
-
- try {
- startActivity(view);
- } catch (ActivityNotFoundException ex2) {
- Toast.makeText(this, R.string.toast_no_application, Toast.LENGTH_SHORT).show();
- }
- }
} else if (mState.action == ACTION_BROWSE) {
// Go straight to viewing
final Intent view = new Intent(Intent.ACTION_VIEW);
diff --git a/src/com/android/documentsui/FilesActivity.java b/src/com/android/documentsui/FilesActivity.java
index 7c445bf..8f9025a 100644
--- a/src/com/android/documentsui/FilesActivity.java
+++ b/src/com/android/documentsui/FilesActivity.java
@@ -30,7 +30,6 @@
import android.net.Uri;
import android.os.Bundle;
import android.provider.DocumentsContract;
-import android.provider.DocumentsContract.Root;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.KeyEvent;
@@ -58,12 +57,11 @@
*/
public class FilesActivity extends BaseActivity {
- public static final String TAG = "StandaloneFileManagement";
+ public static final String TAG = "FilesActivity";
static final boolean DEBUG = false;
private Toolbar mToolbar;
private Spinner mToolbarStack;
- private Toolbar mRootsToolbar;
private DirectoryContainerView mDirectoryContainer;
private ItemSelectedListener mStackListener;
private BaseAdapter mStackAdapter;
@@ -82,20 +80,12 @@
mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
- mToolbar.setTitleTextAppearance(context,
- android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
mStackAdapter = new StackAdapter();
mStackListener = new ItemSelectedListener();
mToolbarStack = (Spinner) findViewById(R.id.stack);
mToolbarStack.setOnItemSelectedListener(mStackListener);
- mRootsToolbar = (Toolbar) findViewById(R.id.roots_toolbar);
- if (mRootsToolbar != null) {
- mRootsToolbar.setTitleTextAppearance(context,
- android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
- }
-
setActionBar(mToolbar);
mClipper = new DocumentClipper(this);
@@ -127,14 +117,14 @@
}
@Override
- State buildDefaultState() {
- State state = new State();
+ State buildState() {
+ State state = buildDefaultState();
final Intent intent = getIntent();
+
state.action = State.ACTION_BROWSE_ALL;
- state.acceptMimes = new String[] { "*/*" };
- state.allowMultiple = true;
state.acceptMimes = new String[] { intent.getType() };
+ state.allowMultiple = true;
// These options are specific to the DocumentsActivity.
Preconditions.checkArgument(
@@ -223,8 +213,6 @@
createDir.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
createDir.setVisible(canCreateDir);
- settings.setVisible((getCurrentRoot().flags & Root.FLAG_HAS_SETTINGS) != 0);
-
pasteFromCb.setVisible(true);
pasteFromCb.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
pasteFromCb.setEnabled(mClipper.hasItemsToPaste());
@@ -246,11 +234,6 @@
}
@Override
- public State getDisplayState() {
- return mState;
- }
-
- @Override
void onDirectoryChanged(int anim) {
final FragmentManager fm = getFragmentManager();
final RootInfo root = getCurrentRoot();
diff --git a/src/com/android/documentsui/IconUtils.java b/src/com/android/documentsui/IconUtils.java
index 9959265..ec1cb1d 100644
--- a/src/com/android/documentsui/IconUtils.java
+++ b/src/com/android/documentsui/IconUtils.java
@@ -222,7 +222,7 @@
return context.getDrawable(R.drawable.ic_doc_album);
}
- if (mode == DocumentsActivity.State.MODE_GRID) {
+ if (mode == BaseActivity.State.MODE_GRID) {
return context.getDrawable(R.drawable.ic_grid_folder);
} else {
return context.getDrawable(R.drawable.ic_doc_folder);
diff --git a/src/com/android/documentsui/ManageRootActivity.java b/src/com/android/documentsui/ManageRootActivity.java
new file mode 100644
index 0000000..7401578
--- /dev/null
+++ b/src/com/android/documentsui/ManageRootActivity.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2013 The Android Open Source 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.android.documentsui;
+
+import static com.android.documentsui.BaseActivity.State.ACTION_MANAGE;
+import static com.android.documentsui.DirectoryFragment.ANIM_DOWN;
+import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.ActivityNotFoundException;
+import android.content.ClipData;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.DocumentsContract;
+import android.util.Log;
+import android.view.Menu;
+import android.view.View;
+import android.widget.BaseAdapter;
+import android.widget.Spinner;
+import android.widget.Toast;
+import android.widget.Toolbar;
+
+import com.android.documentsui.RecentsProvider.ResumeColumns;
+import com.android.documentsui.model.DocumentInfo;
+import com.android.documentsui.model.DurableUtils;
+import com.android.documentsui.model.RootInfo;
+import com.android.internal.util.Preconditions;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class ManageRootActivity extends BaseActivity {
+ private static final int CODE_FORWARD = 42;
+ private static final String TAG = "ManageRootsActivity";
+
+ private Toolbar mToolbar;
+ private Spinner mToolbarStack;
+
+ private DirectoryContainerView mDirectoryContainer;
+
+ private ItemSelectedListener mStackListener;
+ private BaseAdapter mStackAdapter;
+
+ public ManageRootActivity() {
+ super(R.layout.manage_roots_activity, TAG);
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ final Context context = this;
+
+ mDrawer = DrawerController.createDummy();
+
+ mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
+
+ mToolbar = (Toolbar) findViewById(R.id.toolbar);
+ mToolbar.setTitleTextAppearance(context,
+ android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
+
+ mStackAdapter = new StackAdapter();
+ mStackListener = new ItemSelectedListener();
+ mToolbarStack = (Spinner) findViewById(R.id.stack);
+ mToolbarStack.setOnItemSelectedListener(mStackListener);
+
+ setActionBar(mToolbar);
+
+ if (!mState.restored) {
+ // In this case, we set the activity title in AsyncTask.onPostExecute(). To prevent
+ // talkback from reading aloud the default title, we clear it here.
+ setTitle("");
+ final Uri rootUri = getIntent().getData();
+ new RestoreRootTask(rootUri).executeOnExecutor(getCurrentExecutor());
+ } else {
+ onCurrentDirectoryChanged(ANIM_NONE);
+ }
+ }
+
+ @Override
+ State buildState() {
+ State state = buildDefaultState();
+
+ state.action = ACTION_MANAGE;
+ state.acceptMimes = new String[] { "*/*" };
+ state.allowMultiple = true;
+ state.showSize = true;
+ state.excludedAuthorities = getExcludedAuthorities();
+
+ return state;
+ }
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+ updateActionBar();
+ }
+
+ @Override
+ public void updateActionBar() {
+ // No navigation in manage root mode.
+ mToolbar.setNavigationIcon(null);
+ mToolbar.setNavigationOnClickListener(null);
+
+ if (mSearchManager.isExpanded()) {
+ mToolbar.setTitle(null);
+ mToolbarStack.setVisibility(View.GONE);
+ mToolbarStack.setAdapter(null);
+ } else {
+ if (mState.stack.size() <= 1) {
+ mToolbar.setTitle(getCurrentRoot().title);
+ mToolbarStack.setVisibility(View.GONE);
+ mToolbarStack.setAdapter(null);
+ } else {
+ mToolbar.setTitle(null);
+ mToolbarStack.setVisibility(View.VISIBLE);
+ mToolbarStack.setAdapter(mStackAdapter);
+
+ mStackListener.mIgnoreNextNavigation = true;
+ mToolbarStack.setSelection(mStackAdapter.getCount() - 1);
+ }
+ }
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ return true;
+ }
+
+ @Override
+ void onDirectoryChanged(int anim) {
+ final FragmentManager fm = getFragmentManager();
+ final RootInfo root = getCurrentRoot();
+ final DocumentInfo cwd = getCurrentDirectory();
+
+ // If started in manage roots mode, there has to be a cwd (i.e. the root dir of the managed
+ // root).
+ Preconditions.checkNotNull(cwd);
+ mDirectoryContainer.setDrawDisappearingFirst(anim == ANIM_DOWN);
+
+ if (mState.currentSearch != null) {
+ // Ongoing search
+ DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim);
+ } else {
+ // Normal boring directory
+ DirectoryFragment.showNormal(fm, root, cwd, anim);
+ }
+ }
+
+ @Override
+ public void onDocumentPicked(DocumentInfo doc, DocumentContext context) {
+ final FragmentManager fm = getFragmentManager();
+ if (doc.isDirectory()) {
+ openDirectory(doc);
+ } else {
+ // First try managing the document; we expect manager to filter
+ // based on authority, so we don't grant.
+ final Intent manage = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENT);
+ manage.setData(doc.derivedUri);
+
+ try {
+ startActivity(manage);
+ } catch (ActivityNotFoundException ex) {
+ // Fall back to viewing
+ final Intent view = new Intent(Intent.ACTION_VIEW);
+ view.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ view.setData(doc.derivedUri);
+
+ try {
+ startActivity(view);
+ } catch (ActivityNotFoundException ex2) {
+ Toast.makeText(this, R.string.toast_no_application, Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onDocumentsPicked(List<DocumentInfo> docs) {}
+
+ @Override
+ void saveStackBlocking() {
+ final ContentResolver resolver = getContentResolver();
+ final ContentValues values = new ContentValues();
+
+ final byte[] rawStack = DurableUtils.writeToArrayOrNull(mState.stack);
+
+ // Remember location for next app launch
+ final String packageName = getCallingPackageMaybeExtra();
+ values.clear();
+ values.put(ResumeColumns.STACK, rawStack);
+ values.put(ResumeColumns.EXTERNAL, 0);
+ resolver.insert(RecentsProvider.buildResume(packageName), values);
+ }
+
+ @Override
+ void onTaskFinished(Uri... uris) {
+ Log.d(TAG, "onFinished() " + Arrays.toString(uris));
+
+ final Intent intent = new Intent();
+ if (uris.length == 1) {
+ intent.setData(uris[0]);
+ } else if (uris.length > 1) {
+ final ClipData clipData = new ClipData(
+ null, mState.acceptMimes, new ClipData.Item(uris[0]));
+ for (int i = 1; i < uris.length; i++) {
+ clipData.addItem(new ClipData.Item(uris[i]));
+ }
+ intent.setClipData(clipData);
+ }
+
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
+
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ }
+
+ public static ManageRootActivity get(Fragment fragment) {
+ return (ManageRootActivity) fragment.getActivity();
+ }
+}