3

I am downloading files using DownloadManager to a directory, that isn't apart of my "local packages" directory, i.e. outside /storage/emulated/0/Android/data/myPackageName/, but part of another directory's package, more specifically, obb directory, /storage/emulated/0/Android/obb/otherPackageName/

If I install on "my package's directory", no problem, if I got outside of it, I get a "java.lang.SecurityException: Unsupported path /storage/emulated/0/Android/obb/otherPackageName/fileName.obb"

I have my permissions in the android manifest, WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE, and I check if I have them using ContextCompat.checkSelfPermission and see if it equals PackageManager.PERMISSION_GRANTED, which it does. But if it didn't, and for API level>=23, I use something along the lines of

requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, 
    Manifest.permission.READ_EXTERNAL_STORAGE}, CODE);

And then I use onRequestPermissionsResult() to check the response and see if it is a PackageManager.PERMISSION_GRANTED, so that I may be able to start the download.

Even with this, I am getting the exception. Can this be device specific or API specific? I'll have to test on other devices and API's to know for sure. Am I doing something wrong here? Do I need an extra permission? It has to be possible to write outside the directory?

Also, I am getting the external directory using Environment.getExternalStorageDirectory(), and then I add the subdirectories as a string (works for /storage/emulated/0/Android/data/myPackageName/..., but not for /storage/emulated/0/Android/obb/otherPackageName/...)

Thank you for reading, lemme know if you need any information.

ordep mgb
  • 63
  • 1
  • 7
  • That is all on Android 10? Further you did not show code that uses that path and produces the exception. It is also unclear if you get that exception already at downloading. – blackapps Aug 18 '20 at 10:45
  • @blackapps I've only tested on android 10 so far. I just pass the file with the name similar to the dummy name above to the DownloadManager request, and it throws the exception inside the method .enqueue(request). – ordep mgb Aug 18 '20 at 10:50
  • `works for /storage/emulated/0/Android/data/myPackageName/...` Do not build up that path in that way. Use getExternalFilesDir(() instead. – blackapps Aug 18 '20 at 10:50
  • You cannot use such paths anymore on Android 10. Use getFilesDir(), getExternalFilesDir() and getExternalFilesDirs() only. – blackapps Aug 18 '20 at 10:52
  • If you still want to use that path on android 10 then add legacyExternalStorageDirectory true to manifest file. – blackapps Aug 18 '20 at 10:53
  • That was what I was using before, when I just wanted to use my package's directory, but how should I proceed when I want to use another package's? Do those functions work? – ordep mgb Aug 18 '20 at 11:00
  • It is unclear what you were using before. ANd the rest of you question is vague too. – blackapps Aug 18 '20 at 11:01
  • Think of it as an app installer, and I also want to install obbs. Basically what I was doing was downloading an obb to the directory it's meant to go (outside of what getExternalFilesDir() returns, what is referenced as "scoped storage"). From what you are saying that does not work on android 10, so maybe I need to add what you said to the manifest. – ordep mgb Aug 18 '20 at 11:06
  • Realise that that serves only for Q. With R already here you have to rethink and solve better. – blackapps Aug 18 '20 at 11:08
  • Well, regarding my initial problem. I am still using Environment.getExternalStorageDirectory(), but first I'm storing the downloaded file in the "scoped storage", obtained with getExternalFilesDir(), and then I manually move it to the directory I want. That is currently working. I still have to search more to see if a better solution for Android R – ordep mgb Aug 18 '20 at 11:18
  • If you use SAF you can let the user choose the wanted directory. And if you do the download yourself instead of using downloadmanager you can directly download to that directory. – blackapps Aug 18 '20 at 11:28
  • @blackapps It's not a problem for the download to go straight away to that directory, I can move it after it's downloaded, I just thought it would result on the same exception, but it doesn't. Maybe it's because the DownloadManager is a separate entity? Anywho, thanks for your help. I'll post an answer saying my problem is solved, and I'll edit it once or if I find a better solution. – ordep mgb Aug 18 '20 at 11:32

2 Answers2

2

I was directly storing the file outside my package's directory, and the exception was being thrown inside DownloadManager. So I started storing the file in the "local" directory, then manually moved it to the directory I wanted.

You can see this answer for an example method to move files: https://stackoverflow.com/a/11327789/13416944

Since I'm still using Environment.getExternalFilesDirectory(), and that's not really the best way to do it in these newer API's, I'll hopefully edit this answer once I find a better solution

ordep mgb
  • 63
  • 1
  • 7
  • Hi, I'm with the same problem. Do you find any other method to solve? Thanks – Gilian Jul 13 '21 at 18:07
  • Hi. I'm afraid I didn't find any other method. For [Android R](https://developer.android.com/about/versions/11/privacy/storage#app-specific-external), I don't think it's possible to perform this directly to a directory outside your app's scope. – ordep mgb Jul 28 '21 at 11:20
  • If you want to open files in Android R and above, maybe [this](https://developer.android.com/training/data-storage/shared/documents-files#grant-access-directory). It requires asking permission to the user. There is no such thing as unrestricted(-ish) file accesses in new android versions anymore, which obviously is good from a security point of view; just don't think there is enough documentation on this. – ordep mgb Jul 28 '21 at 11:26
1

I got this error in androids version above 10, But in lower Version everything is fine. For android above 10 i solve this problem by specifying subPath for Download manager and it seems necessary for version 10 and above:

 var request = DownloadManager.Request(uri)
 var filename = "MyApp" + imageId + "_.jpg"
 request.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES,"your-sub-path")

Note that subpath is name of your downloaded file for example : landschaft.jpg

** Do not forget to add runtime Persmission:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
soheil ghanbari
  • 388
  • 1
  • 7