提问人:Lee 提问时间:10/10/2023 最后编辑:oolyviLee 更新时间:10/11/2023 访问量:65
为什么 MediaProvider 间歇性地拒绝外部文件访问权限?
Why does MediaProvider intermittently refuse external file access permission?
问:
在运行 Android 6 的 Pixel 13a 上,在创建/访问/删除文件时,我有时会进入 Logcat 日志MediaProvider: Permission to access file storage/emulated/0/Documents/com.myappname/myfilename is denied
为了提供一些上下文,下面的 Java 代码是在自定义 Cordova 插件中调用的。早期的测试没有发现这个问题。即使是现在,这也只发生在某些难以定义的情况下。每当它失败时,它都会记录上述消息,我认为这意味着问题不在于调用此消息的更高级别的 Javascript 和 Cordova 中间层。
有时 Java 可以成功创建文件并读取它,但在尝试删除它时会失败,我什至无法使用 Android 自己的文件应用程序删除该文件,但后来我可以了。
我认为文件可能仍在缓冲中,并尝试在连续请求之间引入延迟,尽管这并没有解决它。
我还想知道这是否可能是作用域存储问题,但为什么它有时会起作用,而其他时候却不起作用?
Android清单(phrasefix).xml:
...
<uses-sdk
android:minSdkVersion="24"
android:targetSdkVersion="33" />
...
<uses-permission android:name="ANDROID.PERMISSION.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="ANDROID.PERMISSION.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="ANDROID.PERMISSION.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
...
离线数据文件:.java:
public class OfflineDataFile {
private final String filePath;
public OfflineDataFile(Context context) {
String pkg = context.getPackageName();
String fileDir = pkg+".OfflineData";
filePath = "/Documents/" + fileDir;
}
private File getAppDir() throws IOException {
String state = Environment.getExternalStorageState();
if ( Environment.MEDIA_MOUNTED.equals( state ) ) {
return new File( Environment.getExternalStorageDirectory() + filePath );
} else {
throw new IOException("Could not mount storage");
}
}
public void write(String filename, byte[] data) throws IOException {
File appDirectory = getAppDir();
if ( !appDirectory.exists() ) {
appDirectory.mkdirs();
}
File dataFile = new File( appDirectory, filename );
dataFile.createNewFile();
FileOutputStream fos = new FileOutputStream(dataFile);
fos.write(data);
fos.close();
}
public byte[] read(String filename, Integer size) throws IOException {
File appDirectory = getAppDir();
if ( !appDirectory.exists() ) {
throw new IOException("Data directory does not exist");
}
File dataFile = new File( appDirectory, filename );
InputStream input = new FileInputStream(dataFile);
byte [] data = OfflineDataUtil.readInputStream(input, size);
input.close();
return data;
}
protected void remove(String filename) {
File appDirectory;
try {
appDirectory = getAppDir();
} catch (IOException e) {
return;
}
if ( !appDirectory.exists() ) {
return;
}
File dataFile = new File( appDirectory, filename );
if ( !dataFile.exists() ) {
return;
}
dataFile.delete();
}
}
答:
0赞
Lee
10/10/2023
#1
为了解决这个问题,我决定使用私有外部存储而不是共享外部存储,因为这些文件仅供应用程序在内部使用,因此将其重写如下(现在根据注释进行编辑)。
离线数据文件:.java:
public class OfflineDataFile {
private final File appDir;
public OfflineDataFile(Context context) throws IOException {
appDir = context.getExternalFilesDir("OfflineData");
}
public void write(String filename, byte[] data) throws IOException {
File dataFile = new File( appDir, filename );
FileOutputStream fos = new FileOutputStream(dataFile);
fos.write(data);
fos.close();
}
public byte[] read(String filename, Integer size) throws IOException {
File dataFile = new File( appDir, filename );
InputStream input = new FileInputStream(dataFile);
byte [] data = OfflineDataUtil.readInputStream(input, size);
input.close();
return data;
}
protected void remove(String filename) throws IOException {
File dataFile = new File( appDir, filename );
if (!dataFile.delete()) {
throw new IOException("Unable to delete file");
}
}
}
评论
1赞
blackapps
10/10/2023
appDir = new File( dirPath );
更改为 appDir = getExternalFilesDir(“OfflineData”);
1赞
blackapps
10/10/2023
dataFile.createNewFile();
您可以删除该语句。
1赞
blackapps
10/10/2023
if ( !appDir.exists() ) { appDir.mkdirs(); }
您可以将其全部删除。或者用 if ( !appDir.exists() ) { if(!appDir.mkdirs()) return ;
1赞
blackapps
10/10/2023
并且:if(!dataFile.delete()) 返回 false 并大喊“哦不!
评论
if ( Environment.MEDIA_MOUNTED.equals......
您可以删除该语句,因为外部存储始终可用。if (!appDirectory.exists() ) { throw new IOException.....
奇怪的结构。在调用 read() 函数之前,应检查该文件是否存在。