You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 33写入应用专属文件时触发Permission denied异常求助

Android应用专属目录写入权限拒绝异常解决

问题重现

开发App两个月,操作应用专属文件目录的创建、写入与读取时持续抛出权限拒绝异常:

java.io.IOException: Permission denied
at java.io.UnixFileSystem.createFileExclusively0(Native Method)
at java.io.UnixFileSystem.createFileExclusively(UnixFileSystem.java:317)
at java.io.File.createNewFile(File.java:1006)
at com.adoc.apktest.Tools.writeFile(Tools.java:36)
at com.adoc.apktest.GeneralFunctions.testCallLog(GeneralFunctions.java:71)
at com.adoc.apktest.Tests.run(Tests.java:98)

官方文档明确说明:

你的应用读写这些目录下的文件不需要任何系统权限。

相关代码如下:

MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
...
    String testID = getIntent().getStringExtra("testID");
    Tools tools = new Tools(this);
    Tests tests = new Tests(testID, this, tools);
    tests.start();

Tests.java

public Tests(String testID, Context context, Tools tools) {
    this.testID = testID;
    this.context = context;
    this.tools = tools;
}

@Override
public void run() {
    super.run();

    try {
        switch (testID) {
...
        case "generalFunctions": {
                GeneralFunctions.testCallLog(context, tools, "016");
...

GeneralFunctions.java

public static void testCallLog(Context context, Tools tools, String number) {
    try {
        tools.deleteFile("pcStatus.txt");
        while (!tools.readFile("pcStatus.txt").equals("id=" + number)) {
            Log.w("General Functions", "pcStatus.txt not found");
            Thread.sleep(1000);
        }
        tools.deleteFile("status.txt");

        Log.i("Call Log Test (" + number + ")", "Number to call: " + number);
        Intent call = new Intent(Intent.ACTION_CALL);
        call.setData(Uri.parse("tel:" + number));

        context.startActivity(call);

        tools.writeFile("status.txt", "endCall", false);
...

Tools.java

public void writeFile(String fileName, String content, boolean append) {
    File file = new File(context.getFilesDir(), fileName);

    try {
        if (!file.exists()) {
            file.createNewFile();
        }
        FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE);
        fos.write(content.getBytes());
        fos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    Log.i("Write File", "File: " + file.getAbsoluteFile() + "\nwritten successfully with data: " + content);
}

问题原因

你在writeFile方法中手动调用file.createNewFile()是多余的,且是触发权限异常的直接原因:

  • context.openFileOutput()会自动在应用专属的files/目录下创建不存在的文件,无需手动调用createNewFile()
  • 手动创建文件时,可能因系统文件锁、并发操作或Context状态问题触发权限拒绝(尽管路径属于应用专属,但手动创建逻辑与系统API的内部处理存在冲突)

另外存在一个潜在问题:你在Tests的run方法(推测为子线程)中调用context.startActivity(call),未添加FLAG_ACTIVITY_NEW_TASK标记,会触发Activity启动异常,可能间接影响后续文件操作流程。

修复方案

  1. 修改Tools.java的writeFile方法,移除手动创建文件的代码,同时修复append参数未生效的问题:
public void writeFile(String fileName, String content, boolean append) {
    File file = new File(context.getFilesDir(), fileName);

    try {
        // 移除手动创建文件逻辑,由openFileOutput自动处理
        int mode = append ? Context.MODE_APPEND : Context.MODE_PRIVATE;
        FileOutputStream fos = context.openFileOutput(fileName, mode);
        fos.write(content.getBytes());
        fos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    Log.i("Write File", "File: " + file.getAbsoluteFile() + "\nwritten successfully with data: " + content);
}
  1. 修复子线程启动Activity的问题,在GeneralFunctions.java中补充Intent标记:
Intent call = new Intent(Intent.ACTION_CALL);
call.setData(Uri.parse("tel:" + number));
// 添加子线程启动Activity必需的标记
call.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(call);

内容的提问来源于stack exchange,提问作者user22748368

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 16:13:28