我想使用公共外部存储在设备中写入图像。因此,我有1)在清单中写有权限标签,以及2)在需要时使用checkSelfPermission
请求权限。但是我仍然有一个例外:java.io.FileNotFoundException: /storage/emulated/03b3d97bd-5186-4506-97dc-9994b7ce0761 (Permission denied)
。
为什么?我已经读过https://developer.android.com/guide/topics/permissions/overview#normal-dangerous,但没有回答我的问题。
我已授予Android设备上的存储权限。因此,正确执行了我的条件if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
(请参见下文),但其条件else
被执行了。并且此else
包含一行以将文件保存到存储中:但是它返回此异常...
目标是在用户授予许可后致电saveImageAndShareIt
。
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
通常,由于具有写权限,应该隐式识别已读内容。
下面是onRequestPermissionsResult
方法。如果用户接受授予许可,则调用saveImageAndShareIt
。
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
System.out.println("onrequestPR");
if (grantResults.length > 0) {
if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
System.out.println("onrequestPR accepted");
saveImageAndShareIt();
}
}
}
onRequestPermissionsResult
由requestPermissions
调用,如下所示:
if (Build.VERSION.SDK_INT >= 23) {
int permissionCheck = ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
} else {
System.out.println("last_case1");
saveImageAndShareIt();
System.out.println("last_case2");
}
} else {
System.out.println("peperoni");
saveImageAndShareIt();
System.out.println("pizza");
}
因此,如果用户已授予该权限,则无需调用requestPermissions
,因此直接调用saveImageAndShareIt
(换句话说:onRequestPermissionsResult
不需要被执行以调用saveImageAndShareIt
)。
通过实例化FileOutputStream
引发异常。
private void saveImageAndShareIt() {
OutputStream output;
try {
System.out.println("siasi1");
output = new FileOutputStream(Environment.getExternalStorageDirectory() + image_uuid);
byte[] buffer = new byte[1024];
int bytesRead;
BitmapDrawable bitmapDrawable = (BitmapDrawable) temp.getDrawable();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmapDrawable.getBitmap().compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] imageInByte = stream.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(imageInByte);
while ((bytesRead = bis.read(buffer, 0, buffer.length)) >= 0) {
output.write(buffer, 0, bytesRead);
}
output.close();
System.out.println("siasi2");
intent_share.putExtra(Intent.EXTRA_STREAM, Uri.parse(Environment.getExternalStorageDirectory() + image_uuid));
activity.startActivity(Intent.createChooser(intent_share, "Share to"));
System.out.println("siasi3");
} catch(IOException e) {
e.printStackTrace();
}
}
W / System.err:java.io.FileNotFoundException: / storage / emulated / 03b3d97bd-5186-4506-97dc-9994b7ce0761(权限 W / System.err:at java.io.FileOutputStream.open0(Native 方法) 在java.io.FileOutputStream.open(FileOutputStream.java:287)W / System.err:在 java.io.FileOutputStream。(FileOutputStream.java:223) W / System.err:位于 java.io.FileOutputStream。(FileOutputStream.java:110) 在com.example ... ClipboardDialogFragment.saveImageAndShareIt(ClipboardDialogFragment.java:115) 在com.example ... ClipboardDialogFragment.access $ 300(ClipboardDialogFragment.java:42) W / System.err:位于 com.example ... ClipboardDialogFragment $ 1 $ 2 $ 1.onTaskCompleted(ClipboardDialogFragment.java:75) W / System.err:位于 com.example ... DownloadImageTask.onPostExecute(DownloadImageTask.java:34) 在com.example ... DownloadImageTask.onPostExecute(DownloadImageTask.java:10) W / System.err:位于android.os.AsyncTask.finish(AsyncTask.java:695) 在android.os.AsyncTask.-wrap1(未知来源:0)W / System.err:在 android.os.AsyncTask $ InternalHandler.handleMessage(AsyncTask.java:712) W / System.err:位于 android.os.Handler.dispatchMessage(Handler.java:105) 在android.os.Looper.loop(Looper.java:164) android.app.ActivityThread.main(ActivityThread.java:6944)W / System.err:java.lang.reflect.Method.invoke(本机方法) 在com.android.internal.os.Zygote $ MethodAndArgsCaller.run(Zygote.java:327) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
答案 0 :(得分:2)
即使授予了文件许可权,您也无法访问SD卡和其他可移动媒体。自从KitKat以来我没有记错,除非用户在内置文档应用中启用了访问权限。
您需要使用DocumentsProvider或通过StorageVolume获得另一个权限/ uri,并使用DocumentsContract(sample project)进行解析。
编辑:根据您的例外情况:
/storage/emulated/03b3d97bd-5186-4506-97dc-9994b7ce0761
默认外部目录为/storage/emulated/0
,看起来您忘记在目录名称后添加分隔符:
output = new FileOutputStream(Environment.getExternalStorageDirectory() +"/"+ image_uuid);