Loading src/com/android/documentsui/AbstractActionHandler.java +24 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.Intent; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Parcelable; import android.support.annotation.VisibleForTesting; import com.android.documentsui.AbstractActionHandler.CommonAddons; import com.android.documentsui.base.BooleanConsumer; Loading @@ -31,6 +32,7 @@ import com.android.documentsui.base.Lookup; import com.android.documentsui.base.RootInfo; import com.android.documentsui.base.Shared; import com.android.documentsui.base.State; import com.android.documentsui.dirlist.AnimationView; import com.android.documentsui.dirlist.AnimationView.AnimationType; import com.android.documentsui.dirlist.DocumentDetails; import com.android.documentsui.files.LauncherActivity; Loading @@ -55,6 +57,7 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons> protected final RootsAccess mRoots; protected final DocumentsAccess mDocs; protected final SelectionManager mSelectionMgr; protected final SearchViewManager mSearchMgr; protected final Lookup<String, Executor> mExecutors; public AbstractActionHandler( Loading @@ -63,6 +66,7 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons> RootsAccess roots, DocumentsAccess docs, SelectionManager selectionMgr, SearchViewManager searchMgr, Lookup<String, Executor> executors) { assert(activity != null); Loading @@ -76,6 +80,7 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons> mRoots = roots; mDocs = docs; mSelectionMgr = selectionMgr; mSearchMgr = searchMgr; mExecutors = executors; } Loading Loading @@ -150,6 +155,21 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons> throw new UnsupportedOperationException("Show chooser for doc not supported!"); } @Override public void openContainerDocument(DocumentInfo doc) { assert(doc.isContainer()); mActivity.notifyDirectoryNavigated(doc.derivedUri); mState.pushDocument(doc); // Show an opening animation only if pressing "back" would get us back to the // previous directory. Especially after opening a root document, pressing // back, wouldn't go to the previous root, but close the activity. final int anim = (mState.hasLocationChanged() && mState.stack.size() > 1) ? AnimationView.ANIM_ENTER : AnimationView.ANIM_NONE; mActivity.refreshCurrentRootAndDirectory(anim); } @Override public void deleteSelectedDocuments() { throw new UnsupportedOperationException("Delete not supported!"); Loading Loading @@ -179,6 +199,7 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons> protected Selection getStableSelection() { return mSelectionMgr.getSelection(new Selection()); } /** * A class primarily for the support of isolating our tests * from our concrete activity implementations. Loading @@ -189,9 +210,11 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons> // TODO: Move this to PickAddons as multi-document picking is exclusive to that activity. void onDocumentsPicked(List<DocumentInfo> docs); void onDocumentPicked(DocumentInfo doc); void openContainerDocument(DocumentInfo doc); RootInfo getCurrentRoot(); DocumentInfo getCurrentDirectory(); void setRootsDrawerOpen(boolean open); @VisibleForTesting void notifyDirectoryNavigated(Uri docUri); } } src/com/android/documentsui/ActionHandler.java +2 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,8 @@ public interface ActionHandler { void showChooserForDoc(DocumentInfo doc); void openContainerDocument(DocumentInfo doc); void deleteSelectedDocuments(); void shareSelectedDocuments(); Loading src/com/android/documentsui/BaseActivity.java +29 −89 Original line number Diff line number Diff line Loading @@ -32,11 +32,9 @@ import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; import android.database.ContentObserver; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.MessageQueue.IdleHandler; import android.provider.DocumentsContract; import android.provider.DocumentsContract.Root; Loading @@ -59,7 +57,6 @@ import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.EventHandler; import com.android.documentsui.base.Events; import com.android.documentsui.base.LocalPreferences; import com.android.documentsui.base.PairedTask; import com.android.documentsui.base.RootInfo; import com.android.documentsui.base.Shared; import com.android.documentsui.base.State; Loading @@ -80,12 +77,11 @@ import com.android.documentsui.ui.DialogController; import com.android.documentsui.ui.MessageBuilder; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.concurrent.Executor; public abstract class BaseActivity public abstract class BaseActivity<T extends ActionHandler> extends Activity implements CommonAddons, NavigationViewManager.Environment { private static final String BENCHMARK_TESTING_PACKAGE = "com.android.documentsui.appperftests"; Loading @@ -95,25 +91,23 @@ public abstract class BaseActivity protected @Nullable RetainedState mRetainedState; protected RootsCache mRoots; protected DocumentsAccess mDocs; protected MessageBuilder mMessages; protected DrawerController mDrawer; protected NavigationViewManager mNavigator; protected FocusManager mFocusManager; protected SortController mSortController; protected T mActions; private final List<EventListener> mEventListeners = new ArrayList<>(); private final String mTag; private final ContentObserver mRootsCacheObserver = new ContentObserver( new Handler()) { @Override public void onChange(boolean selfChange) { new HandleRootsChangedTask(BaseActivity.this).execute(getCurrentRoot()); } }; @LayoutRes private int mLayoutId; private RootsMonitor<BaseActivity> mRootsMonitor; private boolean mNavDrawerHasFocus; private long mStartTime; Loading Loading @@ -202,9 +196,8 @@ public abstract class BaseActivity // support to that fragment. mRetainedState = (RetainedState) getLastNonConfigurationInstance(); mRoots = DocumentsApplication.getRootsCache(this); mDocs = DocumentsAccess.create(this); mMessages = new MessageBuilder(this); getContentResolver().registerContentObserver( RootsCache.sNotificationUri, false, mRootsCacheObserver); DocumentsToolbar toolbar = (DocumentsToolbar) findViewById(R.id.toolbar); setActionBar(toolbar); Loading Loading @@ -245,6 +238,20 @@ public abstract class BaseActivity setResult(Activity.RESULT_CANCELED); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); mRootsMonitor = new RootsMonitor<>( this, mActions, mRoots, mDocs, mState, mSearchManager); mRootsMonitor.start(); } @Override public boolean onCreateOptionsMenu(Menu menu) { boolean showMenu = super.onCreateOptionsMenu(menu); Loading @@ -267,7 +274,7 @@ public abstract class BaseActivity @Override protected void onDestroy() { getContentResolver().unregisterContentObserver(mRootsCacheObserver); mRootsMonitor.stop(); super.onDestroy(); } Loading Loading @@ -344,7 +351,7 @@ public abstract class BaseActivity new GetRootDocumentTask( root, this, this::openContainerDocument) mActions::openContainerDocument) .executeOnExecutor(getExecutorForCurrentDirectory()); } } Loading Loading @@ -406,22 +413,6 @@ public abstract class BaseActivity && !root.isDownloads(); } // TODO: Move to ActionHandler...currently blocked by the notifyDirectory....business. @Override public void openContainerDocument(DocumentInfo doc) { assert(doc.isContainer()); notifyDirectoryNavigated(doc.derivedUri); mState.pushDocument(doc); // Show an opening animation only if pressing "back" would get us back to the // previous directory. Especially after opening a root document, pressing // back, wouldn't go to the previous root, but close the activity. final int anim = (mState.hasLocationChanged() && mState.stack.size() > 1) ? AnimationView.ANIM_ENTER : AnimationView.ANIM_NONE; refreshCurrentRootAndDirectory(anim); } /** * Refreshes the content of the director and the menu/action bar. * The current directory name and selection will get updated. Loading Loading @@ -638,21 +629,26 @@ public abstract class BaseActivity return super.onKeyDown(keyCode, event); } @VisibleForTesting public void addEventListener(EventListener listener) { mEventListeners.add(listener); } @VisibleForTesting public void removeEventListener(EventListener listener) { mEventListeners.remove(listener); } @VisibleForTesting public void notifyDirectoryLoaded(Uri uri) { for (EventListener listener : mEventListeners) { listener.onDirectoryLoaded(uri); } } void notifyDirectoryNavigated(Uri uri) { @VisibleForTesting @Override public void notifyDirectoryNavigated(Uri uri) { for (EventListener listener : mEventListeners) { listener.onDirectoryNavigated(uri); } Loading Loading @@ -728,62 +724,6 @@ public abstract class BaseActivity }); } private static final class HandleRootsChangedTask extends PairedTask<BaseActivity, RootInfo, RootInfo> { RootInfo mCurrentRoot; DocumentInfo mDefaultRootDocument; public HandleRootsChangedTask(BaseActivity activity) { super(activity); } @Override protected RootInfo run(RootInfo... roots) { assert(roots.length == 1); mCurrentRoot = roots[0]; final Collection<RootInfo> cachedRoots = mOwner.mRoots.getRootsBlocking(); for (final RootInfo root : cachedRoots) { if (root.getUri().equals(mCurrentRoot.getUri())) { // We don't need to change the current root as the current root was not removed. return null; } } // Choose the default root. final RootInfo defaultRoot = mOwner.mRoots.getDefaultRootBlocking(mOwner.mState); assert(defaultRoot != null); if (!defaultRoot.isRecents()) { mDefaultRootDocument = defaultRoot.getRootDocumentBlocking(mOwner); } return defaultRoot; } @Override protected void finish(RootInfo defaultRoot) { if (defaultRoot == null) { return; } // If the activity has been launched for the specific root and it is removed, finish the // activity. final Uri uri = mOwner.getIntent().getData(); if (uri != null && uri.equals(mCurrentRoot.getUri())) { mOwner.finish(); return; } // Clear entire backstack and start in new root. mOwner.mState.onRootChanged(defaultRoot); mOwner.mSearchManager.update(defaultRoot); if (defaultRoot.isRecents()) { mOwner.refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE); } else { mOwner.openContainerDocument(mDefaultRootDocument); } } } public final class RetainedState { public @Nullable Selection selection; Loading src/com/android/documentsui/OnRootsChangedTask.javadeleted 100644 → 0 +0 −81 Original line number Diff line number Diff line /* * Copyright (C) 2016 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 android.net.Uri; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.PairedTask; import com.android.documentsui.base.RootInfo; import com.android.documentsui.dirlist.AnimationView; import java.util.Collection; final class OnRootsChangedTask extends PairedTask<BaseActivity, RootInfo, RootInfo> { RootInfo mCurrentRoot; DocumentInfo mDefaultRootDocument; public OnRootsChangedTask(BaseActivity activity) { super(activity); } @Override protected RootInfo run(RootInfo... roots) { assert(roots.length == 1); mCurrentRoot = roots[0]; final Collection<RootInfo> cachedRoots = mOwner.mRoots.getRootsBlocking(); for (final RootInfo root : cachedRoots) { if (root.getUri().equals(mCurrentRoot.getUri())) { // We don't need to change the current root as the current root was not removed. return null; } } // Choose the default root. final RootInfo defaultRoot = mOwner.mRoots.getDefaultRootBlocking(mOwner.mState); assert(defaultRoot != null); if (!defaultRoot.isRecents()) { mDefaultRootDocument = defaultRoot.getRootDocumentBlocking(mOwner); } return defaultRoot; } @Override protected void finish(RootInfo defaultRoot) { if (defaultRoot == null) { return; } // If the activity has been launched for the specific root and it is removed, finish the // activity. final Uri uri = mOwner.getIntent().getData(); if (uri != null && uri.equals(mCurrentRoot.getUri())) { mOwner.finish(); return; } // Clear entire backstack and start in new root. mOwner.mState.onRootChanged(defaultRoot); mOwner.mSearchManager.update(defaultRoot); if (defaultRoot.isRecents()) { mOwner.refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE); } else { mOwner.openContainerDocument(mDefaultRootDocument); } } } No newline at end of file src/com/android/documentsui/RootsMonitor.java 0 → 100644 +147 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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 android.app.Activity; import android.content.ContentResolver; import android.database.ContentObserver; import android.net.Uri; import android.os.Handler; import android.os.Looper; import com.android.documentsui.AbstractActionHandler.CommonAddons; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.PairedTask; import com.android.documentsui.base.RootInfo; import com.android.documentsui.base.State; import com.android.documentsui.dirlist.AnimationView; import com.android.documentsui.roots.RootsAccess; import java.util.Collection; /** * Monitors roots change and refresh the page when necessary. */ final class RootsMonitor<T extends Activity & CommonAddons> { private final ContentResolver mResolver; private final ContentObserver mObserver; RootsMonitor( final T activity, final ActionHandler actions, final RootsAccess roots, final DocumentsAccess docs, final State state, final SearchViewManager searchMgr) { mResolver = activity.getContentResolver(); mObserver = new ContentObserver(new Handler(Looper.getMainLooper())) { @Override public void onChange(boolean selfChange) { new HandleRootsChangedTask<T>( activity, actions, roots, docs, state, searchMgr).execute(activity.getCurrentRoot()); } }; } void start() { mResolver.registerContentObserver(RootsAccess.NOTIFICATION_URI, false, mObserver); } void stop() { mResolver.unregisterContentObserver(mObserver); } private static class HandleRootsChangedTask<T extends Activity & CommonAddons> extends PairedTask<T, RootInfo, RootInfo> { private final ActionHandler mActions; private final RootsAccess mRoots; private final DocumentsAccess mDocs; private final State mState; private final SearchViewManager mSearchMgr; private RootInfo mCurrentRoot; private DocumentInfo mDefaultRootDocument; private HandleRootsChangedTask( T activity, ActionHandler actions, RootsAccess roots, DocumentsAccess docs, State state, SearchViewManager searchMgr) { super(activity); mActions = actions; mRoots = roots; mDocs = docs; mState = state; mSearchMgr = searchMgr; } @Override protected RootInfo run(RootInfo... roots) { assert (roots.length == 1); mCurrentRoot = roots[0]; final Collection<RootInfo> cachedRoots = mRoots.getRootsBlocking(); for (final RootInfo root : cachedRoots) { if (root.getUri().equals(mCurrentRoot.getUri())) { // We don't need to change the current root as the current root was not removed. return null; } } // Choose the default root. final RootInfo defaultRoot = mRoots.getDefaultRootBlocking(mState); assert (defaultRoot != null); if (!defaultRoot.isRecents()) { mDefaultRootDocument = mDocs.getRootDocument(defaultRoot); } return defaultRoot; } @Override protected void finish(RootInfo defaultRoot) { if (defaultRoot == null) { return; } // If the activity has been launched for the specific root and it is removed, finish the // activity. final Uri uri = mOwner.getIntent().getData(); if (uri != null && uri.equals(mCurrentRoot.getUri())) { mOwner.finish(); return; } // Clear entire backstack and start in new root. mState.onRootChanged(defaultRoot); mSearchMgr.update(defaultRoot); if (defaultRoot.isRecents()) { mOwner.refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE); } else { mActions.openContainerDocument(mDefaultRootDocument); } } } } Loading
src/com/android/documentsui/AbstractActionHandler.java +24 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.Intent; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Parcelable; import android.support.annotation.VisibleForTesting; import com.android.documentsui.AbstractActionHandler.CommonAddons; import com.android.documentsui.base.BooleanConsumer; Loading @@ -31,6 +32,7 @@ import com.android.documentsui.base.Lookup; import com.android.documentsui.base.RootInfo; import com.android.documentsui.base.Shared; import com.android.documentsui.base.State; import com.android.documentsui.dirlist.AnimationView; import com.android.documentsui.dirlist.AnimationView.AnimationType; import com.android.documentsui.dirlist.DocumentDetails; import com.android.documentsui.files.LauncherActivity; Loading @@ -55,6 +57,7 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons> protected final RootsAccess mRoots; protected final DocumentsAccess mDocs; protected final SelectionManager mSelectionMgr; protected final SearchViewManager mSearchMgr; protected final Lookup<String, Executor> mExecutors; public AbstractActionHandler( Loading @@ -63,6 +66,7 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons> RootsAccess roots, DocumentsAccess docs, SelectionManager selectionMgr, SearchViewManager searchMgr, Lookup<String, Executor> executors) { assert(activity != null); Loading @@ -76,6 +80,7 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons> mRoots = roots; mDocs = docs; mSelectionMgr = selectionMgr; mSearchMgr = searchMgr; mExecutors = executors; } Loading Loading @@ -150,6 +155,21 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons> throw new UnsupportedOperationException("Show chooser for doc not supported!"); } @Override public void openContainerDocument(DocumentInfo doc) { assert(doc.isContainer()); mActivity.notifyDirectoryNavigated(doc.derivedUri); mState.pushDocument(doc); // Show an opening animation only if pressing "back" would get us back to the // previous directory. Especially after opening a root document, pressing // back, wouldn't go to the previous root, but close the activity. final int anim = (mState.hasLocationChanged() && mState.stack.size() > 1) ? AnimationView.ANIM_ENTER : AnimationView.ANIM_NONE; mActivity.refreshCurrentRootAndDirectory(anim); } @Override public void deleteSelectedDocuments() { throw new UnsupportedOperationException("Delete not supported!"); Loading Loading @@ -179,6 +199,7 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons> protected Selection getStableSelection() { return mSelectionMgr.getSelection(new Selection()); } /** * A class primarily for the support of isolating our tests * from our concrete activity implementations. Loading @@ -189,9 +210,11 @@ public abstract class AbstractActionHandler<T extends Activity & CommonAddons> // TODO: Move this to PickAddons as multi-document picking is exclusive to that activity. void onDocumentsPicked(List<DocumentInfo> docs); void onDocumentPicked(DocumentInfo doc); void openContainerDocument(DocumentInfo doc); RootInfo getCurrentRoot(); DocumentInfo getCurrentDirectory(); void setRootsDrawerOpen(boolean open); @VisibleForTesting void notifyDirectoryNavigated(Uri docUri); } }
src/com/android/documentsui/ActionHandler.java +2 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,8 @@ public interface ActionHandler { void showChooserForDoc(DocumentInfo doc); void openContainerDocument(DocumentInfo doc); void deleteSelectedDocuments(); void shareSelectedDocuments(); Loading
src/com/android/documentsui/BaseActivity.java +29 −89 Original line number Diff line number Diff line Loading @@ -32,11 +32,9 @@ import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; import android.database.ContentObserver; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.MessageQueue.IdleHandler; import android.provider.DocumentsContract; import android.provider.DocumentsContract.Root; Loading @@ -59,7 +57,6 @@ import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.EventHandler; import com.android.documentsui.base.Events; import com.android.documentsui.base.LocalPreferences; import com.android.documentsui.base.PairedTask; import com.android.documentsui.base.RootInfo; import com.android.documentsui.base.Shared; import com.android.documentsui.base.State; Loading @@ -80,12 +77,11 @@ import com.android.documentsui.ui.DialogController; import com.android.documentsui.ui.MessageBuilder; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.concurrent.Executor; public abstract class BaseActivity public abstract class BaseActivity<T extends ActionHandler> extends Activity implements CommonAddons, NavigationViewManager.Environment { private static final String BENCHMARK_TESTING_PACKAGE = "com.android.documentsui.appperftests"; Loading @@ -95,25 +91,23 @@ public abstract class BaseActivity protected @Nullable RetainedState mRetainedState; protected RootsCache mRoots; protected DocumentsAccess mDocs; protected MessageBuilder mMessages; protected DrawerController mDrawer; protected NavigationViewManager mNavigator; protected FocusManager mFocusManager; protected SortController mSortController; protected T mActions; private final List<EventListener> mEventListeners = new ArrayList<>(); private final String mTag; private final ContentObserver mRootsCacheObserver = new ContentObserver( new Handler()) { @Override public void onChange(boolean selfChange) { new HandleRootsChangedTask(BaseActivity.this).execute(getCurrentRoot()); } }; @LayoutRes private int mLayoutId; private RootsMonitor<BaseActivity> mRootsMonitor; private boolean mNavDrawerHasFocus; private long mStartTime; Loading Loading @@ -202,9 +196,8 @@ public abstract class BaseActivity // support to that fragment. mRetainedState = (RetainedState) getLastNonConfigurationInstance(); mRoots = DocumentsApplication.getRootsCache(this); mDocs = DocumentsAccess.create(this); mMessages = new MessageBuilder(this); getContentResolver().registerContentObserver( RootsCache.sNotificationUri, false, mRootsCacheObserver); DocumentsToolbar toolbar = (DocumentsToolbar) findViewById(R.id.toolbar); setActionBar(toolbar); Loading Loading @@ -245,6 +238,20 @@ public abstract class BaseActivity setResult(Activity.RESULT_CANCELED); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); mRootsMonitor = new RootsMonitor<>( this, mActions, mRoots, mDocs, mState, mSearchManager); mRootsMonitor.start(); } @Override public boolean onCreateOptionsMenu(Menu menu) { boolean showMenu = super.onCreateOptionsMenu(menu); Loading @@ -267,7 +274,7 @@ public abstract class BaseActivity @Override protected void onDestroy() { getContentResolver().unregisterContentObserver(mRootsCacheObserver); mRootsMonitor.stop(); super.onDestroy(); } Loading Loading @@ -344,7 +351,7 @@ public abstract class BaseActivity new GetRootDocumentTask( root, this, this::openContainerDocument) mActions::openContainerDocument) .executeOnExecutor(getExecutorForCurrentDirectory()); } } Loading Loading @@ -406,22 +413,6 @@ public abstract class BaseActivity && !root.isDownloads(); } // TODO: Move to ActionHandler...currently blocked by the notifyDirectory....business. @Override public void openContainerDocument(DocumentInfo doc) { assert(doc.isContainer()); notifyDirectoryNavigated(doc.derivedUri); mState.pushDocument(doc); // Show an opening animation only if pressing "back" would get us back to the // previous directory. Especially after opening a root document, pressing // back, wouldn't go to the previous root, but close the activity. final int anim = (mState.hasLocationChanged() && mState.stack.size() > 1) ? AnimationView.ANIM_ENTER : AnimationView.ANIM_NONE; refreshCurrentRootAndDirectory(anim); } /** * Refreshes the content of the director and the menu/action bar. * The current directory name and selection will get updated. Loading Loading @@ -638,21 +629,26 @@ public abstract class BaseActivity return super.onKeyDown(keyCode, event); } @VisibleForTesting public void addEventListener(EventListener listener) { mEventListeners.add(listener); } @VisibleForTesting public void removeEventListener(EventListener listener) { mEventListeners.remove(listener); } @VisibleForTesting public void notifyDirectoryLoaded(Uri uri) { for (EventListener listener : mEventListeners) { listener.onDirectoryLoaded(uri); } } void notifyDirectoryNavigated(Uri uri) { @VisibleForTesting @Override public void notifyDirectoryNavigated(Uri uri) { for (EventListener listener : mEventListeners) { listener.onDirectoryNavigated(uri); } Loading Loading @@ -728,62 +724,6 @@ public abstract class BaseActivity }); } private static final class HandleRootsChangedTask extends PairedTask<BaseActivity, RootInfo, RootInfo> { RootInfo mCurrentRoot; DocumentInfo mDefaultRootDocument; public HandleRootsChangedTask(BaseActivity activity) { super(activity); } @Override protected RootInfo run(RootInfo... roots) { assert(roots.length == 1); mCurrentRoot = roots[0]; final Collection<RootInfo> cachedRoots = mOwner.mRoots.getRootsBlocking(); for (final RootInfo root : cachedRoots) { if (root.getUri().equals(mCurrentRoot.getUri())) { // We don't need to change the current root as the current root was not removed. return null; } } // Choose the default root. final RootInfo defaultRoot = mOwner.mRoots.getDefaultRootBlocking(mOwner.mState); assert(defaultRoot != null); if (!defaultRoot.isRecents()) { mDefaultRootDocument = defaultRoot.getRootDocumentBlocking(mOwner); } return defaultRoot; } @Override protected void finish(RootInfo defaultRoot) { if (defaultRoot == null) { return; } // If the activity has been launched for the specific root and it is removed, finish the // activity. final Uri uri = mOwner.getIntent().getData(); if (uri != null && uri.equals(mCurrentRoot.getUri())) { mOwner.finish(); return; } // Clear entire backstack and start in new root. mOwner.mState.onRootChanged(defaultRoot); mOwner.mSearchManager.update(defaultRoot); if (defaultRoot.isRecents()) { mOwner.refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE); } else { mOwner.openContainerDocument(mDefaultRootDocument); } } } public final class RetainedState { public @Nullable Selection selection; Loading
src/com/android/documentsui/OnRootsChangedTask.javadeleted 100644 → 0 +0 −81 Original line number Diff line number Diff line /* * Copyright (C) 2016 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 android.net.Uri; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.PairedTask; import com.android.documentsui.base.RootInfo; import com.android.documentsui.dirlist.AnimationView; import java.util.Collection; final class OnRootsChangedTask extends PairedTask<BaseActivity, RootInfo, RootInfo> { RootInfo mCurrentRoot; DocumentInfo mDefaultRootDocument; public OnRootsChangedTask(BaseActivity activity) { super(activity); } @Override protected RootInfo run(RootInfo... roots) { assert(roots.length == 1); mCurrentRoot = roots[0]; final Collection<RootInfo> cachedRoots = mOwner.mRoots.getRootsBlocking(); for (final RootInfo root : cachedRoots) { if (root.getUri().equals(mCurrentRoot.getUri())) { // We don't need to change the current root as the current root was not removed. return null; } } // Choose the default root. final RootInfo defaultRoot = mOwner.mRoots.getDefaultRootBlocking(mOwner.mState); assert(defaultRoot != null); if (!defaultRoot.isRecents()) { mDefaultRootDocument = defaultRoot.getRootDocumentBlocking(mOwner); } return defaultRoot; } @Override protected void finish(RootInfo defaultRoot) { if (defaultRoot == null) { return; } // If the activity has been launched for the specific root and it is removed, finish the // activity. final Uri uri = mOwner.getIntent().getData(); if (uri != null && uri.equals(mCurrentRoot.getUri())) { mOwner.finish(); return; } // Clear entire backstack and start in new root. mOwner.mState.onRootChanged(defaultRoot); mOwner.mSearchManager.update(defaultRoot); if (defaultRoot.isRecents()) { mOwner.refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE); } else { mOwner.openContainerDocument(mDefaultRootDocument); } } } No newline at end of file
src/com/android/documentsui/RootsMonitor.java 0 → 100644 +147 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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 android.app.Activity; import android.content.ContentResolver; import android.database.ContentObserver; import android.net.Uri; import android.os.Handler; import android.os.Looper; import com.android.documentsui.AbstractActionHandler.CommonAddons; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.PairedTask; import com.android.documentsui.base.RootInfo; import com.android.documentsui.base.State; import com.android.documentsui.dirlist.AnimationView; import com.android.documentsui.roots.RootsAccess; import java.util.Collection; /** * Monitors roots change and refresh the page when necessary. */ final class RootsMonitor<T extends Activity & CommonAddons> { private final ContentResolver mResolver; private final ContentObserver mObserver; RootsMonitor( final T activity, final ActionHandler actions, final RootsAccess roots, final DocumentsAccess docs, final State state, final SearchViewManager searchMgr) { mResolver = activity.getContentResolver(); mObserver = new ContentObserver(new Handler(Looper.getMainLooper())) { @Override public void onChange(boolean selfChange) { new HandleRootsChangedTask<T>( activity, actions, roots, docs, state, searchMgr).execute(activity.getCurrentRoot()); } }; } void start() { mResolver.registerContentObserver(RootsAccess.NOTIFICATION_URI, false, mObserver); } void stop() { mResolver.unregisterContentObserver(mObserver); } private static class HandleRootsChangedTask<T extends Activity & CommonAddons> extends PairedTask<T, RootInfo, RootInfo> { private final ActionHandler mActions; private final RootsAccess mRoots; private final DocumentsAccess mDocs; private final State mState; private final SearchViewManager mSearchMgr; private RootInfo mCurrentRoot; private DocumentInfo mDefaultRootDocument; private HandleRootsChangedTask( T activity, ActionHandler actions, RootsAccess roots, DocumentsAccess docs, State state, SearchViewManager searchMgr) { super(activity); mActions = actions; mRoots = roots; mDocs = docs; mState = state; mSearchMgr = searchMgr; } @Override protected RootInfo run(RootInfo... roots) { assert (roots.length == 1); mCurrentRoot = roots[0]; final Collection<RootInfo> cachedRoots = mRoots.getRootsBlocking(); for (final RootInfo root : cachedRoots) { if (root.getUri().equals(mCurrentRoot.getUri())) { // We don't need to change the current root as the current root was not removed. return null; } } // Choose the default root. final RootInfo defaultRoot = mRoots.getDefaultRootBlocking(mState); assert (defaultRoot != null); if (!defaultRoot.isRecents()) { mDefaultRootDocument = mDocs.getRootDocument(defaultRoot); } return defaultRoot; } @Override protected void finish(RootInfo defaultRoot) { if (defaultRoot == null) { return; } // If the activity has been launched for the specific root and it is removed, finish the // activity. final Uri uri = mOwner.getIntent().getData(); if (uri != null && uri.equals(mCurrentRoot.getUri())) { mOwner.finish(); return; } // Clear entire backstack and start in new root. mState.onRootChanged(defaultRoot); mSearchMgr.update(defaultRoot); if (defaultRoot.isRecents()) { mOwner.refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE); } else { mActions.openContainerDocument(mDefaultRootDocument); } } } }