java.io.FileNotFoundException (Permission denied) 尝试写入 Android sdcard 时
Posted
技术标签:
【中文标题】java.io.FileNotFoundException (Permission denied) 尝试写入 Android sdcard 时【英文标题】:java.io.FileNotFoundException (Permission denied) When trying to write to the Android sdcard 【发布时间】:2011-06-16 23:26:07 【问题描述】:我正在尝试从照片库中选择一个图像文件并写入 SD 卡。下面是导致异常的代码。尝试创建 FileOutputStream 时似乎会引发此异常。我将以下行添加到嵌套在应用程序元素内的清单文件中。我找不到问题的解决方案:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
public boolean saveSelectedImage( Uri selectedImage, int imageGroup,
int imageNumber )
boolean exception = false;
InputStream input = null;
OutputStream output = null;
if( externalStorageIsWritable() )
try
ContentResolver content = ctx.getContentResolver();
input = content.openInputStream( selectedImage );
if(input != null) Log.v( CLASS_NAME, "Input Stream Opened successfully");
File outFile = null;
File root = Environment.getExternalStorageDirectory( );
if(root == null) Log.v(CLASS_NAME, "FAILED TO RETRIEVE DIRECTORY");
else Log.v(CLASS_NAME, "ROOT DIRECTORY is:"+root.toString());
output = new FileOutputStream( root+"/Image"+ imageGroup + "_" + imageNumber + ".png" );
if(output != null) Log.e( CLASS_NAME, "Output Stream Opened successfully");
// output = new FileOutputStream
// ("/sdcard/Image"+imageGroup+"_"+imageNumber+".png");
byte[] buffer = new byte[1000];
int bytesRead = 0;
while ( ( bytesRead = input.read( buffer, 0, buffer.length ) ) >= 0 )
output.write( buffer, 0, buffer.length );
catch ( Exception e )
Log.e( CLASS_NAME, "Exception occurred while moving image: ");
e.printStackTrace();
exception = true;
finally
// if(input != null)input.close();
// if(output != null)output.close();
// if (exception ) return false;
return true;
else
return false;
【问题讨论】:
您是否已在清单中请求写入权限? 我找到了问题的答案 uses-permission 元素必须在清单文件中的 application 元素之外。 【参考方案1】:这就是清单文件的样子
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".WriteCBTextToFileActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
【讨论】:
【参考方案2】:我遇到了这个问题,这里的答案并没有解决它,因为我犯了一个非常愚蠢的错误。
确保你给你的安卓模拟器一个 SD 卡...我把 SD 卡的大小留为空白,所以它当然找不到任何东西。最重要的是,我在所述 SD 卡中指定了一个尚未创建的目录,因此请务必考虑这种情况。
(您可以通过转到 Android 虚拟设备管理器、编辑您选择的模拟器并输入一些 SD 卡大小值来更改 AVD 的 SD 卡设置)
【讨论】:
他们为什么默认将其留空...今天有如此多的应用程序依赖于 SDCard。【参考方案3】:您还必须确保外部存储子系统处于正确状态;使用Environment.getExternalStorageState()
并寻找Environment.MEDIA_MOUNTED
,这是唯一安全的状态。
在这些部分周围将异常处理范围缩小到 IOException
也是一个好主意,这样您就不会从特定于 IO 的问题中过度恢复,例如媒体已卸载。
如果您需要事件,有广播意图 (Intent.ACTION_MEDIA_xxx
),您可以使用 IntentListener
注册相同的信息。
另请注意,当您使用 USB 进行调试时,外部存储可能会禁用!
在设备启动期间还有一段较长的时间,外部存储不可用。如果你在启动时在服务中做一些事情,这是一个问题。
一般来说,您的应用程序在访问外部存储时必须了解它的状态,并处理不可用或在访问时变得不可用的情况。
【讨论】:
具体来说,您应该测试 Environment.getExternalStorageState() 返回 Environment.MEDIA_MOUNTED。这是唯一允许写入的存储状态。【参考方案4】:如果您在清单中设置了正确的权限,请确保您的设备在连接到 PC 时未处于“磁盘驱动器”模式。将其更改为“仅充电”模式,它应该可以工作。
【讨论】:
【参考方案5】:请注意,除了 Saurabh 的回答之外,从 API 23 开始,您需要在运行时请求权限。
请看这里: https://developer.android.com/training/permissions/requesting.html
Justin Fiedler 的回答在这里:https://***.com/a/33288986/328059
此外,在更改权限并使用 Instant Run 重新运行应用程序后,我遇到过几种情况,但权限未更新。因此,作为最佳实践,在更改清单后,我会从目标设备上卸载应用程序,然后重新构建。
【讨论】:
【参考方案6】:你可以试试:
String myPath=Environment.getExternalStorageDirectory()+"/Image"+ imageGroup + "_" + imageNumber + ".png";
File myFile = new File();
input = new FileInputStream(myFile);
【讨论】:
【参考方案7】:尽量使用openFileOutput("filename")
返回一个FileOutputStream,而不是自己指定位置。
检查文档 here
【讨论】:
这仅适用于私有文件(只能由调用应用程序访问)。以上是关于java.io.FileNotFoundException (Permission denied) 尝试写入 Android sdcard 时的主要内容,如果未能解决你的问题,请参考以下文章