如何在Android中获得对可移动媒体上DCIM目录的写访问权?
我的代码如下:如何在Android中获得对可移动媒体上DCIM目录的写访问权?,android,permissions,Android,Permissions,我的代码如下: public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); writeFile();
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
writeFile();
}
public void writeFile() {
File removableRoot = RootsUtil.getRemovableRoots(this)[0];
File DCIMDirectory = new File(removableRoot, "DCIM");
File cameraDirectory = new File(DCIMDirectory, "Camera");
if( cameraDirectory.exists() ) {
try {
String filename = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date()) + ".txt";
//cameraDirectory.mkdirs();
File file = new File(cameraDirectory, filename);
FileWriter writer = null;
writer = new FileWriter(file);
PrintWriter printWriter = new PrintWriter(writer);
printWriter.println("Hello World");
printWriter.close();
writer.close();
System.out.println("Number of files: " + cameraDirectory.listFiles().length);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
cameraDirectory
等于if和它存在之前的/storage/9C33-6BBD/DCIM/Camera
。这是我的相机
应用程序存储其文件的地方
我也尝试将文件写入此目录,但失败,出现以下异常:
java.io.FileNotFoundException: /storage/9C33-6BBD/DCIM/Camera/20170204_192001.txt: open failed: EACCES (Permission denied)
at libcore.io.IoBridge.open(IoBridge.java:452)
at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
at java.io.FileOutputStream.<init>(FileOutputStream.java:72)
at java.io.FileWriter.<init>(FileWriter.java:42)
at com.inthemoon.trycamerawrite.MainActivity.writeFile(MainActivity.java:48)
at com.inthemoon.trycamerawrite.MainActivity.onCreate(MainActivity.java:28)
at android.app.Activity.performCreate(Activity.java:6876)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1135)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3207)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350)
at android.app.ActivityThread.access$1100(ActivityThread.java:222)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Posix.open(Native Method)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
at libcore.io.IoBridge.open(IoBridge.java:438)
... 17 more
然后允许用户手动选择DCIM/Camera,但这没有帮助。您试图直接写入可移动存储的文件系统。这将不起作用,除非选择应用程序特有的目录(例如,
getExternalFilesDirs()
返回的目录)
使用ACTION\u OPEN\u DOCUMENT\u TREE
不会神奇地授予您文件系统访问权限。它所做的是为您提供一个Uri
,您可以将其与ContentResolver
、DocumentFile
和kin一起使用,以基于该Uri
处理文档和集合
ACTION\u OPEN\u DOCUMENT\u TREE
是文档的一部分,包含在文档中
Android 7.0+还提供了一种更简单的方式,用户可以通过这种方式在可移动存储上授予您访问类似于
DCIM/
的内容的权限。但是,它也给了您一个Uri
,您仍然可以使用ContentResolver
、DocumentFile
,等等来处理基于该Uri
其他文件夹工作的内容和集合?您在清单中授予了写存储权限吗?您的目标sdk是什么?在gradle?cameraDirectory.mkdirs()中代码>。不要盲目地调用mkdirs()。首先检查目录是否存在。并检查返回值,因为它可能无法创建目录,在这种情况下返回false。如果是的话,向说这句话的用户敬酒。然后返回。不要继续你的代码,因为试图在一个不存在的目录中创建一个文件是没有意义的。@greenapps抱歉,我不得不继续尝试,因为似乎没有人知道我需要的答案;当我找到它时,它的价值就越大:)我对Uri
没有任何异议。我只是想知道,如果有一个Uri
,我可以如何将“Hello world”文本写入引用文件:)这可能吗?@Dims:同样,它不是一个文件。使用fromTreeUri()
为所选树创建文档文件。创建一个文档文件
,指向要写入的树中的位置。对该DocumentFile
调用getUri()
,以获取文档的Uri
。将其传递到ContentResolver
上的openOutputStream()
。然后,写入流,flush()
流和close()
流。好吧,那么为什么我不能用uri.fromFile(myPoorFile)
创建uri,然后从“将它传递到openOurputStream”这几个字继续你的食谱?@Dims:因为你没有对文件系统的直接写访问权。从ACTION\u OPEN\u DOCUMENT\u树
和getUri()
获取的Uri
将有一个内容
方案。您正在告诉内容提供者
要写什么;它基于Uri
将内容写入任何有意义的地方。对于可移动存储,系统提供的可移动存储提供程序对其具有写访问权限,而您的应用程序对其上的任意位置没有写访问权限。@Dims:安装期间没有。此外,当您的targetSdkVersion
达到23或更高版本时,您引用的danger
权限需要与Android 6.0+上的用户进行运行时交互。关于ACTION\u OPEN\u DOCUMENT\u树
,一旦获得Uri
,调用以获得对该树的持久访问。
private static final int RQS_OPEN_DOCUMENT_TREE = 2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE, Uri.fromFile(cameraDirectory));
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, RQS_OPEN_DOCUMENT_TREE);
//writeFile();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
writeFile();
}