下面列出了怎么用android.os.storage.StorageVolume的API类实例代码及写法,或者点击链接到github查看源代码。
private void requestPermission() {
try {
StorageManager sm = getSystemService(StorageManager.class);
//noinspection ConstantConditions
StorageVolume volume = sm.getPrimaryStorageVolume();
Intent intent = volume.createAccessIntent(Environment.DIRECTORY_DOWNLOADS);
startActivityForResult(intent, REQUEST_CODE);
} catch (Exception e) {
//Toast.makeText(this, R.string.cannot_request_permission, Toast.LENGTH_LONG).show();
Toast.makeText(this, "Can't use Scoped Directory Access.\nFallback to runtime permission.", Toast.LENGTH_LONG).show();
Log.wtf("FFM", "can't use Scoped Directory Access", e);
Crashlytics.logException(e);
// fallback to runtime permission
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
}
}
}
private void askSystemDownloadsPermission(Runnable cb, boolean noShowDenialDialog) {
if (cb != null) {
if (mStoragePermissionRequestCallbacks == null)
mStoragePermissionRequestCallbacks = new ArrayList<>();
mStoragePermissionRequestCallbacks.add(cb);
}
mPermissionRequestPending = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
StorageManager manager = (StorageManager) mActivity
.getSystemService(Context.STORAGE_SERVICE);
StorageVolume volume = manager.getPrimaryStorageVolume();
Intent intent = volume.createAccessIntent(Environment.DIRECTORY_DOWNLOADS);
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
mActivity.startActivityForResult(intent, mDownloadsPermissionRequestCode);
} else {
if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity,
Manifest.permission.WRITE_EXTERNAL_STORAGE) && !noShowDenialDialog) {
showSystemDownloadsPermissionDenialDialog();
} else {
ActivityCompat.requestPermissions(mActivity,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
mStoragePermissionRequestCode);
}
}
}
/**
* Get all available storage directories.
* Inspired by CyanogenMod File Manager:
* https://github.com/CyanogenMod/android_packages_apps_CMFileManager
*/
public static Set<File> getStorageDirectories(Context context) {
if (storageDirectories == null) {
try {
// Use reflection to retrieve storage volumes because required classes and methods are hidden in AOSP.
StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
Method method = storageManager.getClass().getMethod("getVolumeList");
StorageVolume[] storageVolumes = (StorageVolume[]) method.invoke(storageManager);
if (storageVolumes != null && storageVolumes.length > 0) {
storageDirectories = new HashSet<>();
for (StorageVolume volume : storageVolumes) {
storageDirectories.add(new File(volume.getPath()));
}
}
} catch (Exception e) {
Log.e(LOG_TAG, e.getMessage());
}
}
return storageDirectories;
}
private void onUnlockUser(int userId) {
Slog.d(TAG, "onUnlockUser " + userId);
// We purposefully block here to make sure that user-specific
// staging area is ready so it's ready for zygote-forked apps to
// bind mount against.
try {
mVold.onUserStarted(userId);
mStoraged.onUserStarted(userId);
} catch (Exception e) {
Slog.wtf(TAG, e);
}
// Record user as started so newly mounted volumes kick off events
// correctly, then synthesize events for any already-mounted volumes.
synchronized (mLock) {
for (int i = 0; i < mVolumes.size(); i++) {
final VolumeInfo vol = mVolumes.valueAt(i);
if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
final String envState = VolumeInfo.getEnvironmentForState(vol.getState());
mCallbacks.notifyStorageStateChanged(userVol.getPath(), envState, envState);
}
}
mSystemUnlockedUsers = ArrayUtils.appendInt(mSystemUnlockedUsers, userId);
}
}
public File[] getExternalDirs() {
final StorageVolume[] volumes = StorageManager.getVolumeList(mUserId,
StorageManager.FLAG_FOR_WRITE);
final File[] files = new File[volumes.length];
for (int i = 0; i < volumes.length; i++) {
files[i] = volumes[i].getPathFile();
}
return files;
}
private String sharedDomainToPath(String domain) throws IOException {
// already known to start with SHARED_PREFIX, so we just look after that
final String volume = domain.substring(FullBackup.SHARED_PREFIX.length());
final StorageVolume[] volumes = getVolumeList();
final int volNum = Integer.parseInt(volume);
if (volNum < mVolumes.length) {
return volumes[volNum].getPathFile().getCanonicalPath();
}
return null;
}
private StorageVolume[] getVolumeList() {
if (mStorageManager != null) {
if (mVolumes == null) {
mVolumes = mStorageManager.getVolumeList();
}
} else {
Log.e(TAG, "Unable to access Storage Manager");
}
return mVolumes;
}
@RequiresApi(api = Build.VERSION_CODES.N)
private void listing8_4() {
// Listing 8-4: Requesting access with Scoped Directory Access
StorageManager sm =
(StorageManager) getSystemService(Context.STORAGE_SERVICE);
StorageVolume volume = sm.getPrimaryStorageVolume();
Intent intent = volume.createAccessIntent(Environment.DIRECTORY_PICTURES);
startActivityForResult(intent, PICTURE_REQUEST_CODE);
}
/**
* 获取应用的大小
*/
@RequiresApi(api = Build.VERSION_CODES.O)
private static void getAppSizeAboveO(Context context, @NonNull OnGetSizeListener listener) {
StorageStatsManager storageStatsManager = (StorageStatsManager) context
.getSystemService(Context.STORAGE_STATS_SERVICE);
StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
// 获取所有应用的StorageVolume列表
List<StorageVolume> storageVolumes = storageManager.getStorageVolumes();
for (StorageVolume item : storageVolumes) {
String uuidStr = item.getUuid();
UUID uuid;
if (uuidStr == null) {
uuid = StorageManager.UUID_DEFAULT;
} else {
uuid = UUID.fromString(uuidStr);
}
int uid = getUid(context, context.getPackageName());
// 通过包名获取uid
StorageStats storageStats;
try {
storageStats = storageStatsManager.queryStatsForUid(uuid, uid);
AppSizeInfo ctAppSizeInfo = new AppSizeInfo();
ctAppSizeInfo.cacheSize = storageStats.getCacheBytes();
ctAppSizeInfo.dataSize = storageStats.getDataBytes();
ctAppSizeInfo.codeSize = storageStats.getAppBytes();
listener.onGetSize(ctAppSizeInfo);
} catch (IOException e) {
listener.onError(e);
}
}
}
@GuardedBy("mLock")
private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
// Remember that we saw this volume so we're ready to accept user
// metadata, or so we can annoy them when a private volume is ejected
if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) {
VolumeRecord rec = mRecords.get(vol.fsUuid);
if (rec == null) {
rec = new VolumeRecord(vol.type, vol.fsUuid);
rec.partGuid = vol.partGuid;
rec.createdMillis = System.currentTimeMillis();
if (vol.type == VolumeInfo.TYPE_PRIVATE) {
rec.nickname = vol.disk.getDescription();
}
mRecords.put(rec.fsUuid, rec);
writeSettingsLocked();
} else {
// Handle upgrade case where we didn't store partition GUID
if (TextUtils.isEmpty(rec.partGuid)) {
rec.partGuid = vol.partGuid;
writeSettingsLocked();
}
}
}
mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
// Do not broadcast before boot has completed to avoid launching the
// processes that receive the intent unnecessarily.
if (mBootCompleted && isBroadcastWorthy(vol)) {
final Intent intent = new Intent(VolumeInfo.ACTION_VOLUME_STATE_CHANGED);
intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.id);
intent.putExtra(VolumeInfo.EXTRA_VOLUME_STATE, newState);
intent.putExtra(VolumeRecord.EXTRA_FS_UUID, vol.fsUuid);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mHandler.obtainMessage(H_INTERNAL_BROADCAST, intent).sendToTarget();
}
final String oldStateEnv = VolumeInfo.getEnvironmentForState(oldState);
final String newStateEnv = VolumeInfo.getEnvironmentForState(newState);
if (!Objects.equals(oldStateEnv, newStateEnv)) {
// Kick state changed event towards all started users. Any users
// started after this point will trigger additional
// user-specific broadcasts.
for (int userId : mSystemUnlockedUsers) {
if (vol.isVisibleForRead(userId)) {
final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
mCallbacks.notifyStorageStateChanged(userVol.getPath(), oldStateEnv,
newStateEnv);
}
}
}
if (vol.type == VolumeInfo.TYPE_PUBLIC && vol.state == VolumeInfo.STATE_EJECTING) {
// TODO: this should eventually be handled by new ObbVolume state changes
/*
* Some OBBs might have been unmounted when this volume was
* unmounted, so send a message to the handler to let it know to
* remove those from the list of mounted OBBS.
*/
mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(
OBB_FLUSH_MOUNT_STATE, vol.path));
}
maybeLogMediaMount(vol, newState);
}
@Override
public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
final int userId = UserHandle.getUserId(uid);
final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
final boolean includeInvisible = (flags & StorageManager.FLAG_INCLUDE_INVISIBLE) != 0;
final boolean userKeyUnlocked;
final boolean storagePermission;
final long token = Binder.clearCallingIdentity();
try {
userKeyUnlocked = isUserKeyUnlocked(userId);
storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
} finally {
Binder.restoreCallingIdentity(token);
}
boolean foundPrimary = false;
final ArrayList<StorageVolume> res = new ArrayList<>();
synchronized (mLock) {
for (int i = 0; i < mVolumes.size(); i++) {
final VolumeInfo vol = mVolumes.valueAt(i);
switch (vol.getType()) {
case VolumeInfo.TYPE_PUBLIC:
case VolumeInfo.TYPE_EMULATED:
break;
default:
continue;
}
boolean match = false;
if (forWrite) {
match = vol.isVisibleForWrite(userId);
} else {
match = vol.isVisibleForRead(userId)
|| (includeInvisible && vol.getPath() != null);
}
if (!match) continue;
boolean reportUnmounted = false;
if ((vol.getType() == VolumeInfo.TYPE_EMULATED) && !userKeyUnlocked) {
reportUnmounted = true;
} else if (!storagePermission && !realState) {
reportUnmounted = true;
}
final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
reportUnmounted);
if (vol.isPrimary()) {
res.add(0, userVol);
foundPrimary = true;
} else {
res.add(userVol);
}
}
}
if (!foundPrimary) {
Log.w(TAG, "No primary storage defined yet; hacking together a stub");
final boolean primaryPhysical = SystemProperties.getBoolean(
StorageManager.PROP_PRIMARY_PHYSICAL, false);
final String id = "stub_primary";
final File path = Environment.getLegacyExternalStorageDirectory();
final String description = mContext.getString(android.R.string.unknownName);
final boolean primary = true;
final boolean removable = primaryPhysical;
final boolean emulated = !primaryPhysical;
final boolean allowMassStorage = false;
final long maxFileSize = 0L;
final UserHandle owner = new UserHandle(userId);
final String uuid = null;
final String state = Environment.MEDIA_REMOVED;
res.add(0, new StorageVolume(id, path, path,
description, primary, removable, emulated,
allowMassStorage, maxFileSize, owner, uuid, state));
}
return res.toArray(new StorageVolume[res.size()]);
}
public void onAccessClick(View view) {
StorageManager storageManager = (StorageManager)getSystemService(Context.STORAGE_SERVICE);
StorageVolume storageVolume = storageManager.getPrimaryStorageVolume();
Intent intent = storageVolume.createAccessIntent(Environment.DIRECTORY_MUSIC);
startActivityForResult(intent, REQUEST_FOLDER_MUSIC);
}
private Api24StorageVolumeImpl(String path, StorageVolume volume) {
mPath = path;
mStorageVolume = volume;
}
private Api24StorageVolumeImpl(Parcel in) {
this.mStorageVolume = in.readParcelable(StorageVolume.class.getClassLoader());
this.mPath = in.readString();
}
public static void updateUsbOtg(final Context context) {
if (Build.VERSION.SDK_INT < 24) {
return;
}
if (swapView == null) {
Utils.debugLog(TAG, "swapView == null");
return;
}
TextView storageVolumeText = swapView.findViewById(R.id.storage_volume_text);
Button requestStorageVolume = swapView.findViewById(R.id.request_storage_volume_button);
storageVolumeText.setVisibility(View.GONE);
requestStorageVolume.setVisibility(View.GONE);
final StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
for (final StorageVolume storageVolume : storageManager.getStorageVolumes()) {
if (storageVolume.isRemovable() && !storageVolume.isPrimary()) {
Log.i(TAG, "StorageVolume: " + storageVolume);
final Intent intent = storageVolume.createAccessIntent(null);
if (intent == null) {
Utils.debugLog(TAG, "Got null Storage Volume access Intent");
return;
}
storageVolumeText.setVisibility(View.VISIBLE);
String text = storageVolume.getDescription(context);
if (!TextUtils.isEmpty(text)) {
requestStorageVolume.setText(text);
UsbDevice usb = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (usb != null) {
text = String.format("%s (%s %s)", text, usb.getManufacturerName(), usb.getProductName());
Toast.makeText(context, text, Toast.LENGTH_LONG).show();
}
}
requestStorageVolume.setVisibility(View.VISIBLE);
requestStorageVolume.setOnClickListener(new View.OnClickListener() {
@Override
@RequiresApi(api = 24)
public void onClick(View v) {
List<UriPermission> list = context.getContentResolver().getPersistedUriPermissions();
if (list != null) for (UriPermission uriPermission : list) {
Uri uri = uriPermission.getUri();
if (uri.getPath().equals(String.format("/tree/%s:", storageVolume.getUuid()))) {
intent.setData(uri);
TreeUriScannerIntentService.onActivityResult(context, intent);
return;
}
}
((Activity) context).startActivityForResult(intent,
MainActivity.REQUEST_STORAGE_ACCESS);
}
});
}
}
}
/**
* Returns the current state of the shared/external storage media at the
* given path.
*
* @return one of {@link #MEDIA_UNKNOWN}, {@link #MEDIA_REMOVED},
* {@link #MEDIA_UNMOUNTED}, {@link #MEDIA_CHECKING},
* {@link #MEDIA_NOFS}, {@link #MEDIA_MOUNTED},
* {@link #MEDIA_MOUNTED_READ_ONLY}, {@link #MEDIA_SHARED},
* {@link #MEDIA_BAD_REMOVAL}, or {@link #MEDIA_UNMOUNTABLE}.
*/
public static String getExternalStorageState(File path) {
final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
if (volume != null) {
return volume.getState();
} else {
return MEDIA_UNKNOWN;
}
}
/**
* Returns whether the shared/external storage media at the given path is
* physically removable.
*
* @return true if the storage device can be removed (such as an SD card),
* or false if the storage device is built in and cannot be
* physically removed.
* @throws IllegalArgumentException if the path is not a valid storage
* device.
*/
public static boolean isExternalStorageRemovable(File path) {
final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
if (volume != null) {
return volume.isRemovable();
} else {
throw new IllegalArgumentException("Failed to find storage device at " + path);
}
}
/**
* Returns whether the shared/external storage media at the given path is
* emulated.
* <p>
* The contents of emulated storage devices are backed by a private user
* data partition, which means there is little benefit to apps storing data
* here instead of the private directories returned by
* {@link Context#getFilesDir()}, etc.
* <p>
* This returns true when emulated storage is backed by either internal
* storage or an adopted storage device.
*
* @throws IllegalArgumentException if the path is not a valid storage
* device.
*/
public static boolean isExternalStorageEmulated(File path) {
final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
if (volume != null) {
return volume.isEmulated();
} else {
throw new IllegalArgumentException("Failed to find storage device at " + path);
}
}