资料
https://developer.android.google.cn/training/data-storage/app-specific?hl=zh-cn
MindMap
planuml
见代码plantuml
代码
https://gitee.com/hellosunshine/application_data_storage.git
文章目录
存储路径获取
getFilesDir();
getCacheDir();
getExternalFilesDir("mp4");
getExternalCacheDir();
获取文件
File file = new File(context.getFilesDir(), fileName);
通过文件流写入文件
///信息流存储文件
private void writeToApplicationDirFile(Context context) throws IOException {
String fileContents = "Hello world! 你好";
try (FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE)) {
fos.write(fileContents.getBytes());
}
}
信息流访问文件内容
///信息流访问文件
private void readFromApplicationDirFile(Context context) throws FileNotFoundException {
FileInputStream fis = context.openFileInput(fileName);
InputStreamReader inputStreamReader = new InputStreamReader(fis, StandardCharsets.UTF_8);
StringBuilder stringBuilder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(inputStreamReader)) {
String line = reader.readLine();
while (line != null) {
stringBuilder.append(line).append('\n');
line = reader.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
String contents = stringBuilder.toString();
}
}
查看文件列表
///查看文件列表
private void getFileList(Context context) {
String[] files = context.fileList();
for (String file : files) {
}
}
创建潜逃目录
///创建嵌套目录
private void createFileDir(Context context) {
File directory = context.getFilesDir();
File file = new File(directory, fileName);
}
缓存文件
///创建缓存文件
private File createFileCache(Context context) throws IOException {
return File.createTempFile(fileName, null, context.getCacheDir());
}
///移除缓存文件
private void deleteCacheFile(File cacheFile) {
boolean result = cacheFile.delete();
}
///移除缓存文件
private void deleteCacheFileByName(Context context) {
boolean result = context.deleteFile(fileName);
}
检查外部存储控件是否可以读写文件
///检查外部存储空间中是否可以读写文件
private boolean isExternalStorageWritable() {
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
}
///至少可以读文件
private boolean isExternalStorageReadable() {
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) || Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY);
}
选择物理存储位置
///选择物理存储位置
private void choosePhysicStorage() {
File[] externalStorageVolumes = ContextCompat.getExternalFilesDirs(getApplicationContext(), null);
File primaryExternalStorage = externalStorageVolumes[0];
}
访问持久性文件
///访问持久性文件
private void getExternalFileDir(Context context) {
File appSpecificExternalDir = new File(context.getExternalFilesDir(null), fileName);
}
创建缓存文件
private void createCacheFile(Context context) {
File externalCacheFile = new File(context.getExternalCacheDir(), fileName);
}
媒体内容
File getAppSpecificAlbumStorageDir(Context context, String albumName) {
File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(TAG, "Directory not created");
}
return file;
}
查询可用空间
private void searchDevicesAvailable() throws IOException {
long NUM_BYTES_NEEDED_FOR_MY_APP = 1024 * 1024 * 10L;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
StorageManager storageManager = getApplicationContext().getSystemService(StorageManager.class);
UUID appSpecificInternalDirUuid = storageManager.getUuidForPath(getFilesDir());
///可用空间
long availableBytes = storageManager.getAllocatableBytes(appSpecificInternalDirUuid);
if (availableBytes >= NUM_BYTES_NEEDED_FOR_MY_APP) {
storageManager.allocateBytes(appSpecificInternalDirUuid, NUM_BYTES_NEEDED_FOR_MY_APP);
} else {
///管理存储,释放空间
Intent storageIntent = new Intent();
storageIntent.setAction(ACTION_MANAGE_STORAGE);
startActivity(storageIntent);
}
}
}
显示设备上可用空间量
private void showAllocatedSpace() throws IOException {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
StorageStatsManager storageStatsManager = (StorageStatsManager) getSystemService(Context.STORAGE_STATS_SERVICE);
StorageManager storageManager = getApplicationContext().getSystemService(StorageManager.class);
UUID appSpecificInternalDirUuid = storageManager.getUuidForPath(getFilesDir());
long freeBytes = storageStatsManager.getFreeBytes(appSpecificInternalDirUuid);
long totalBytes = storageStatsManager.getTotalBytes(appSpecificInternalDirUuid);
double value = (float) freeBytes / totalBytes;
Toast.makeText(getApplicationContext(), String.valueOf(value), Toast.LENGTH_LONG).show();
}
}
移除所有缓文件
///移除所有缓文件
@RequiresApi(api = Build.VERSION_CODES.R)
private void clearAllCache() {
Intent intent = new Intent();
intent.setAction(ACTION_CLEAR_APP_CACHE);
startActivityForResult(intent, 1000);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode == 1000) {
Toast.makeText(getApplicationContext(), "调用", Toast.LENGTH_LONG).show();
}
super.onActivityResult(requestCode, resultCode, data);
}
访问共享媒体文件(MediaStore)
///媒体库
private void getMediaStore() {
String[] projection = new String[]{};
String seleciton = "";
String[] selectionArgs = new String[]{};
String sortOrder = "";
@SuppressLint("Recycle") Cursor cursor = getApplicationContext().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
// MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
// MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
// MediaStore.Downloads.EXTERNAL_CONTENT_URI,
// MediaStore.Files,
projection, seleciton, selectionArgs, sortOrder);
while (cursor.moveToNext()) {
}
}
获取媒体库的版本
///获取媒体库的版本
private void getVersion(Context context) {
String v = MediaStore.getVersion(context);
}
查询媒体集合(视频 & 图片)
///视频类
class Video {
private final Uri uri;
private final String name;
private final int duration;
private final int size;
public Video(Uri uri, String name, int duration, int size) {
this.uri = uri;
this.name = name;
this.duration = duration;
this.size = size;
}
}
///查询媒体集合(视频)
private void queryMediaCollection(Context context) {
List<Video> videoList = new ArrayList<>();
Uri collection;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
collection = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
} else {
collection = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
}
String[] projection = new String[]{MediaStore.Video.Media._ID, MediaStore.Video.Media.DISPLAY_NAME, MediaStore.Video.Media.DURATION, MediaStore.Video.Media.SIZE, MediaStore.Video.Media.DATA,};
String selection = MediaStore.Video.Media.DURATION + ">= ?";
String[] selectionArgs = new String[]{String.valueOf(TimeUnit.MILLISECONDS.convert(1, TimeUnit.MINUTES))};
String sortOrder = MediaStore.Video.Media.DISPLAY_NAME + " ASC";
try (Cursor cursor = context.getContentResolver().query(collection, projection, selection, selectionArgs, sortOrder)) {
int idColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID);
int nameColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME);
int durationColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION);
int sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE);
int dataColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
while (cursor.moveToNext()) {
long id = cursor.getLong(idColumn);
String name = cursor.getString(nameColumn);
int duration = cursor.getInt(durationColumn);
int size = cursor.getInt(sizeColumn);
String path = cursor.getString(dataColumn);
System.out.println(path);
Uri contentUri = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id);
///加载文件缩略图
Bitmap bitmap = loadFileThumbnail(contentUri);
///打开媒体文件
openMediaFile(contentUri);
///获取媒体的位置信息
getVideoInfo(contentUri, context);
///原生代码更新
remoteCodeUpdate(contentUri);
videoList.add(new Video(contentUri, name, duration, size));
}
Toast.makeText(context, videoList.size() + "个", Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
}
///查询媒体集合(图片)
private void queryPhotoCollection(Context context) {
Uri collection;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
collection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
} else {
collection = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
}
String[] projection = new String[]{MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.SIZE, MediaStore.Images.Media.DATA,};
String sortOrder = MediaStore.Images.Media.DISPLAY_NAME + " ASC";
try (Cursor cursor = context.getContentResolver().query(collection, projection, null, null, sortOrder)) {
int idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
int nameColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME);
int sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE);
int data = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
while (cursor.moveToNext()) {
long id = cursor.getLong(idColumn);
String name = cursor.getString(nameColumn);
int size = cursor.getInt(sizeColumn);
Uri contentUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
String path = cursor.getString(data);
///获取媒体的拍摄位置
getPhotoInfo(contentUri);
}
}
}
获取媒体的缩略图
///加载文件缩略图
private Bitmap loadFileThumbnail(Uri contentUri) throws IOException {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
return getApplicationContext().getContentResolver().loadThumbnail(contentUri, new Size(640, 480), null);
}
return null;
}
打开媒体文件
///打开媒体文件
private void openMediaFile(Uri contentUri) throws IOException {
ContentResolver resolver = getApplicationContext().getContentResolver();
//rw 读和写; rwt 覆盖已有的文件
String readOnlyMode = "r";
//文件描述符
try (ParcelFileDescriptor parcelFileDescriptor = resolver.openFileDescriptor(contentUri, readOnlyMode)) {
} catch (IOException e) {
e.printStackTrace();
}
//文件流
try (InputStream stream = resolver.openInputStream(contentUri)) {
}
}
查看其他分卷
///查看其他分卷
private void checkOutOtherVolume(Context context) {
Set<String> volumeNames = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
volumeNames = MediaStore.getExternalVolumeNames(context);
String firstVolumeName = volumeNames.iterator().next();
}
}
获取媒体的拍摄位置(图片 & 视频)
///获取媒体的拍摄位置(图片)
private void getPhotoInfo(Uri photoUri) {
float[] latLong = new float[2];
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
photoUri = MediaStore.setRequireOriginal(photoUri);
InputStream stream = null;
try {
stream = getApplicationContext().getContentResolver().openInputStream(photoUri);
if (stream != null) {
ExifInterface exifInterface = new ExifInterface(stream);
boolean returnedLatLong = exifInterface.getLatLong(latLong);
if (returnedLatLong) {
float la = latLong[0];
float lo = latLong[1];
} else {
latLong = new float[2];
}
stream.close();
} else {
latLong = new float[2];
}
} catch (IOException e) {
e.printStackTrace();
}
} else {
latLong = new float[2];
}
}
//获取媒体的位置信息
private void getVideoInfo(Uri videoUri, Context context) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setDataSource(context, videoUri);
} catch (RuntimeException e) {
e.printStackTrace();
}
String locationMetadata = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION);
}
添加媒体
//添加媒体到媒体库中
private Uri addMedia() {
ContentResolver resolver = getApplicationContext().getContentResolver();
Uri videoCollection;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
videoCollection = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
} else {
videoCollection = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
}
ContentValues newSongDetails = new ContentValues();
Random random = new Random();
double number = random.nextInt(1000);
newSongDetails.put(MediaStore.Video.Media.DISPLAY_NAME, "My Video" + number + ".mp4");
Uri uri = resolver.insert(videoCollection, newSongDetails);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
try(Cursor cursor = getApplicationContext().getContentResolver().query(uri, new String[] {MediaStore.Video.Media.DATA}, null, null)) {
int data = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
while (cursor.moveToNext()) {
System.out.println(cursor.getString(data));
}
}
}
return uri;
}
///耗时操作写入媒体
@RequiresApi(api = Build.VERSION_CODES.Q)
private void addMediaWithinLongTime() {
ContentResolver resolver = getApplicationContext().getContentResolver();
Uri audioCollection;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
audioCollection = MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
} else {
audioCollection = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
ContentValues songDetails = new ContentValues();
songDetails.put(MediaStore.Audio.Media.DISPLAY_NAME, "My Workout Playlist.mp3");
songDetails.put(MediaStore.Audio.Media.IS_PENDING, 1);
Uri songContentUri = resolver.insert(audioCollection, songDetails);
try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(songContentUri, "w", null)) {
} catch (IOException e) {
e.printStackTrace();
}
songDetails.clear();
songDetails.put(MediaStore.Audio.Media.IS_PENDING, 0);
resolver.update(songContentUri, songDetails, null, null);
}
更新媒体
///更新项目(自己app创建的可以修改)
private void updateProject(Uri uri) {
ContentResolver resolver = getApplicationContext().getContentResolver();
ContentValues updatedSongDetails = new ContentValues();
updatedSongDetails.put(MediaStore.Video.Media.DISPLAY_NAME, "My Favorite video.mp4");
try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "w", null)) {
String path = uri.getPath();
int numSongsUpdated = resolver.update(uri, updatedSongDetails, null, null);
} catch (IOException e) {
e.printStackTrace();
}
}
原生代码更新
///原生代码更新
private void remoteCodeUpdate(Uri contentUri) throws FileNotFoundException {
ContentResolver resolver = getApplicationContext().getContentResolver();
String fileOpenMode = "r";
@SuppressLint("Recycle") ParcelFileDescriptor parcelFd = resolver.openFileDescriptor(contentUri, fileOpenMode);
if (parcelFd != null) {
int fd = parcelFd.detachFd();
// Pass the integer value "fd" into your native code. Remember to call
// close(2) on the file descriptor when you're done using it.
}
}
删除媒体
///删除媒体
private void deleteMedia(Uri uri) {
ContentResolver contentResolver = getApplicationContext().getContentResolver();
String selection = "";
String[] selectionArgs = {""};
int numImagesRemoved = contentResolver.delete(uri, selection, selectionArgs);
}
检查媒体文件的更新
///检查媒体文件的更新
private void checkMediaUpdate(Context context, String volumeName) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
long number = MediaStore.getGeneration(context, volumeName);
}
}
管理媒体文件组 createWriteRequest()
///管理媒体文件组 createWriteRequest()
private void manageMediaGroupCreateWriteRequest(Uri uri) throws IntentSender.SendIntentException {
ContentResolver contentResolver = getApplicationContext().getContentResolver();
List<Uri> urisToModify = new ArrayList<>();
urisToModify.add(uri);
PendingIntent editPendingIntent = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
editPendingIntent = MediaStore.createWriteRequest(contentResolver, urisToModify);
startIntentSenderForResult(editPendingIntent.getIntentSender(), EDIT_REQUEST_CODE, null, 0, 0, 0);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == EDIT_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
/* Edit request granted; proceed. */
} else {
/* Edit request not granted; explain to the user. */
}
}
}