File.createNewFile() 方法在 Android M 中抛出异常
File.createNewFile() method throws exception in Android M
我在 Android M 中创建文件时遇到问题。
我使用 Nexus 9 和 Android 6.0.1。然后我在我的项目中设置如下:
AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
build.gradle
android {
defaultConfig {
targetSdkVersion 23
...
}
}
MainActivity.Java
public class MainActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String storagePath = Environment.getExternalStorageDirectory().getAbsolutePath();
String rootPath = storagePath + "/test";
String fileName = "/test.zip";
File root = new File(rootPath);
if(!root.mkdirs()) {
Log.i("Test", "This path is already exist: " + root.getAbsolutePath());
}
File file = new File(rootPath + fileName);
try {
if (!file.createNewFile()) {
Log.i("Test", "This file is already exist: " + file.getAbsolutePath());
}
} catch (Exception e) {
e.printStackTrace();
}
}
构建成功并启动了应用程序,但我收到如下异常消息:
IO异常
01-07 18:13:40.669 18027-18027/com.sample.myapplication W/System.err: java.io.IOException: open failed: ENOENT (No such file or directory)
01-07 18:13:40.669 18027-18027/com.sample.myapplication W/System.err: at java.io.File.createNewFile(File.java:939)
01-07 18:13:40.669 18027-18027/com.sample.myapplication W/System.err: at com.sample.myapplication.MainActivity.onCreate(MainActivity.java:36)
01-07 18:13:40.670 18027-18027/com.sample.myapplication W/System.err: at android.app.Activity.performCreate(Activity.java:6251)
01-07 18:13:40.670 18027-18027/com.sample.myapplication W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
01-07 18:13:40.670 18027-18027/com.sample.myapplication W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
01-07 18:13:40.670 18027-18027/com.sample.myapplication W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
01-07 18:13:40.670 18027-18027/com.sample.myapplication W/System.err: at android.app.ActivityThread.-wrap11(ActivityThread.java)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at android.os.Looper.loop(Looper.java:148)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5417)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at java.lang.reflect.Method.invoke(Native Method)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at libcore.io.Posix.open(Native Method)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at java.io.File.createNewFile(File.java:932)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: ... 13 more
我该如何解决这个问题?我没有抓住我想念的东西....
请帮忙。
已更新
替换 storagePath
以访问分区存储,对于 Android 10。
有关详细信息,请参阅此 document。
谢谢,laalto。
我不知道运行时权限。
我这样解决了异常:
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Request user permissions in runtime */
ActivityCompat.requestPermissions(MainActivity.this,
new String[] {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},
100);
/* Request user permissions in runtime */
createTestFile();
}
@TargetApi(23)
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 100:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
// User checks permission.
} else {
Toast.makeText(MainActivity.this, "Permission is denied.", Toast.LENGTH_SHORT).show();
finish();
}
}
}
private void createTestFile() {
// String storagePath = Environment.getExternalStorageDirectory().getAbsolutePath();
// If Target API level is 29(Android 10),
// you should access local path in scoped storage mode.
File localStorage = getExternalFilesDir(null);
if (localStorage == null) { return; }
String storagePath = localStorage.getAbsolutePath();
String rootPath = storagePath + "/test";
String fileName = "/test.zip";
File root = new File(rootPath);
if(!root.mkdirs()) {
Log.i("Test", "This path is already exist: " + root.getAbsolutePath());
}
File file = new File(rootPath + fileName);
try {
int permissionCheck = ContextCompat.checkSelfPermission(
MainActivity.this,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
if (!file.createNewFile()) {
Log.i("Test", "This file is already exist: " + file.getAbsolutePath());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
有效!
我遇到了同样的问题。我在 file.createNewFile 上遇到了 IOException。仔细查看异常会发现它是由 "permissions denied" 引起的。我正在写我的 getFilesDir,所以我不需要 android 清单中的一个来完成这个任务。我当然为外部存储添加了读和写权限,当然,这并没有解决问题。
我一直在使用带有 sdk 26 的 NEXUS 6 模拟器测试代码。在不更改任何代码的情况下,我尝试使用带有 sdk 26 的 PIXEL C 模拟器进行测试,但问题没有发生。所以我的 Nexus 6 模拟器似乎有问题。
我怀疑这并不总是一个问题,而且这个模拟器实例已损坏,但我尚未验证。我确实花时间查看了目录的 linux 文件权限,我正在将文件创建到它报告的 "drwxrwxrwx" 中,这是正确的。我将补充一点,我已经实现了一个 FileProvider,其中包含我尝试在其中创建新文件的目录的路径。我使用的代码与 Kae10 显示的代码非常相似。
我将问题追溯到 UnixFileSystem 中的这段代码:
public boolean createFileExclusively(String path) throws IOException {
BlockGuard.getThreadPolicy().onWriteToDisk();
return createFileExclusively0(path);
}
异常是从 createFileExlussively0 抛出的,我无法对其进行调试。我没有进一步调查这个问题(即 1.)删除 avd 实例并重新创建它会有所帮助,我的猜测是可能,2.)是否有我应该使用的更高版本的系统映像?)
我在 Android M 中创建文件时遇到问题。
我使用 Nexus 9 和 Android 6.0.1。然后我在我的项目中设置如下:
AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
build.gradle
android {
defaultConfig {
targetSdkVersion 23
...
}
}
MainActivity.Java
public class MainActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String storagePath = Environment.getExternalStorageDirectory().getAbsolutePath();
String rootPath = storagePath + "/test";
String fileName = "/test.zip";
File root = new File(rootPath);
if(!root.mkdirs()) {
Log.i("Test", "This path is already exist: " + root.getAbsolutePath());
}
File file = new File(rootPath + fileName);
try {
if (!file.createNewFile()) {
Log.i("Test", "This file is already exist: " + file.getAbsolutePath());
}
} catch (Exception e) {
e.printStackTrace();
}
}
构建成功并启动了应用程序,但我收到如下异常消息:
IO异常
01-07 18:13:40.669 18027-18027/com.sample.myapplication W/System.err: java.io.IOException: open failed: ENOENT (No such file or directory)
01-07 18:13:40.669 18027-18027/com.sample.myapplication W/System.err: at java.io.File.createNewFile(File.java:939)
01-07 18:13:40.669 18027-18027/com.sample.myapplication W/System.err: at com.sample.myapplication.MainActivity.onCreate(MainActivity.java:36)
01-07 18:13:40.670 18027-18027/com.sample.myapplication W/System.err: at android.app.Activity.performCreate(Activity.java:6251)
01-07 18:13:40.670 18027-18027/com.sample.myapplication W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
01-07 18:13:40.670 18027-18027/com.sample.myapplication W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
01-07 18:13:40.670 18027-18027/com.sample.myapplication W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
01-07 18:13:40.670 18027-18027/com.sample.myapplication W/System.err: at android.app.ActivityThread.-wrap11(ActivityThread.java)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at android.os.Looper.loop(Looper.java:148)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5417)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at java.lang.reflect.Method.invoke(Native Method)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at libcore.io.Posix.open(Native Method)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: at java.io.File.createNewFile(File.java:932)
01-07 18:13:40.671 18027-18027/com.sample.myapplication W/System.err: ... 13 more
我该如何解决这个问题?我没有抓住我想念的东西....
请帮忙。
已更新
替换 storagePath
以访问分区存储,对于 Android 10。
有关详细信息,请参阅此 document。
谢谢,laalto。
我不知道运行时权限。
我这样解决了异常:
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Request user permissions in runtime */
ActivityCompat.requestPermissions(MainActivity.this,
new String[] {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},
100);
/* Request user permissions in runtime */
createTestFile();
}
@TargetApi(23)
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 100:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
// User checks permission.
} else {
Toast.makeText(MainActivity.this, "Permission is denied.", Toast.LENGTH_SHORT).show();
finish();
}
}
}
private void createTestFile() {
// String storagePath = Environment.getExternalStorageDirectory().getAbsolutePath();
// If Target API level is 29(Android 10),
// you should access local path in scoped storage mode.
File localStorage = getExternalFilesDir(null);
if (localStorage == null) { return; }
String storagePath = localStorage.getAbsolutePath();
String rootPath = storagePath + "/test";
String fileName = "/test.zip";
File root = new File(rootPath);
if(!root.mkdirs()) {
Log.i("Test", "This path is already exist: " + root.getAbsolutePath());
}
File file = new File(rootPath + fileName);
try {
int permissionCheck = ContextCompat.checkSelfPermission(
MainActivity.this,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
if (!file.createNewFile()) {
Log.i("Test", "This file is already exist: " + file.getAbsolutePath());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
有效!
我遇到了同样的问题。我在 file.createNewFile 上遇到了 IOException。仔细查看异常会发现它是由 "permissions denied" 引起的。我正在写我的 getFilesDir,所以我不需要 android 清单中的一个来完成这个任务。我当然为外部存储添加了读和写权限,当然,这并没有解决问题。
我一直在使用带有 sdk 26 的 NEXUS 6 模拟器测试代码。在不更改任何代码的情况下,我尝试使用带有 sdk 26 的 PIXEL C 模拟器进行测试,但问题没有发生。所以我的 Nexus 6 模拟器似乎有问题。
我怀疑这并不总是一个问题,而且这个模拟器实例已损坏,但我尚未验证。我确实花时间查看了目录的 linux 文件权限,我正在将文件创建到它报告的 "drwxrwxrwx" 中,这是正确的。我将补充一点,我已经实现了一个 FileProvider,其中包含我尝试在其中创建新文件的目录的路径。我使用的代码与 Kae10 显示的代码非常相似。
我将问题追溯到 UnixFileSystem 中的这段代码:
public boolean createFileExclusively(String path) throws IOException {
BlockGuard.getThreadPolicy().onWriteToDisk();
return createFileExclusively0(path);
}
异常是从 createFileExlussively0 抛出的,我无法对其进行调试。我没有进一步调查这个问题(即 1.)删除 avd 实例并重新创建它会有所帮助,我的猜测是可能,2.)是否有我应该使用的更高版本的系统映像?)