2

In Android P or less, We have used the below code for android P assets extracting path,

public String getAppAssetsExtractingPath() {
    return Environment.getExternalStorageDirectory()+"/" + _activity.getPackageName();
}

Here, added the package name for wrap(group) the files into single package.

In Android Q, To improve user privacy, direct access to shared/external storage devices is deprecated. When an app targets Build.VERSION_CODES.Q, the path returned from this method is no longer directly accessible to apps. Apps can continue to access content stored on shared/external storage by migrating to alternatives such as Context#getExternalFilesDir(String), MediaStore, or Intent#ACTION_OPEN_DOCUMENT.

public String getAppAssetsExtractingPath() {
    Context context = _activity.getApplicationContext();
    return context.getExternalFilesDir(null) +"/" + _activity.getPackageName();
}

But we have faced the ENOENT error while append the package name after that tried the below code its working fine

public String getAppAssetsExtractingPath() {
    return context.getExternalFilesDir(null) + "";
}

My doubt is why ENOENT error was thrown while write the file into getExternalFilesDir() sub directory path in Android Q?

If the path is not related to the getExternalFilesDir(null) then ENOENT is valid

Sample Code:

  try {
  assetsList = xAssetMgr.list(xFromDirectory);
  for (String assetName : assetsList) {
    String assetFullName = new File(xFromDirectory, assetName).toString();
    if (!assetName.startsWith("images") && !assetName.startsWith("sounds") && !assetName.startsWith("webkit")) {
      boolean isDirectory = 0 != xAssetMgr.list(assetFullName).length;
      if (isDirectory) {
        Log.v(_gDebugTag, "Asset " + assetFullName + " is directory");
        File outDir = new File(xToDirectory, assetFullName);
        outDir.mkdirs();
        copyAssetsDirectory(xAssetMgr, assetFullName, xToDirectory);
        outDir = null;
      } // if
      else {
        // asset is a file
        Log.v(_gDebugTag, "Asset " + assetFullName + " is file");
        InputStream inStream = xAssetMgr.open(assetFullName);
        File outFile = new File(xToDirectory, assetFullName);
        FileOutputStream outStream = new FileOutputStream(outFile);
        Log.i(_gDebugTag, "Copying " + outFile);
        copyAsset(inStream, outStream);
        inStream.close();
        outStream.close();
        outStream = null;
        outFile = null;
      } // else if
    }
    else
    {
      Log.v(_gDebugTag, "Skip Android entry " + assetName);
    } // else
    assetFullName = null;
  } // for
} catch (IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
}

Sample Log file: *

07-19 15:10:01.800 18275 18300 V GLUE : Call copyAssetsDirectory from to /storage/emulated/0/Android/data/com.mp.test/files/com.mp.test 07-19 15:10:01.804 18275 18300 W System.err: java.io.FileNotFoundException: /storage/emulated/0/Android/data/com.mp.test/files/com.mp.test/0.key: open failed: ENOENT (No such file or directory) 07-19 15:10:01.804 18275 18300 W System.err: at libcore.io.IoBridge.open(IoBridge.java:496) 07-19 15:10:01.804 18275 18300 W System.err: at java.io.FileOutputStream.(FileOutputStream.java:235) 07-19 15:10:01.804 18275 18300 W System.err: at java.io.FileOutputStream.(FileOutputStream.java:186) 07-19 15:10:01.804 18275 18300 W System.err: at com.mp.test.TestCorePak.copyAssetsDirectory(TestCorePak.java:94) 07-19 15:10:01.804 18275 18300 W System.err: at com.nagra.CppUnitForAndroid.TestWrapper.start(TestWrapper.java:96) 07-19 15:10:01.804 18275 18300 W System.err: at com.nagra.CppUnitForAndroid.TestWrapper.access$200(TestWrapper.java:58) 07-19 15:10:01.804 18275 18300 W System.err: at com.nagra.CppUnitForAndroid.TestWrapper$WrapperThread.run(TestWrapper.java:443) 07-19 15:10:01.804 18275 18300 W System.err: Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory) 07-19 15:10:01.804 18275 18300 W System.err: at libcore.io.Linux.open(Native Method) 07-19 15:10:01.804 18275 18300 W System.err: at libcore.io.ForwardingOs.open(ForwardingOs.java:167) 07-19 15:10:01.804 18275 18300 W System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:252) 07-19 15:10:01.804 18275 18300 W System.err: at libcore.io.ForwardingOs.open(ForwardingOs.java:167) 07-19 15:10:01.804 18275 18300 W System.err: at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7242) 07-19 15:10:01.805 18275 18300 W System.err: at libcore.io.IoBridge.open(IoBridge.java:482) 07-19 15:10:01.805 18275 18300 W System.err: ... 6 more

*

VMS
  • 137
  • 2
  • 8
  • You might want to post the entire stack trace, along with the code showing where you are creating the directory and how you are writing to a file in it. Also note that you do not need `_activity.getApplicationContext()` to call `getExternalFilesDir()` -- you can just call that on `_activity` itself. And, please do not use concatenation to assemble a filesystem path. Replace `context.getExternalFilesDir(null) +"/" + _activity.getPackageName()` with `new File(_activity.getExternalFilesDir(null), _activity.getPackageName())`. – CommonsWare Jul 19 '19 at 13:41
  • I have paste the sample code and sample log for your reference. In Android Q once create the directory before copy the content its work fine. But Android P without directory creation its works – VMS Jul 22 '19 at 10:03
  • Please comment, i'm eagerly waiting for your reply – VMS Jul 29 '19 at 07:07
  • It is unclear how the code marked "Sample Code" relates to the other code snippets. You might want to add `outFile.getParentFile().mkdirs()` before `FileOutputStream outStream = new FileOutputStream(outFile)`. – CommonsWare Jul 29 '19 at 11:03
  • Refer to [this](https://stackoverflow.com/a/61721373/7366265) answer. It worked for me. – Mohd Zaid May 11 '20 at 02:30

0 Answers0