Loading core/java/android/os/storage/StorageVolume.java +24 −17 Original line number Diff line number Diff line Loading @@ -315,27 +315,34 @@ public final class StorageVolume implements Parcelable { * To gain access to descendants (child, grandchild, etc) documents, use * {@link DocumentsContract#buildDocumentUriUsingTree(Uri, String)}, or * {@link DocumentsContract#buildChildDocumentsUriUsingTree(Uri, String)} with the returned URI. * * <b>If your application only needs to store internal data, consider using * <p> * If your application only needs to store internal data, consider using * {@link Context#getExternalFilesDirs(String) Context.getExternalFilesDirs}, * {@link Context#getExternalCacheDirs()}, or * {@link Context#getExternalMediaDirs()}, which require no permissions to read or write. * * <strong>NOTE: </strong>requesting access to the entire volume is not recommended and it will * result in a stronger message displayed to the user, which may cause the user to reject * the request. * * @param directoryName must be one of * {@link Environment#DIRECTORY_MUSIC}, {@link Environment#DIRECTORY_PODCASTS}, * {@link Environment#DIRECTORY_RINGTONES}, {@link Environment#DIRECTORY_ALARMS}, * {@link Environment#DIRECTORY_NOTIFICATIONS}, {@link Environment#DIRECTORY_PICTURES}, * {@link Environment#DIRECTORY_MOVIES}, {@link Environment#DIRECTORY_DOWNLOADS}, * {@link Environment#DIRECTORY_DCIM}, or {@link Environment#DIRECTORY_DOCUMENTS}, or * {code null} to request access to the entire volume. * {@link Context#getExternalCacheDirs()}, or {@link Context#getExternalMediaDirs()}, which * require no permissions to read or write. * <p> * Access to the entire volume is only available for non-primary volumes (for the primary * volume, apps can use the {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} and * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permissions) and should be used * with caution, since users are more likely to deny access when asked for entire volume access * rather than specific directories. * * @param directoryName must be one of {@link Environment#DIRECTORY_MUSIC}, * {@link Environment#DIRECTORY_PODCASTS}, {@link Environment#DIRECTORY_RINGTONES}, * {@link Environment#DIRECTORY_ALARMS}, {@link Environment#DIRECTORY_NOTIFICATIONS}, * {@link Environment#DIRECTORY_PICTURES}, {@link Environment#DIRECTORY_MOVIES}, * {@link Environment#DIRECTORY_DOWNLOADS}, {@link Environment#DIRECTORY_DCIM}, or * {@link Environment#DIRECTORY_DOCUMENTS}, or {code null} to request access to the * entire volume. * @return intent to request access, or {@code null} if the requested directory is invalid for * that volume. * @see DocumentsContract */ public Intent createAccessIntent(String directoryName) { public @Nullable Intent createAccessIntent(String directoryName) { if ((isPrimary() && directoryName == null) || (directoryName != null && !Environment.isStandardDirectory(directoryName))) { return null; } final Intent intent = new Intent(ACTION_OPEN_EXTERNAL_DIRECTORY); intent.putExtra(EXTRA_STORAGE_VOLUME, this); intent.putExtra(EXTRA_DIRECTORY_NAME, directoryName); Loading packages/DocumentsUI/res/values/strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -204,6 +204,9 @@ <string name="open_external_dialog_request">Grant <xliff:g id="appName" example="System Settings"><b>^1</b></xliff:g> access to <xliff:g id="directory" example="Pictures"><i>^2</i></xliff:g> directory on <xliff:g id="storage" example="SD Card"><i>^3</i></xliff:g>?</string> <!-- Text in an alert dialog asking user to grant app access to a given directory in the internal storage --> <string name="open_external_dialog_request_primary_volume">Grant <xliff:g id="appName" example="System Settings"><b>^1</b></xliff:g> access to <xliff:g id="directory" example="Pictures"><i>^2</i></xliff:g> directory?</string> <!-- Text in an alert dialog asking user to grant app access to all data in an external storage volume --> <string name="open_external_dialog_root_request">Grant <xliff:g id="appName" example="System Settings"><b>^1</b></xliff:g> access to your data, including photos and videos, on <xliff:g id="storage" example="SD Card"><i>^2</i></xliff:g>?</string> Loading packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java +14 −1 Original line number Diff line number Diff line Loading @@ -86,6 +86,7 @@ public class OpenExternalDirectoryActivity extends Activity { private static final String EXTRA_VOLUME_LABEL = "com.android.documentsui.VOLUME_LABEL"; private static final String EXTRA_VOLUME_UUID = "com.android.documentsui.VOLUME_UUID"; private static final String EXTRA_IS_ROOT = "com.android.documentsui.IS_ROOT"; private static final String EXTRA_IS_PRIMARY = "com.android.documentsui.IS_PRIMARY"; // Special directory name representing the full volume static final String DIRECTORY_ROOT = "ROOT_DIRECTORY"; Loading Loading @@ -157,6 +158,13 @@ public class OpenExternalDirectoryActivity extends Activity { Log.d(TAG, "showFragment() for volume " + storageVolume.dump() + ", directory " + directoryName + ", and user " + userId); final boolean isRoot = directoryName.equals(DIRECTORY_ROOT); final boolean isPrimary = storageVolume.isPrimary(); if (isRoot && isPrimary) { if (DEBUG) Log.d(TAG, "root access requested on primary volume"); return false; } final File volumeRoot = storageVolume.getPathFile(); File file; try { Loading Loading @@ -235,6 +243,7 @@ public class OpenExternalDirectoryActivity extends Activity { args.putString(EXTRA_VOLUME_UUID, volumeUuid); args.putString(EXTRA_APP_LABEL, appLabel); args.putBoolean(EXTRA_IS_ROOT, isRoot); args.putBoolean(EXTRA_IS_PRIMARY, isPrimary); final FragmentManager fm = activity.getFragmentManager(); final FragmentTransaction ft = fm.beginTransaction(); Loading Loading @@ -352,6 +361,7 @@ public class OpenExternalDirectoryActivity extends Activity { private String mVolumeLabel; private String mAppLabel; private boolean mIsRoot; private boolean mIsPrimary; private CheckBox mDontAskAgain; private OpenExternalDirectoryActivity mActivity; private AlertDialog mDialog; Loading @@ -367,6 +377,7 @@ public class OpenExternalDirectoryActivity extends Activity { mVolumeLabel = args.getString(EXTRA_VOLUME_LABEL); mAppLabel = args.getString(EXTRA_APP_LABEL); mIsRoot = args.getBoolean(EXTRA_IS_ROOT); mIsPrimary= args.getBoolean(EXTRA_IS_PRIMARY); } mActivity = (OpenExternalDirectoryActivity) getActivity(); } Loading Loading @@ -435,7 +446,9 @@ public class OpenExternalDirectoryActivity extends Activity { message = TextUtils.expandTemplate(getText( R.string.open_external_dialog_root_request), mAppLabel, mVolumeLabel); } else { message = TextUtils.expandTemplate(getText(R.string.open_external_dialog_request), message = TextUtils.expandTemplate( getText(mIsPrimary ? R.string.open_external_dialog_request_primary_volume : R.string.open_external_dialog_request), mAppLabel, directory, mVolumeLabel); } final TextView messageField = (TextView) view.findViewById(R.id.message); Loading Loading
core/java/android/os/storage/StorageVolume.java +24 −17 Original line number Diff line number Diff line Loading @@ -315,27 +315,34 @@ public final class StorageVolume implements Parcelable { * To gain access to descendants (child, grandchild, etc) documents, use * {@link DocumentsContract#buildDocumentUriUsingTree(Uri, String)}, or * {@link DocumentsContract#buildChildDocumentsUriUsingTree(Uri, String)} with the returned URI. * * <b>If your application only needs to store internal data, consider using * <p> * If your application only needs to store internal data, consider using * {@link Context#getExternalFilesDirs(String) Context.getExternalFilesDirs}, * {@link Context#getExternalCacheDirs()}, or * {@link Context#getExternalMediaDirs()}, which require no permissions to read or write. * * <strong>NOTE: </strong>requesting access to the entire volume is not recommended and it will * result in a stronger message displayed to the user, which may cause the user to reject * the request. * * @param directoryName must be one of * {@link Environment#DIRECTORY_MUSIC}, {@link Environment#DIRECTORY_PODCASTS}, * {@link Environment#DIRECTORY_RINGTONES}, {@link Environment#DIRECTORY_ALARMS}, * {@link Environment#DIRECTORY_NOTIFICATIONS}, {@link Environment#DIRECTORY_PICTURES}, * {@link Environment#DIRECTORY_MOVIES}, {@link Environment#DIRECTORY_DOWNLOADS}, * {@link Environment#DIRECTORY_DCIM}, or {@link Environment#DIRECTORY_DOCUMENTS}, or * {code null} to request access to the entire volume. * {@link Context#getExternalCacheDirs()}, or {@link Context#getExternalMediaDirs()}, which * require no permissions to read or write. * <p> * Access to the entire volume is only available for non-primary volumes (for the primary * volume, apps can use the {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} and * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permissions) and should be used * with caution, since users are more likely to deny access when asked for entire volume access * rather than specific directories. * * @param directoryName must be one of {@link Environment#DIRECTORY_MUSIC}, * {@link Environment#DIRECTORY_PODCASTS}, {@link Environment#DIRECTORY_RINGTONES}, * {@link Environment#DIRECTORY_ALARMS}, {@link Environment#DIRECTORY_NOTIFICATIONS}, * {@link Environment#DIRECTORY_PICTURES}, {@link Environment#DIRECTORY_MOVIES}, * {@link Environment#DIRECTORY_DOWNLOADS}, {@link Environment#DIRECTORY_DCIM}, or * {@link Environment#DIRECTORY_DOCUMENTS}, or {code null} to request access to the * entire volume. * @return intent to request access, or {@code null} if the requested directory is invalid for * that volume. * @see DocumentsContract */ public Intent createAccessIntent(String directoryName) { public @Nullable Intent createAccessIntent(String directoryName) { if ((isPrimary() && directoryName == null) || (directoryName != null && !Environment.isStandardDirectory(directoryName))) { return null; } final Intent intent = new Intent(ACTION_OPEN_EXTERNAL_DIRECTORY); intent.putExtra(EXTRA_STORAGE_VOLUME, this); intent.putExtra(EXTRA_DIRECTORY_NAME, directoryName); Loading
packages/DocumentsUI/res/values/strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -204,6 +204,9 @@ <string name="open_external_dialog_request">Grant <xliff:g id="appName" example="System Settings"><b>^1</b></xliff:g> access to <xliff:g id="directory" example="Pictures"><i>^2</i></xliff:g> directory on <xliff:g id="storage" example="SD Card"><i>^3</i></xliff:g>?</string> <!-- Text in an alert dialog asking user to grant app access to a given directory in the internal storage --> <string name="open_external_dialog_request_primary_volume">Grant <xliff:g id="appName" example="System Settings"><b>^1</b></xliff:g> access to <xliff:g id="directory" example="Pictures"><i>^2</i></xliff:g> directory?</string> <!-- Text in an alert dialog asking user to grant app access to all data in an external storage volume --> <string name="open_external_dialog_root_request">Grant <xliff:g id="appName" example="System Settings"><b>^1</b></xliff:g> access to your data, including photos and videos, on <xliff:g id="storage" example="SD Card"><i>^2</i></xliff:g>?</string> Loading
packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java +14 −1 Original line number Diff line number Diff line Loading @@ -86,6 +86,7 @@ public class OpenExternalDirectoryActivity extends Activity { private static final String EXTRA_VOLUME_LABEL = "com.android.documentsui.VOLUME_LABEL"; private static final String EXTRA_VOLUME_UUID = "com.android.documentsui.VOLUME_UUID"; private static final String EXTRA_IS_ROOT = "com.android.documentsui.IS_ROOT"; private static final String EXTRA_IS_PRIMARY = "com.android.documentsui.IS_PRIMARY"; // Special directory name representing the full volume static final String DIRECTORY_ROOT = "ROOT_DIRECTORY"; Loading Loading @@ -157,6 +158,13 @@ public class OpenExternalDirectoryActivity extends Activity { Log.d(TAG, "showFragment() for volume " + storageVolume.dump() + ", directory " + directoryName + ", and user " + userId); final boolean isRoot = directoryName.equals(DIRECTORY_ROOT); final boolean isPrimary = storageVolume.isPrimary(); if (isRoot && isPrimary) { if (DEBUG) Log.d(TAG, "root access requested on primary volume"); return false; } final File volumeRoot = storageVolume.getPathFile(); File file; try { Loading Loading @@ -235,6 +243,7 @@ public class OpenExternalDirectoryActivity extends Activity { args.putString(EXTRA_VOLUME_UUID, volumeUuid); args.putString(EXTRA_APP_LABEL, appLabel); args.putBoolean(EXTRA_IS_ROOT, isRoot); args.putBoolean(EXTRA_IS_PRIMARY, isPrimary); final FragmentManager fm = activity.getFragmentManager(); final FragmentTransaction ft = fm.beginTransaction(); Loading Loading @@ -352,6 +361,7 @@ public class OpenExternalDirectoryActivity extends Activity { private String mVolumeLabel; private String mAppLabel; private boolean mIsRoot; private boolean mIsPrimary; private CheckBox mDontAskAgain; private OpenExternalDirectoryActivity mActivity; private AlertDialog mDialog; Loading @@ -367,6 +377,7 @@ public class OpenExternalDirectoryActivity extends Activity { mVolumeLabel = args.getString(EXTRA_VOLUME_LABEL); mAppLabel = args.getString(EXTRA_APP_LABEL); mIsRoot = args.getBoolean(EXTRA_IS_ROOT); mIsPrimary= args.getBoolean(EXTRA_IS_PRIMARY); } mActivity = (OpenExternalDirectoryActivity) getActivity(); } Loading Loading @@ -435,7 +446,9 @@ public class OpenExternalDirectoryActivity extends Activity { message = TextUtils.expandTemplate(getText( R.string.open_external_dialog_root_request), mAppLabel, mVolumeLabel); } else { message = TextUtils.expandTemplate(getText(R.string.open_external_dialog_request), message = TextUtils.expandTemplate( getText(mIsPrimary ? R.string.open_external_dialog_request_primary_volume : R.string.open_external_dialog_request), mAppLabel, directory, mVolumeLabel); } final TextView messageField = (TextView) view.findViewById(R.id.message); Loading