在本文中,我们将给您介绍关于重命名由android10中的应用程序创建的Mediastore的文件。正在使用AndroidAPI30,但在API29中显示错误的详细内容,此外,我们还将为您提供关于An
在本文中,我们将给您介绍关于重命名由android 10中的应用程序创建的Mediastore的文件。正在使用Android API 30,但在API 29中显示错误的详细内容,此外,我们还将为您提供关于Android API 30 中的外部文件读取和写入,在 JAVA 中使用 MediaStore API、Android CRUD MediaStore API 26+、Android Media Store API 在外部存储中找不到由 Google Photo 创建的图像、Android MediaStore插入图像创建的附加文件的知识。
本文目录一览:- 重命名由android 10中的应用程序创建的Mediastore的文件。正在使用Android API 30,但在API 29中显示错误
- Android API 30 中的外部文件读取和写入,在 JAVA 中使用 MediaStore API
- Android CRUD MediaStore API 26+
- Android Media Store API 在外部存储中找不到由 Google Photo 创建的图像
- Android MediaStore插入图像创建的附加文件
重命名由android 10中的应用程序创建的Mediastore的文件。正在使用Android API 30,但在API 29中显示错误
在这里,此renameFile(..)函数在Android API 30中正常工作。但是,在Android API 29中却无效,并显示如下错误:
java.lang.IllegalArgumentException:不允许移动内容:// media / external / file /116,这不是定义明确的集合的一部分
更新说明:
-开始-
为了使用sdk-29,我们必须使用Uri作为extUri =MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL),例如:
private static Uri extUri = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL);
代替下面的代码。并将 MediaStore.Files.FileColumns 更新为 MediaStore.Downloads
-结束-
Uri extUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL);String relativeLocation = Environment.DIRECTORY_DOWNLOADS + File.separator + "AppFolder";
函数renameFile(…)
boolean renameFile(Context context, String newName, String displayName) { try { Long id = getIdFromDisplayName(displayName); ContentResolver contentResolver = context.getContentResolver(); Uri mUri = ContentUris.withAppendedId(extUri, id); ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, 1); contentResolver.update(mUri, contentValues, null, null); contentValues.clear(); contentValues.put(MediaStore.Files.FileColumns.DISPLAY_NAME, newName); // contentValues.put(MediaStore.Files.FileColumns.MIME_TYPE, "files/pdf"); // contentValues.put(MediaStore.Files.FileColumns.RELATIVE_PATH, relativeLocation); // contentValues.put(MediaStore.Files.FileColumns.TITLE, "SomeName"); // contentValues.put(MediaStore.Files.FileColumns.DATE_ADDED, System.currentTimeMillis() / 1000); // contentValues.put(MediaStore.Files.FileColumns.DATE_TAKEN, System.currentTimeMillis()); contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, 0); contentResolver.update(mUri, contentValues, null, null); return true; } catch (Exception ex) { ex.printStackTrace(); } return false;}
函数getIdFromDisplayName(…)
@RequiresApi(api = Build.VERSION_CODES.Q)Long getIdFromDisplayName(String displayName) { String[] projection; projection = new String[]{MediaStore.Files.FileColumns._ID}; // TODO This will break if we have no matching item in the MediaStore. Cursor cursor = getContentResolver().query(extUri, projection, MediaStore.Files.FileColumns.DISPLAY_NAME + " LIKE ?", new String[]{displayName}, null); assert cursor != null; cursor.moveToFirst(); if (cursor.getCount() > 0) { int columnIndex = cursor.getColumnIndex(projection[0]); long fileId = cursor.getLong(columnIndex); cursor.close(); return fileId; } return null;}
答案1
小编典典java.lang.IllegalArgumentException:不允许移动内容:// media / external / file /
116,这不是定义明确的集合的一部分
因此,如果您使用集合,则不适用于Android Q;
Uri extUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL);
但允许“定义明确的集合”,例如:
Uri extUri = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);// Use "Pictures/MyFolder" for RELATIVE_PATH
我留给您查找其他定义明确的集合。
为什么这仅适用于Android Q我不知道。
您可以在以下Java文件中看到该消息:https
:
//android.googlesource.com/platform/packages/providers/MediaProvider/+/refs/heads/master/src/com/android/providers/media/MediaProvider.java
引用:
// We only support movement under well-defined collections switch (match) { case AUDIO_MEDIA_ID: case VIDEO_MEDIA_ID: case IMAGES_MEDIA_ID: case DOWNLOADS_ID: break; default: throw new IllegalArgumentException("Movement of " + uri + " which isn''t part of well-defined collection not allowed"); }
如果重命名失败,请使用SAF(如前所述)。如何在仅知道媒体内容Uri的Android中重命名文件
Android API 30 中的外部文件读取和写入,在 JAVA 中使用 MediaStore API
如何解决Android API 30 中的外部文件读取和写入,在 JAVA 中使用 MediaStore API?
我对新的 Google 政策有疑问。我正在尝试找到一种无需 MANAGE_EXTERNAL_STORAGE 权限即可读取或写入 txt 文件的方法。问题是: MediaStore API 可用于写入或读取文件,但我只能读取稍后由应用程序创建的文件。就我而言,外部软件通过 USB 连接使用 adb.exe 将数据上传到手机,并且该应用程序使用这些数据。 因为它不是由应用程序创建的,所以我收到以下示例的“FileNotFoundException”“权限被拒绝”错误消息。应用程序创建的文件是什么样的标志?我可以授予外部文件这个权利吗?
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.R){
ContentValues contentValues= new ContentValues();
String datfile = null;
contentValues.put(MediaStore.Files.FileColumns.disPLAY_NAME,"ac.dat");
contentValues.put(MediaStore.Files.FileColumns.MIME_TYPE,"");
contentValues.put(MediaStore.Files.FileColumns.RELATIVE_PATH,Environment.DIRECTORY_DOCUMENTS+dir);
Uri uri = context.getContentResolver().insert(MediaStore.Files.getContentUri("external"),contentValues);
InputStream inputStream = context.getContentResolver().openInputStream(uri);
int read = 0;
int bufferSize = 1024;
final byte[] buffers = new byte[bufferSize];
while ((read = inputStream.read(buffers)) != -1) {
datfile = new String(buffers);
}
inputStream.close();
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)
Android CRUD MediaStore API 26+
如何解决Android CRUD MediaStore API 26+?
我有一个 API26+ 的应用程序
Android 10 及更高版本 (API29+) 应使用 MediaStore
来访问文件,而不是 Environment.getExternalStoragePublicDirectory
通常在创建 if-block 时会产生新的方法
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
// deprecated code
} else {
// new approach
}
但是:
-
MediaStorage
使用Uri
请求文件。 API28 及以下版本使用File
或String
作为文件路径 - 使用
MediaStore
不需要手动创建文件夹。如果 API 28 及以下版本不存在,则应创建一个文件夹。 - 删除文件需要用户与
MediaStore
交互。
CRUD:
-
创建:需要为任何 API 在文件中写入数据
OutputStream
。这可以通过if else
实现
-
读取:如何创建读取文件的通用方法,其中 API 29+ 需要
Uri
,API28- 需要File|String
才能访问文件? -
更新:首先读取以检查是否存在,然后创建以获取
OutputStream
-
删除:如何使用
MediaStore
创建批量确认?
是否可以通过 API26+ 使用 MediaStorage
?
如果是,如何? API29中首先添加了许多属性
解决方法
经过一些自己的研究和测试,我找到了同时使用 MediaStore
和旧设备的方法。
首先需要一些辅助类:
使用 FileType
,我们可以同时在应用程序中支持不同的文件类型。
public enum FileType {
File(Environment.DIRECTORY_DOCUMENTS,Constants.VERSION_29_ABOVE ? MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL) : null,"text/plain"),Download(Environment.DIRECTORY_DOWNLOADS,Constants.VERSION_29_ABOVE ? MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL) : null,Image(Environment.DIRECTORY_PICTURES,Constants.VERSION_29_ABOVE ? MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL) : null,"image/jpeg"),Audio(Environment.DIRECTORY_MUSIC,Constants.VERSION_29_ABOVE ? MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL) : null,"audio/mpeg"),Video(Environment.DIRECTORY_MOVIES,Constants.VERSION_29_ABOVE ? MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL) : null,"video/mpeg");
private final String directory;
private final Uri contentUri;
private String mimeType;
FileType(String directory,Uri contentUri,String mimeType) {
this.directory = directory;
this.contentUri = contentUri;
this.mimeType = mimeType;
}
public String getDirectory() {
return directory;
}
public Uri getContentUri() {
return contentUri;
}
public String getMimeType() {
return mimeType;
}
public void setMimeType(String mimeType) {
this.mimeType = mimeType;
}
}
使用 setMimeType
我们可以更改当前文件扩展名并仍然使用其他设置
我们需要简单的回调类来得到不同的结果
public interface ObjectCallback<T> {
void result(T object);
}
当我们想在文件中写入一些数据时,我们需要一个 OutputStream
使用内部存储,获取文件的方式没有改变
/**
* opens OutputStream to write data to file
*
* @param context activity context
* @param fileName relative file name
* @param fileType file type to get folder specific values for access
* @param fileStream callback with file output stream to requested file
* @return true if output stream successful opened,false otherwise
*/
public boolean openOutputStream(Context context,String fileName,FileType fileType,ObjectCallback<OutputStream> fileStream) {
File internalFolder = context.getExternalFilesDir(fileType.getDirectory());
File absFileName = new File(internalFolder,fileName);
try {
FileOutputStream fOut = new FileOutputStream(absFileName);
fileStream.result(fOut);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
通过外部存储,在 API 28- 和 API 29+ 上访问文件的方式完全不同。
在 API 28 上,我们可以只使用一个文件。
在 API 29+ 上,我们应该首先检查文件是否已经存在。如果它(比如 text.txt
)存在并且我们将创建 ContentResolver.insert
,它将创建 text-1.txt
并且在最坏的情况下(无限循环)可以快速填满整个智能手机存储。
/**
* @param context application context
* @param fileName relative file name
* @return uri to file or null if file not exist
*/
public Uri getFileUri(Context context,String fileName) {
// remove folders from file name
fileName = fileName.contains("/") ? fileName.substring(fileName.lastIndexOf("/") + 1) : fileName;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
// Deprecated in API 29
File storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),Constants.PUBLIC_STORAGE_FOLDER);
File file = new File(storageDir,fileName);
return file.exists() ? Uri.fromFile(file) : null;
} else {
String folderName = Environment.DIRECTORY_PICTURES + File.separator + Constants.PUBLIC_STORAGE_FOLDER + File.separator;
// get content resolver that can interact with public storage
ContentResolver resolver = context.getContentResolver();
String selection = MediaStore.MediaColumns.RELATIVE_PATH + "=?";
String[] selectionArgs = new String[]{folderName};
Cursor cursor = resolver.query(MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL),null,selection,selectionArgs,null);
Uri uri = null;
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
String itemFileName = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME));
if (itemFileName.equals(fileName)) {
long id = cursor.getLong(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
uri = ContentUris.withAppendedId(MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL),id);
break;
}
}
}
cursor.close();
return uri;
}
}
/**
* opens OutputStream to write data to file
*
* @param context activity context
* @param fileName relative file name
* @param fileType file type to get folder specific values for access
* @param fileStream callback with file output stream to requested file
* @return true if output stream successful opened,ObjectCallback<OutputStream> fileStream) {
// remove folders from file name
fileName = fileName.contains("/") ? fileName.substring(fileName.lastIndexOf("/") + 1) : fileName;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
File storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),Constants.PUBLIC_STORAGE_FOLDER);
if (!storageDir.exists() && !storageDir.mkdir()) {
// directory for file not exists and not created. return false
return false;
}
File file = new File(storageDir,fileName);
try {
FileOutputStream fOut = new FileOutputStream(file);
fileStream.result(fOut);
} catch (Exception e) {
e.printStackTrace();
return false;
}
} else {
// get content resolver that can interact with public storage
ContentResolver resolver = context.getContentResolver();
// always check first if file already exist
Uri existFile = getFileUri(context,fileName);
if (existFile == null) {
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.MIME_TYPE,fileType.getMimeType());
// absolute folder name
values.put(MediaStore.MediaColumns.RELATIVE_PATH,fileType.getDirectory() + File.separator + Constants.PUBLIC_STORAGE_FOLDER);
// file name
values.put(MediaStore.MediaColumns.DISPLAY_NAME,fileName);
// create uri to the file. If folder not exists,it would be created automatically
Uri uri = resolver.insert(fileType.getContentUri(),values);
// open stream from uri and write data to file
try (OutputStream outputStream = resolver.openOutputStream(uri)) {
fileStream.result(outputStream);
// end changing of file
// when this point reached,no exception was thrown and file write was successful
values.put(MediaStore.MediaColumns.IS_PENDING,false);
resolver.update(uri,values,null);
} catch (Exception e) {
e.printStackTrace();
if (uri != null) {
// Don''t leave an orphan entry in the MediaStore
resolver.delete(uri,null);
}
return false;
}
} else {
// open stream from uri and write data to file
try (OutputStream outputStream = resolver.openOutputStream(existFile)) {
fileStream.result(outputStream);
} catch (Exception e) {
e.printStackTrace();
// Don''t leave an orphan entry in the MediaStore
resolver.delete(existFile,null);
return false;
}
}
}
return true;
}
可以在所有设备和不同存储空间上以相同的方式打开 InputStream
。
删除文件:
- internal 仍然可以在每个 API 上使用
file.delete
删除 - 使用 API29+ 的外部存储需要用户交互才能删除某些文件
文件提供者
要使用 Intent
来显示一些图片、裁剪图片或其他什么,我们使用 setDataAndType
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(photoUri,"image/*");
// allow to read the file
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
在某些情况下我们需要 FileProvider。特别:
要显示使用应用程序创建的外部文件,photoUri
会以这种方式显示
Uri photoUri = Constants.VERSION_29_ABOVE ? uriToFile :
FileProvider.getUriForFile(context,context.getApplicationContext().getPackageName() + ".provider",new File(uriToFile.getPath()));
Android Media Store API 在外部存储中找不到由 Google Photo 创建的图像
如何解决Android Media Store API 在外部存储中找不到由 Google Photo 创建的图像?
我尝试实现一个图库应用程序,该应用程序还显示按其包含目录分组的所有本地存储图像文件。 为此,我构建了 MediaStore API。
我的代码找不到本地图像目录,如果这些目录和图像文件是由 Google 相册创建的。 但是,如果我使用 Google 文件在受影响的目录中复制/移动/创建图像文件,那么我的应用会找到该图像。
我做错了什么?
注意:我说的是外部存储上 Pictures/ 目录下的真实文件系统目录。我不是在谈论 Google 相册在云中创建的相册。 根据 developer documentation,MediaStore API 应在 Pictures/ 目录下找到所有图像。
图像,包括照片和屏幕截图,存储在 DCIM/ 和 Pictures/ 目录中。系统会将这些文件添加到 MediaStore.Images 表中。
简化代码:
清单
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
简化的数据类
public class LocalFolder {
public final long id;
public final Uri coverUri;
public LocalFolder( final long id,final Uri coverUri ) {
this.id = id;
this.coverUri = coverUri;
}
}
为内部数据库播种的简化代码
protected TreeMap< Long,LocalFolder > database;
public void run() {
final Uri collection = ( Build.VERSION.SDK_INT < Build.VERSION_CODES.Q ) ?
MediaStore.Images.Media.EXTERNAL_CONTENT_URI :
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
final String[] projection = {
MediaStore.Images.Media._ID,MediaStore.Images.Media.BUCKET_ID };
final Cursor cursor = contentResolver.query(
collection,projection,null,null
);
if(cursor == null) return;
// Cache column indices
final int imageIdColumn = cursor.getColumnIndexOrThrow( MediaStore.Images.Media._ID );
final int folderIdColumn = cursor.getColumnIndexOrThrow( MediaStore.Images.Media.BUCKET_ID );
while( cursor.movetoNext() ) {
// Compile all required attributes
final long imageId = cursor.getLong( imageIdColumn );
final long folderId = cursor.getLong( folderIdColumn );
final Uri coverUri = ContentUris.withAppendedId( collection,imageId );
// If the image is contained in a folder,which already has been processed,skip
if( database.containsKey( folderId ) )
continue;
// Create the folder and take the current image as cover image
final LocalFolder localFolder = new LocalFolder( folderId,coverUri );
database.put( folderId,localFolder );
}
cursor.close();
}
重现步骤:
- 创建一个新的共享图像文件
- 打开您最喜欢的网络浏览器并下载图像文件
- 图片文件放在共享的Downloads/目录下
- 上面的代码找到了图像(很好!)
- 使用 Google 相册将图像文件移动到基于文件系统的新目录中
- 打开 Google 相册
- 打开注册“图书馆”
- 打开相册“下载”
- 打开最近添加的图片
- 点按“设置”(右上角的点)
- 点按“移至文件夹”
- 点按“新建文件夹”
- 创建一个新文件夹
- 上面的代码没有找到图像(糟糕!)
- 使用 Google 文件“重新创建”图像文件
- 打开 Google 文件
- 点按汉堡菜单
- 点按设备
- 打开目录图片/
- 打开谷歌相册新建目录对应的子目录
- 长按最近添加的图片文件
- 移动图像文件并将图像文件移回文件夹
- 上面的代码找到了新文件夹和图像(很好!)
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)
Android MediaStore插入图像创建的附加文件
我使用以下代码片段在MediaStore缓存中插入一个Image:
MediaStore.Images.Media.insertimage(getContentResolver(),selectedFile.getParent()file.separator selectedFile.getName(),selectedFile.getName(),null);
插入没问题,但它也在同一路径上创建了另一个图像缩略图.这在图库中不可见,但在使用文件浏览器浏览时,此图像缩略图可见.如何在此处停止创建此图像缩略图,以免混淆用户.
解决方法:
MediaStore.Images.Media.insertimage()的文档说它:
Insert an image and create a thumbnail
for it.
您实际需要做的是访问Media Scanner服务.
默认情况下,该服务在启动期间或插入SD卡后运行.你可以强制它使用意图运行,但你最终重新扫描整个SD卡一个.
当然,有一个更好的解决方案:
如果您正在开发API级别8或更高级别(Android 2.2),请使用
来自MediaScannerConnection的scanFile静态函数,记录为here.
对于API 7或更低版本,它有点复杂,但您可以使用以下帖子中最佳解释的包装器将所有内容放在一起:
dynamically add pictures to gallery widget
关于重命名由android 10中的应用程序创建的Mediastore的文件。正在使用Android API 30,但在API 29中显示错误的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于Android API 30 中的外部文件读取和写入,在 JAVA 中使用 MediaStore API、Android CRUD MediaStore API 26+、Android Media Store API 在外部存储中找不到由 Google Photo 创建的图像、Android MediaStore插入图像创建的附加文件的相关信息,请在本站寻找。
本文标签: