java.io.FileNotFoundException:/sdcard/testwrite.txt:打开失败:EACCES(权限被拒绝)
java.io.FileNotFoundException: /sdcard/testwrite.txt: open failed: EACCES (Permission denied)
请帮忙。
我正在开发 Android 应用程序。
问题来了。
我无法在 /sdcard 写入文件。
怎么了?
开发工具:Android studio 3.5.2
设备:AVD Pixel 2 API29
我编码了Permission Request
。
我可以用旧的 android 设备写一个文件。
为什么我不能用这个设备写字?
请帮忙。
错误日志
E: Unknown bits set in runtime_flags: 0x8000
E: --> WRITE_EXTERNAL_STORAGE=true
E: --> READ_EXTERNAL_STORAGE=true
E: ====================================================================
E: --> TEST: Writing.. /sdcard/testwrite.txt
E: --> Writing..
E: --> Error..
E: java.io.FileNotFoundException: /sdcard/testwrite.txt: open failed: EACCES (Permission denied)
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myapp.TestWrite">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
package com.myapp.TestWrite;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.util.Log;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate( Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
Log.wtf( "TAG", "--> WRITE_EXTERNAL_STORAGE=" + hasPermission( Manifest.permission.WRITE_EXTERNAL_STORAGE ) );
Log.wtf( "TAG", "--> READ_EXTERNAL_STORAGE=" + hasPermission( Manifest.permission.READ_EXTERNAL_STORAGE ) );
if( Build.VERSION.SDK_INT >= 23 )
if( hasPermission( Manifest.permission.WRITE_EXTERNAL_STORAGE ) )
if( hasPermission( Manifest.permission.READ_EXTERNAL_STORAGE ) ) {
writeTest( "/sdcard/testwrite.txt" );
return;
}
Log.wtf( "TAG", "--> Request permission\n" );
ActivityCompat.requestPermissions(
this,
new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
},
1
);
}
void writeTest( String fn ) {
Log.wtf( "TAG", "====================================================================" );
Log.wtf( "TAG", "--> TEST: Writing.. " + fn );
File file = new File( fn );
try {
Log.wtf( "TAG", "--> Writing.." );;
FileWriter fw = new FileWriter(file, false);
fw.write( "Test Doc !!!!!" );
fw.close();
Log.wtf( "TAG", "--> Success.." );
} catch( IOException e) {
e.printStackTrace();
Log.wtf( "TAG", "--> Error.." );
Log.wtf( "TAG", e.toString() );
}
}
public boolean hasPermission( String strPerm ) {
if ( ContextCompat.checkSelfPermission( this, strPerm ) == PackageManager.PERMISSION_GRANTED )
return true;
return false;
}
@Override
public void onRequestPermissionsResult( int requestCode, String[] permissions, int[] grantResults ) {
Log.wtf( "TAG", ":onRequestPermissionsResult\n" );
switch ( requestCode ) {
case 1:
{
// If request is cancelled, the result arrays are empty.
if ( grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED ) {
Log.wtf( "TAG", "--> Permission granted.\n" );
finish();
startActivity( getIntent() );
}
else {
Log.wtf( "TAG", "--> Permission denied. Quitting.\n" );
finish();
}
}
}
}
}
您 运行 您的应用在 Android 10 中,但清单中没有包含旧版支持属性。按照以下建议编辑您的清单:
<manifest ... >
<!-- This attribute is "false" by default on apps targeting
Android 10 or higher. -->
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
(source)
请注意,这只是一个临时修复,因为随着下一个 android 版本的发布,这将默认为 false。如果这些文件对您的应用程序是私有的,请考虑使用 getExternalFilesDir()
动态获取路径。在 developers' website.
中阅读有关范围存储更改的更多信息
您应该先尝试在设备中创建文件并检查 pwd
的路径。
它可能不会 /sdcard/testwrite.txt
.
使用以下代码之一如何?
/** internal: start with /data/user/0/{applicationId}/ */
String cacheDirPath = mStorageManager.getCachedDir().getPath();
String filesDirPath = mStorageManager.getFileDir().getAbsolutePath();
String dirNamePath = mStorageManager.getDir("dirname").getPath();
String codeCacheDirPath = mStorageManager.getCodeCacheDir().getPath();
String noBackupFilesDir = mStorageManager.getNoBackupFilesDir().getPath();
/** external start with /storage/emulated/0/Android/data/ */
String externalCacheDirPath = mStorageManager.getExternalCacheDir().getPath();
String externalFilesDirPath = mStorageManager.getExternalFilesDir().getPath();
/** obb start with /storage/emulated/0/Android/obb/ */
String obbDirPath = mStorageManager.getObbDir().getPath();
请帮忙。
我正在开发 Android 应用程序。
问题来了。 我无法在 /sdcard 写入文件。 怎么了?
开发工具:Android studio 3.5.2
设备:AVD Pixel 2 API29
我编码了Permission Request
。
我可以用旧的 android 设备写一个文件。
为什么我不能用这个设备写字?
请帮忙。
错误日志
E: Unknown bits set in runtime_flags: 0x8000
E: --> WRITE_EXTERNAL_STORAGE=true
E: --> READ_EXTERNAL_STORAGE=true
E: ====================================================================
E: --> TEST: Writing.. /sdcard/testwrite.txt
E: --> Writing..
E: --> Error..
E: java.io.FileNotFoundException: /sdcard/testwrite.txt: open failed: EACCES (Permission denied)
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myapp.TestWrite">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
package com.myapp.TestWrite;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.util.Log;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate( Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
Log.wtf( "TAG", "--> WRITE_EXTERNAL_STORAGE=" + hasPermission( Manifest.permission.WRITE_EXTERNAL_STORAGE ) );
Log.wtf( "TAG", "--> READ_EXTERNAL_STORAGE=" + hasPermission( Manifest.permission.READ_EXTERNAL_STORAGE ) );
if( Build.VERSION.SDK_INT >= 23 )
if( hasPermission( Manifest.permission.WRITE_EXTERNAL_STORAGE ) )
if( hasPermission( Manifest.permission.READ_EXTERNAL_STORAGE ) ) {
writeTest( "/sdcard/testwrite.txt" );
return;
}
Log.wtf( "TAG", "--> Request permission\n" );
ActivityCompat.requestPermissions(
this,
new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
},
1
);
}
void writeTest( String fn ) {
Log.wtf( "TAG", "====================================================================" );
Log.wtf( "TAG", "--> TEST: Writing.. " + fn );
File file = new File( fn );
try {
Log.wtf( "TAG", "--> Writing.." );;
FileWriter fw = new FileWriter(file, false);
fw.write( "Test Doc !!!!!" );
fw.close();
Log.wtf( "TAG", "--> Success.." );
} catch( IOException e) {
e.printStackTrace();
Log.wtf( "TAG", "--> Error.." );
Log.wtf( "TAG", e.toString() );
}
}
public boolean hasPermission( String strPerm ) {
if ( ContextCompat.checkSelfPermission( this, strPerm ) == PackageManager.PERMISSION_GRANTED )
return true;
return false;
}
@Override
public void onRequestPermissionsResult( int requestCode, String[] permissions, int[] grantResults ) {
Log.wtf( "TAG", ":onRequestPermissionsResult\n" );
switch ( requestCode ) {
case 1:
{
// If request is cancelled, the result arrays are empty.
if ( grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED ) {
Log.wtf( "TAG", "--> Permission granted.\n" );
finish();
startActivity( getIntent() );
}
else {
Log.wtf( "TAG", "--> Permission denied. Quitting.\n" );
finish();
}
}
}
}
}
您 运行 您的应用在 Android 10 中,但清单中没有包含旧版支持属性。按照以下建议编辑您的清单:
<manifest ... >
<!-- This attribute is "false" by default on apps targeting
Android 10 or higher. -->
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
(source)
请注意,这只是一个临时修复,因为随着下一个 android 版本的发布,这将默认为 false。如果这些文件对您的应用程序是私有的,请考虑使用 getExternalFilesDir()
动态获取路径。在 developers' website.
您应该先尝试在设备中创建文件并检查 pwd
的路径。
它可能不会 /sdcard/testwrite.txt
.
使用以下代码之一如何?
/** internal: start with /data/user/0/{applicationId}/ */
String cacheDirPath = mStorageManager.getCachedDir().getPath();
String filesDirPath = mStorageManager.getFileDir().getAbsolutePath();
String dirNamePath = mStorageManager.getDir("dirname").getPath();
String codeCacheDirPath = mStorageManager.getCodeCacheDir().getPath();
String noBackupFilesDir = mStorageManager.getNoBackupFilesDir().getPath();
/** external start with /storage/emulated/0/Android/data/ */
String externalCacheDirPath = mStorageManager.getExternalCacheDir().getPath();
String externalFilesDirPath = mStorageManager.getExternalFilesDir().getPath();
/** obb start with /storage/emulated/0/Android/obb/ */
String obbDirPath = mStorageManager.getObbDir().getPath();