Android 无法对 sd 卡进行写入和删除操作
Android couldn't able to write and delete operation on sd card
我现在正在开发 ImageCompressor 应用程序。
我需要 delete
和 write
(更新)图像文件。在内部存储中运行完美,但 **SD 卡无法让我访问删除和写入文件。
我的应用程序如何能够在 SD 卡(可移动存储)上执行 write
和 delete
操作?
我已经在没有这个的情况下完成了整个项目,所以我必须找到一种方法。
更新:
我已经在研究和讨论这个问题了。并且明白我必须使用 storage access framework
但我是 SAF 的新手。
我使用 库 来压缩需要 文件而不是 Uri 的照片。为此,我 Uri -> File
并使用 Intent.ACTION_OPEN_DOCUMENT
并从可移动存储中选择图像。
But for removable storage I can't find Image Real Path from uri.
不知道这样对不对。如果有任何方法 在 SAF 中我可以使用 uri 压缩我的图像,请告诉我。或 如何从可移动存储照片的 uri 获取图像真实路径。
更新代码SAF:
// ----------- Intent -------------
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
// ------------ On Activity Result --------------
Uri uri = data.getData();
try {
ParcelFileDescriptor fileDescriptor = getContentResolver().openFileDescriptor(uri, "w");
FileOutputStream fos = new FileOutputStream(fileDescriptor.getFileDescriptor());
FileInputStream fis = new FileInputStream(getImageFilePath(uri));
FileChannel source = fis.getChannel();
FileChannel destination = fos.getChannel();
destination.transferFrom(source, 0, source.size());
fis.close();
fos.close();
fileDescriptor.close();
Toast.makeText(this, "File save successfully.", Toast.LENGTH_SHORT).show();
}
Uri 到文件路径,我完成了从媒体应用程序(如 Gallary、Photos)中选择图像但从 SD 卡中选择什么而不是 MediaStore.Images.Media.DATA
我不知道不知道。代码:
private File getImageFilePath(Uri uri) throws IOException {
String image_id = null, imagePath = null;
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
image_id = cursor.getString(0);
image_id = image_id.substring(image_id.lastIndexOf(":") + 1);
cursor.close();
}
cursor = getContentResolver().query(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", new String[]{image_id}, null);
if (cursor!=null) {
cursor.moveToFirst();
imagePath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
cursor.close();
}
File file = new File(imagePath);
return new Compressor(this).setQuality(50).compressToFile(file);
}
如果您使用文件和 FileOutputStream 类。
,则可移动 SD 卡只能在现代 Android 设备上写入
如果你幸运的话,你的设备会使用 getExternalFilesDirs()
returns 作为卡上应用程序特定目录的第二项,你仍然可以在其中写入。
对于其余部分,请改用 Storage Access Framework。
首先让用户选择 Intent.ACTION_OPEN_DOCUMENT_TREE
的 sd 卡或 Intent.ACTION_OPEN_DOCUMENT
的文件。
你试过了
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("mount");
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
String line;
BufferedReader br = new BufferedReader(isr);
while ((line = br.readLine()) != null) {
//Filter common Linux partitions
if (line.contains("secure"))
continue;
if (line.contains("asec"))
continue;
if (line.contains("media"))
continue;
if (line.contains("system") || line.contains("cache")
|| line.contains("sys") || line.contains("data")
|| line.contains("tmpfs") || line.contains("shell")
|| line.contains("root") || line.contains("acct")
|| line.contains("proc") || line.contains("misc")
|| line.contains("obb")) {
continue;
}
if (line.contains("fat") || line.contains("fuse") || (line
.contains("ntfs"))) {
String columns[] = line.split(" ");
if (columns != null && columns.length > 1) {
String path = columns[1];
if (path!=null&&!SdList.contains(path)&&path.contains("sd"))
SdList.add(columns[1]);
}
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
我深入研究了我的一个旧 Android 应用程序并检索到了这个 :
此方法将 sdcard uri 的根目录转换为 File
路径。
public File getRootPath(Context context, Uri sdcardRootUri)
{
List<String> pathSegments = sdcardRootUri.getPathSegments();
String[] tokens = pathSegments.get(pathSegments.size()-1).split(":");
for (File f : ContextCompat.getExternalFilesDirs(context, null))
{
String path = f.getAbsolutePath().substring(0, f.getAbsolutePath().indexOf("/Android/"));
if (path.contains(tokens[0]))
{
return new File(path);
}
}
return null;
}
为了检索 sdcard 根的 uri,我使用了它:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, SDCARD_ROOT_CODE);
然后用户选择sdcard的根目录,然后,我这样处理结果:
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (resultCode == RESULT_OK && requestCode == SDCARD_ROOT_CODE)
{
// Persist access permissions
Uri sdcdardRootUri = data.getData();
grantUriPermission(getPackageName(), sdcdardRootUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(sdcdardRootUri, takeFlags);
// Do whatever you want with sdcdardRootUri
}
}
希望这就是您要找的。有了它,您可以 read/write/delete SD 卡上的任何文件。
我现在正在开发 ImageCompressor 应用程序。
我需要 delete
和 write
(更新)图像文件。在内部存储中运行完美,但 **SD 卡无法让我访问删除和写入文件。
我的应用程序如何能够在 SD 卡(可移动存储)上执行 write
和 delete
操作?
我已经在没有这个的情况下完成了整个项目,所以我必须找到一种方法。
更新:
我已经在研究和讨论这个问题了。并且明白我必须使用 storage access framework
但我是 SAF 的新手。
我使用 库 来压缩需要 文件而不是 Uri 的照片。为此,我 Uri -> File
并使用 Intent.ACTION_OPEN_DOCUMENT
并从可移动存储中选择图像。
But for removable storage I can't find Image Real Path from uri.
不知道这样对不对。如果有任何方法 在 SAF 中我可以使用 uri 压缩我的图像,请告诉我。或 如何从可移动存储照片的 uri 获取图像真实路径。
更新代码SAF:
// ----------- Intent -------------
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
// ------------ On Activity Result --------------
Uri uri = data.getData();
try {
ParcelFileDescriptor fileDescriptor = getContentResolver().openFileDescriptor(uri, "w");
FileOutputStream fos = new FileOutputStream(fileDescriptor.getFileDescriptor());
FileInputStream fis = new FileInputStream(getImageFilePath(uri));
FileChannel source = fis.getChannel();
FileChannel destination = fos.getChannel();
destination.transferFrom(source, 0, source.size());
fis.close();
fos.close();
fileDescriptor.close();
Toast.makeText(this, "File save successfully.", Toast.LENGTH_SHORT).show();
}
Uri 到文件路径,我完成了从媒体应用程序(如 Gallary、Photos)中选择图像但从 SD 卡中选择什么而不是 MediaStore.Images.Media.DATA
我不知道不知道。代码:
private File getImageFilePath(Uri uri) throws IOException {
String image_id = null, imagePath = null;
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
image_id = cursor.getString(0);
image_id = image_id.substring(image_id.lastIndexOf(":") + 1);
cursor.close();
}
cursor = getContentResolver().query(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", new String[]{image_id}, null);
if (cursor!=null) {
cursor.moveToFirst();
imagePath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
cursor.close();
}
File file = new File(imagePath);
return new Compressor(this).setQuality(50).compressToFile(file);
}
如果您使用文件和 FileOutputStream 类。
,则可移动 SD 卡只能在现代 Android 设备上写入如果你幸运的话,你的设备会使用 getExternalFilesDirs()
returns 作为卡上应用程序特定目录的第二项,你仍然可以在其中写入。
对于其余部分,请改用 Storage Access Framework。
首先让用户选择 Intent.ACTION_OPEN_DOCUMENT_TREE
的 sd 卡或 Intent.ACTION_OPEN_DOCUMENT
的文件。
你试过了
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("mount");
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
String line;
BufferedReader br = new BufferedReader(isr);
while ((line = br.readLine()) != null) {
//Filter common Linux partitions
if (line.contains("secure"))
continue;
if (line.contains("asec"))
continue;
if (line.contains("media"))
continue;
if (line.contains("system") || line.contains("cache")
|| line.contains("sys") || line.contains("data")
|| line.contains("tmpfs") || line.contains("shell")
|| line.contains("root") || line.contains("acct")
|| line.contains("proc") || line.contains("misc")
|| line.contains("obb")) {
continue;
}
if (line.contains("fat") || line.contains("fuse") || (line
.contains("ntfs"))) {
String columns[] = line.split(" ");
if (columns != null && columns.length > 1) {
String path = columns[1];
if (path!=null&&!SdList.contains(path)&&path.contains("sd"))
SdList.add(columns[1]);
}
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
我深入研究了我的一个旧 Android 应用程序并检索到了这个 :
此方法将 sdcard uri 的根目录转换为 File
路径。
public File getRootPath(Context context, Uri sdcardRootUri)
{
List<String> pathSegments = sdcardRootUri.getPathSegments();
String[] tokens = pathSegments.get(pathSegments.size()-1).split(":");
for (File f : ContextCompat.getExternalFilesDirs(context, null))
{
String path = f.getAbsolutePath().substring(0, f.getAbsolutePath().indexOf("/Android/"));
if (path.contains(tokens[0]))
{
return new File(path);
}
}
return null;
}
为了检索 sdcard 根的 uri,我使用了它:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, SDCARD_ROOT_CODE);
然后用户选择sdcard的根目录,然后,我这样处理结果:
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (resultCode == RESULT_OK && requestCode == SDCARD_ROOT_CODE)
{
// Persist access permissions
Uri sdcdardRootUri = data.getData();
grantUriPermission(getPackageName(), sdcdardRootUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(sdcdardRootUri, takeFlags);
// Do whatever you want with sdcdardRootUri
}
}
希望这就是您要找的。有了它,您可以 read/write/delete SD 卡上的任何文件。