Android 写入外部存储
Android write on external Storage
我正在尝试使用以下代码在我的外部存储中写入一些可绘制对象:
Bitmap bm = BitmapFactory.decodeResource( getResources(), R.drawable.paco);
File file = new File( Environment.getExternalStorageDirectory(), "paco.png");
FileOutputStream outStream = null;
try {
FileOutputStream out = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 90, out);
out.flush();
out.close();
Log.d("XXXXX","voy a cerrar");
} catch (Exception e) {
Log.e("XXXXX","eeeee", e);
}
但我不断收到此错误:
28476-28476/com.example.usuari.myapplication3 E/XXXXX: eeeee
java.io.FileNotFoundException: /storage/emulated/0/paco.png: open
failed: EACCES (Permission denied)
at libcore.io.IoBridge.open(IoBridge.java:452)
at java.io.FileOutputStream.(FileOutputStream.java:87)
at java.io.FileOutputStream.(FileOutputStream.java:72)
at
com.example.usuari.myapplication3.MainActivity.iniciarDrawables(MainActivity.java:276)
at
com.example.usuari.myapplication3.MainActivity.onCreate(MainActivity.java:90)
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.access00(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)
at java.io.FileOutputStream.(FileOutputStream.java:87)
at java.io.FileOutputStream.(FileOutputStream.java:72)
at
com.example.usuari.myapplication3.MainActivity.iniciarDrawables(MainActivity.java:276)
at
com.example.usuari.myapplication3.MainActivity.onCreate(MainActivity.java:90)
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.access00(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)
我的清单中有权限条目:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.usuari.myapplication3">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
编辑:我正在使用 sdk 23
如果您是 API 23+,您必须在运行时请求权限(尽管它们已经存在于清单文件中)。
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
Android Sdk >=23 需要用户的运行时权限。仅添加清单权限是行不通的。
试试这个代码:
if(isPermissionGranted()){
//open file
}
public boolean isPermissionGranted() {
if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
Log.v("TAG","Permission is granted");
return true;
} else {
Log.v("TAG","Permission is revoked");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
return false;
}
}
else { //permission is automatically granted on sdk<23 upon installation
Log.v("TAG","Permission is granted");
return true;
}
}
捕获权限结果:
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 0: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(), "Permission granted", Toast.LENGTH_SHORT).show();
//call your method open file
} else {
Toast.makeText(getApplicationContext(), "Permission denied", Toast.LENGTH_SHORT).show();
}
return;
}
}
}
首先,检查您的存储是否准备就绪:
if (Environment.getExternalStorageState(file) != Environment.MEDIA_MOUNTED) {
// your storage is not ready for work, do something with this
}
其次,据我所知,从 Kit-Kat 开始,您无法写入外部存储的根目录。
只允许写入存储上的应用程序特定文件夹。
要获取此文件夹,请使用
Environment.getExternalStoragePublicDirectory(directoryType);
directoryType 怎么样,检查方法的文档,您可能想要使用 Environment.DIRECTORY_PICTURES。
试试这个。
我正在尝试使用以下代码在我的外部存储中写入一些可绘制对象:
Bitmap bm = BitmapFactory.decodeResource( getResources(), R.drawable.paco);
File file = new File( Environment.getExternalStorageDirectory(), "paco.png");
FileOutputStream outStream = null;
try {
FileOutputStream out = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 90, out);
out.flush();
out.close();
Log.d("XXXXX","voy a cerrar");
} catch (Exception e) {
Log.e("XXXXX","eeeee", e);
}
但我不断收到此错误:
28476-28476/com.example.usuari.myapplication3 E/XXXXX: eeeee java.io.FileNotFoundException: /storage/emulated/0/paco.png: open failed: EACCES (Permission denied) at libcore.io.IoBridge.open(IoBridge.java:452) at java.io.FileOutputStream.(FileOutputStream.java:87) at java.io.FileOutputStream.(FileOutputStream.java:72) at com.example.usuari.myapplication3.MainActivity.iniciarDrawables(MainActivity.java:276) at com.example.usuari.myapplication3.MainActivity.onCreate(MainActivity.java:90) 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.access00(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) at java.io.FileOutputStream.(FileOutputStream.java:87) at java.io.FileOutputStream.(FileOutputStream.java:72) at com.example.usuari.myapplication3.MainActivity.iniciarDrawables(MainActivity.java:276) at com.example.usuari.myapplication3.MainActivity.onCreate(MainActivity.java:90) 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.access00(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)
我的清单中有权限条目:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.usuari.myapplication3">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
编辑:我正在使用 sdk 23
如果您是 API 23+,您必须在运行时请求权限(尽管它们已经存在于清单文件中)。
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
Android Sdk >=23 需要用户的运行时权限。仅添加清单权限是行不通的。
试试这个代码:
if(isPermissionGranted()){
//open file
}
public boolean isPermissionGranted() {
if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
Log.v("TAG","Permission is granted");
return true;
} else {
Log.v("TAG","Permission is revoked");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
return false;
}
}
else { //permission is automatically granted on sdk<23 upon installation
Log.v("TAG","Permission is granted");
return true;
}
}
捕获权限结果:
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 0: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(), "Permission granted", Toast.LENGTH_SHORT).show();
//call your method open file
} else {
Toast.makeText(getApplicationContext(), "Permission denied", Toast.LENGTH_SHORT).show();
}
return;
}
}
}
首先,检查您的存储是否准备就绪:
if (Environment.getExternalStorageState(file) != Environment.MEDIA_MOUNTED) {
// your storage is not ready for work, do something with this
}
其次,据我所知,从 Kit-Kat 开始,您无法写入外部存储的根目录。 只允许写入存储上的应用程序特定文件夹。 要获取此文件夹,请使用
Environment.getExternalStoragePublicDirectory(directoryType);
directoryType 怎么样,检查方法的文档,您可能想要使用 Environment.DIRECTORY_PICTURES。
试试这个。