Android:没有向SD卡写入数据的权限
在我的应用程序中,我需要将一些mp4文件下载到存储器中。有一个选项菜单可选择mp4文件的位置(电话存储或SD卡存储)。 我通过reflect android SDK获得手机存储路径和SD卡存储路径,如下图:Android:没有向SD卡写入数据的权限,android,Android,在我的应用程序中,我需要将一些mp4文件下载到存储器中。有一个选项菜单可选择mp4文件的位置(电话存储或SD卡存储)。 我通过reflect android SDK获得手机存储路径和SD卡存储路径,如下图: public class StorageUtils { private static final String TAG = "===StorageUtil==="; public static String getPrimaryStoragePath(Context co
public class StorageUtils {
private static final String TAG = "===StorageUtil===";
public static String getPrimaryStoragePath(Context context) {
try {
StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
Method getVolumePathsMethod = StorageManager.class.getMethod("getVolumePaths", null);
String[] paths = (String[]) getVolumePathsMethod.invoke(sm, null);
// first element in paths[] is primary storage path
return paths[0];
} catch (Exception e) {
Log.e(TAG, "getPrimaryStoragePath() failed", e);
}
return null;
}
public static String getSecondaryStoragePath(Context context) {
try {
StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
Method getVolumePathsMethod = StorageManager.class.getMethod("getVolumePaths", null);
String[] paths = (String[]) getVolumePathsMethod.invoke(sm, null);
// second element in paths[] is secondary storage path
return paths[1];
} catch (Exception e) {
Log.e(TAG, "getSecondaryStoragePath() failed", e);
}
return null;
}
public static String getStorageState(Context context, String path) {
try {
StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
Method getVolumeStateMethod = StorageManager.class.getMethod("getVolumeState", new Class[]{String.class});
String state = (String) getVolumeStateMethod.invoke(sm, path);
return state;
} catch (Exception e) {
Log.e(TAG, "getStorageState() failed", e);
}
return null;
}
}
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
和我的测试代码如下:
public class StorageTestActivity extends AppCompatActivity {
private TextView primaryStoragePath;
private TextView slaveStoragePath, tvStatus;
private Button btn1, btn2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_storage_test);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
primaryStoragePath = (TextView) findViewById(R.id.primaryStoragePath);
slaveStoragePath = (TextView) findViewById(R.id.slaveStoragePath);
//state: mounted, shared, removed
final String path1 = StorageUtils.getPrimaryStoragePath(this);
String state1 = StorageUtils.getStorageState(this, path1);
StringBuilder sb1 = new StringBuilder().append("path1:").append(path1).append("\n").append("state1=").append(state1);
primaryStoragePath.setText(sb1.toString());
final String path2 = StorageUtils.getSecondaryStoragePath(this);
String state2 = StorageUtils.getStorageState(this, path2);
StringBuilder sb2 = new StringBuilder().append("path2:").append(path2).append("\n").append("state2=").append(state2);
slaveStoragePath.setText(sb2.toString());
btn1 = (Button) findViewById(R.id.btnWriteToPrimaryStorage);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
currentType = 0;
writeData(path1);
}
});
btn2 = (Button) findViewById(R.id.btnWriteToSDCard);
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
currentType = 1;
writeData(path2);
}
});
tvStatus = (TextView) findViewById(R.id.tvStatus);
}
private int currentType = 0;
private void writeData(final String path) {
Runnable runnable = new Runnable() {
@Override
public void run() {
String state = StorageUtils.getStorageState(StorageTestActivity.this, path);
if(!"mounted".equals(state)) {
Snackbar.make(slaveStoragePath, "state is " + state, Snackbar.LENGTH_LONG).show();
return;
}
String tmpPath = path+File.separator+"Android/data/com.example.fjz.myapplication/";
File directory = new File(tmpPath);
if (!directory.exists()) {
Log.e("========", "create directories.");
directory.mkdirs();
}
File file = new File(tmpPath + "abcdefg.txt");
if (file.exists()) {
file.delete();
}
try {
file.createNewFile();
handler.sendEmptyMessage(currentType);
} catch (IOException e) {
e.printStackTrace();
handler.sendEmptyMessage(3);
}
Log.e("storage test activity:", file.getAbsolutePath());
}
};
new Thread(runnable).start();
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if(msg.what == 0) {
tvStatus.setText("Write primary success");
} else if(msg.what == 1) {
tvStatus.setText("Write SD card success");
} else {
tvStatus.setText("Write failed.");
}
}
};
然后出错:
public class StorageTestActivity extends AppCompatActivity {
private TextView primaryStoragePath;
private TextView slaveStoragePath, tvStatus;
private Button btn1, btn2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_storage_test);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
primaryStoragePath = (TextView) findViewById(R.id.primaryStoragePath);
slaveStoragePath = (TextView) findViewById(R.id.slaveStoragePath);
//state: mounted, shared, removed
final String path1 = StorageUtils.getPrimaryStoragePath(this);
String state1 = StorageUtils.getStorageState(this, path1);
StringBuilder sb1 = new StringBuilder().append("path1:").append(path1).append("\n").append("state1=").append(state1);
primaryStoragePath.setText(sb1.toString());
final String path2 = StorageUtils.getSecondaryStoragePath(this);
String state2 = StorageUtils.getStorageState(this, path2);
StringBuilder sb2 = new StringBuilder().append("path2:").append(path2).append("\n").append("state2=").append(state2);
slaveStoragePath.setText(sb2.toString());
btn1 = (Button) findViewById(R.id.btnWriteToPrimaryStorage);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
currentType = 0;
writeData(path1);
}
});
btn2 = (Button) findViewById(R.id.btnWriteToSDCard);
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
currentType = 1;
writeData(path2);
}
});
tvStatus = (TextView) findViewById(R.id.tvStatus);
}
private int currentType = 0;
private void writeData(final String path) {
Runnable runnable = new Runnable() {
@Override
public void run() {
String state = StorageUtils.getStorageState(StorageTestActivity.this, path);
if(!"mounted".equals(state)) {
Snackbar.make(slaveStoragePath, "state is " + state, Snackbar.LENGTH_LONG).show();
return;
}
String tmpPath = path+File.separator+"Android/data/com.example.fjz.myapplication/";
File directory = new File(tmpPath);
if (!directory.exists()) {
Log.e("========", "create directories.");
directory.mkdirs();
}
File file = new File(tmpPath + "abcdefg.txt");
if (file.exists()) {
file.delete();
}
try {
file.createNewFile();
handler.sendEmptyMessage(currentType);
} catch (IOException e) {
e.printStackTrace();
handler.sendEmptyMessage(3);
}
Log.e("storage test activity:", file.getAbsolutePath());
}
};
new Thread(runnable).start();
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if(msg.what == 0) {
tvStatus.setText("Write primary success");
} else if(msg.what == 1) {
tvStatus.setText("Write SD card success");
} else {
tvStatus.setText("Write failed.");
}
}
};
01-18 16:05:12.819 30125-30601/com.example.myapplication W/System.err:
java.io.IOException:打开失败:EACCES(权限被拒绝)01-18
16:05:12.819 30125-30601/com.example.myapplication W/System.err:在java.io.File.createNewFile(File.java:978)01-18 16:05:12.819 30125-30601/com.example.myapplication W/System.err:at com.example.fjz.demo.StorageTestActivity$4.run(StorageTestActivity.java:108) 01-18 16:05:12.819 30125-30601/com.example.myapplication W/System.err: 在java.lang.Thread.run(Thread.java:841)01-18 16:05:12.819 30125-30601/com.example.myapplication W/System.err:由以下原因引起: libcore.io.ErrnoException:打开失败:EACCES(权限被拒绝) 01-18 16:05:12.819 30125-30601/com.example.myapplication W/System.err: 在libcore.io.Posix.open(本机方法)01-18 16:05:12.819 30125-30601/com.example.myapplication W/System.err:at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)01-18 16:05:12.819 30125-30601/com.example.myapplication W/System.err:at java.io.File.createNewFile(File.java:971)01-18 16:05:12.819 30125-30601/com.example.myapplication W/System.err:。。。还有两个 在清单文件中,我已声明权限:
非常感谢您的帮助您需要在AndroidManifest.xml中添加写入权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
我声明权限如下:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
幸运的是,我明白了
1) 我将sdcard
路径设置为/storaget/sdcard1
2) 然后我创建路径/storaget/sdcard1/Android/data/com.example.sdcard.demo
3) 尝试mkdirs(path)
,然后返回false,因此我没有权限创建'Android/data/com.example.sdcard.demo'
目录
4)我可以调用
api:getExternalCacheDir
,它可以成功创建此目录。此问题经常发生,因为权限声明在错误的位置……它需要位于应用程序标记之外……因此,您可以使用此文件sd=Environment.getExternalStorageDirectory()进行检查;Log.e(“CHECK WRITE”,sd.canWrite()+”);" "