文件创建无一例外失败

时间:2018-10-13 04:44:54

标签: java android

我正在尝试在Android应用中创建空白文件。我的代码在Android 5上运行良好,但是当我在Android 7或更高版本上进行测试时,它没有打印异常就失败了。

我的代码是:

downloadLocation = new File(Environment.getExternalStorageDirectory() + "/" + "folder" + System.currentTimeMillis());
downloadLocation.mkdir();

downloadFile = new File(downloadLocation, "file" + System.currentTimeMillis());
downloadFile.createNewFile();

请注意,我已经声明了变量和所有内容,只是没有包括在内。 downloadLocation和downloadFile变量都是File类型。

在我使用的Android 5物理设备上,它运行良好。然后,我使用Android 7虚拟设备进行了测试,但是它失败了,没有在日志中打印错误。问题出在第二段代码,特别是最后一行。我之所以知道这一点,是因为我在每行与每个日志输出之间都放置了一个日志,除了创建文件后的日志。

当没有错误显示时,调试某些东西非常困难,尽管存在捕获错误,该错误应该打印堆栈跟踪和异常。

有什么想法吗?

请注意,我知道该文件和文件夹尚不存在,因为我在该名称后附加了一个时间戳以防止进行测试,因为我100%知道该文件将具有唯一的名称发布中的名称。这就是为什么我没有将每个块都包含在if语句中的原因,该语句将检查以确保文件/文件夹不存在。

1 个答案:

答案 0 :(得分:0)

您的代码可能抛出未找到文件异常。在downloadLocation.mkdir()通话之后:

if (downloadLocation.exists()) { System.out.println("File Exists"); }

您会注意到该消息不会打印。这是因为您从来没有写目录的权限。

将以下内容添加到您的AndroidManifest.xml中:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

一个简单的方法来处理请求权限是一个很棒的库:EasyPermissions

使用EasyPermissions,您的代码可能类似于:

1。)您在活动中调用一个函数以触发创建文件:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    writeFiles();
}

2。)writeFiles将需要确保在执行文件操作之前已授予权限:

@AfterPermissionGranted(PERMISSIONS_REQUEST_CODE)
private void writeFiles() {
    String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
    if (EasyPermissions.hasPermissions(this, permissions)) {
        try {
            File downloadLocation = new File(Environment.getExternalStorageDirectory() + "/" + "folder" + System.currentTimeMillis());
            downloadLocation.mkdir();

            if (downloadLocation.exists()) {
                Log.i("writeFiles()", downloadLocation.getAbsolutePath());
            }

            File downloadFile = new File(downloadLocation, "file" + System.currentTimeMillis());
            downloadFile.createNewFile();
        } catch (Exception e) {
            Log.e("ERROR", e.getMessage(), e);
        }
    } else {
        // Do not have permissions, request them now
        EasyPermissions.requestPermissions(this, "Your permission rationale", PERMISSIONS_REQUEST_CODE, permissions);
    }
}

3。)为了使EasyPermissions在授予权限后再次自动调用writeFiles(),您需要添加以下覆盖:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    // Forward results to EasyPermissions
    EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}

您会发现PERMISSIONS_REQUEST_CODE使用了两次。这只是一个常量整数,您可以从Activity调用onRequestPermissionsResult时用来标识权限请求。只要它是唯一的,它就可以是您想要的任何数字(例如1000)。我链接到EasyPermissions的文档,该文档将进一步解释它的工作原理,但这大大简化了您处理运行时权限的方式。

编辑: 以下链接将帮助解释有关请求应用程序权限的更多信息:

过去,当用户将您的应用安装到Play商店中时,系统会向他们显示您的应用所需的权限列表。如果用户继续安装该应用程序,则会自动授予所有权限。 Android 6改变了这一点,现在用户可以更好地控制要授予每个应用程序的权限。

某些权限仍然不需要用户批准,这些权限被视为普通权限。一个示例是INTERNET权限。其他可能会影响隐私,系统数据等的权限被视为危险权限,并且要求用户通过权限对话框(如上所示)授予它们。我在上面发布的第二个URL将向您显示一些表,列出每个权限的资格。

请记住,如果用户拒绝许可并选中“不再显示”框,则对话框将永远不会再显示给他们,他们将不得不进入系统设置中的“应用”并从那里。如果您想帮助用户进入此屏幕,可以使用以下意图:

Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", getPackageName(), null));
startActivity(intent);