我得到了

open failed: EACCES(权限被拒绝)

myOutput = new FileOutputStream(outFileName);

我检查了根目录,并尝试了android.permission.WRITE_EXTERNAL_STORAGE。

我该如何解决这个问题?

try {
    InputStream myInput;

    myInput = getAssets().open("XXX.db");

    // Path to the just created empty db
    String outFileName = "/data/data/XX/databases/"
            + "XXX.db";

    // Open the empty db as the output stream
    OutputStream myOutput = new FileOutputStream(outFileName);

    // Transfer bytes from the inputfile to the outputfile
    byte[] buffer = new byte[1024];
    int length;
    while ((length = myInput.read(buffer)) > 0) {
        myOutput.write(buffer, 0, length);
    }

    // Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();
    buffer = null;
    outFileName = null;
}
catch (IOException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

当前回答

在我的例子中,错误出现在行上

      target.createNewFile();

因为我不能在sd卡上创建一个新文件,所以我不得不使用DocumentFile方法。

      documentFile.createFile(mime, target.getName());

对于上述问题,可以用这种方法来解决,

    fos=context.getContentResolver().openOutputStream(documentFile.getUri());

看看这个帖子, 如何使用新的SD卡访问API为Android 5.0(棒棒糖)?

其他回答

除了所有的答案,确保你没有把你的手机用作USB存储器。

我在启用USB存储模式的HTC Sensation上也遇到了同样的问题。我仍然可以调试/运行应用程序,但我不能保存到外部存储。

添加gradle依赖项

implementation 'com.karumi:dexter:4.2.0'

在主活动中添加以下代码。

import com.karumi.dexter.Dexter;
import com.karumi.dexter.MultiplePermissionsReport;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.multi.MultiplePermissionsListener;
    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);

    new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {


                checkMermission();
            }
        }, 4000);
    }

    private void checkMermission(){
        Dexter.withActivity(this)
                .withPermissions(
                        android.Manifest.permission.READ_EXTERNAL_STORAGE,
                        android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        android.Manifest.permission.ACCESS_NETWORK_STATE,
                        Manifest.permission.INTERNET
                ).withListener(new MultiplePermissionsListener() {
            @Override
            public void onPermissionsChecked(MultiplePermissionsReport report) {
                if (report.isAnyPermissionPermanentlyDenied()){
                    checkMermission();
                } else if (report.areAllPermissionsGranted()){
                    // copy some things
                } else {
                    checkMermission();
                }

            }
            @Override
            public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
                token.continuePermissionRequest();
            }
        }).check();
    }

我有同样的问题(API >= 23)。

解决方案https://stackoverflow.com/a/13569364/1729501对我有用,但断开应用程序进行调试是不实际的。

我的解决方案是在Windows上安装合适的adb设备驱动程序。谷歌USB驱动程序不适用于我的设备。

步骤1:下载适合您的设备品牌的adb驱动程序。

步骤2:进入设备管理器->其他设备->查找带有“adb”字样的条目->选择更新驱动程序->在步骤1中给出位置

将文件存储在与应用程序目录无关的目录中受API 29+以上限制。因此,要生成一个新文件或创建一个新文件,使用你的应用程序目录,就像这样

所以正确的做法是:-

val file = File(appContext.applicationInfo.dataDir + File.separator + "anyRandomFileName/")

您可以将任何数据写入这个生成的文件!

上面的文件是可访问的,不会抛出任何异常,因为它位于您自己开发的应用程序的目录中。

另一个选项是android:requestLegacyExternalStorage="true"在清单应用程序标签,由Uriel建议,但它不是一个永久的解决方案!

在我的例子中,我使用的是一个文件选择器库,它返回到外部存储的路径,但它从/root/开始。即使在运行时授予WRITE_EXTERNAL_STORAGE权限,我仍然得到错误EACCES(权限被拒绝)。 因此,使用Environment.getExternalStorageDirectory()来获取外部存储的正确路径。

例子: 无法写入:/root/storage/emulated/0/newfile.txt 可以写:/storage/emulated/0/newfile.txt

boolean externalStorageWritable = isExternalStorageWritable();
File file = new File(filePath);
boolean canWrite = file.canWrite();
boolean isFile = file.isFile();
long usableSpace = file.getUsableSpace();

Log.d(TAG, "externalStorageWritable: " + externalStorageWritable);
Log.d(TAG, "filePath: " + filePath);
Log.d(TAG, "canWrite: " + canWrite);
Log.d(TAG, "isFile: " + isFile);
Log.d(TAG, "usableSpace: " + usableSpace);

/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}

输出1:

externalStorageWritable: true
filePath: /root/storage/emulated/0/newfile.txt
isFile: false
usableSpace: 0

输出2:

externalStorageWritable: true
filePath: /storage/emulated/0/newfile.txt
isFile: true
usableSpace: 1331007488