我正在尝试创建外部目录结构,以便将某些文件从设备存储移动到Android手机中的SD卡。我已经按照https://developer.android.com/training/permissions/requesting.html中给出的步骤和多个stackoverflow答案进行了操作。但是,当我尝试创建目录时,我的程序失败了。
我的AndroidManifest.xml
文件包含以下行:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
相关代码如下:
public int mkFolder(String folderName){
String state = Environment.getExternalStorageState();
if (!Environment.MEDIA_MOUNTED.equals(state)){
Log.d(TAG, "Error: external storage is unavailable");
return 0;
}
if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
Log.d(TAG, "Error: external storage is read only.");
return 0;
}
Log.d(TAG, "External storage is not read only or unavailable");
boolean writePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED;
boolean readPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED;
final boolean permissionNotGranted = writePermission|| readPermission;
if (permissionNotGranted) {
Log.i(TAG, "STORAGE permissions NOT granted");
// Should we show an explanation?
boolean shouldShowRationaleForWritePermssion = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
boolean shouldShowRationaleForReadPermssion = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE);
if (shouldShowRationaleForWritePermssion || shouldShowRationaleForReadPermssion) {
// 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 {
ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}
} else {
Log.i(TAG, "STORAGE permissions granted");
}
// File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),folderName);
File folder = new File(folderName);
int result = 0;
if (folder.exists()) {
Log.d(TAG,"folder exist:"+folder.toString());
result = 2; // folder exist
}else{
try {
if (folder.mkdirs()) {
Log.d(TAG, "folder created:" + folder.toString());
result = 0; // folder created
} else {
Log.d(TAG, "create folder fails:" + folder.toString());
result = 1; // create folder fails
}
}catch (Exception ecp){
ecp.printStackTrace();
}
}
return result;
}
public static final int REQUEST_EXTERNAL_STORAGE = 112;
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String permissions[], @NonNull int[] grantResults) {
Log.e(TAG, "onRequestPermissionsResult invoked");
switch (requestCode) {
case REQUEST_EXTERNAL_STORAGE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
Log.i(TAG, "Permission to write to external storage granted");
Toast.makeText(this, "Permission to write to external storage granted", Toast.LENGTH_LONG).show();
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Log.e(TAG, "Permission to write to external storage NOT granted");
Toast.makeText(this, "Permission to write to external storage NOT granted", Toast.LENGTH_LONG).show();
}
}
// other 'case' lines to check for other
// permissions this app might request
}
}
以下是日志的摘录:
MainActivity: /storage/0000-0000 false true
MainActivity: /storage/0000-0000/MyDir does not exist. Creating target parent directory
MainActivity: STORAGE permissions granted
MainActivity: Creation of directory /storage/0000-0000/MyDir failed with return value 1. Aborting...
有人可以帮我理解我的代码中的错误吗?
答案 0 :(得分:1)
从Android 4.4开始,您没有removable storage上任意位置的直接文件系统访问权限。 WRITE_EXTERNAL_STORAGE
在这里没有意义,因为external storage不是可移动存储。
使用存储访问框架(ACTION_OPEN_DOCUMENT_TREE
和亲属)代替。或者,将您的工作限制为getExternalFilesDirs()
,getExternalCacheDirs()
和getExternalMediaDirs()
(Context
上的所有方法)中返回的可移动存储位置。