1

My Android Expansion File Downloder is not working. I found out, that the problem occurs in the original DownloadThread.java I have verified that that external media is mounted.

The passed data is correct: byte[] data contains bytesRead = 4096 Bytes. These are checked and were correctly read from the expected obb file. Also state.filename is absolutely correct. state.mStream = null, therefore a FileOutputStream must be opened first.

new FileOutputStream(state.mFilename, true) produces an IOException

private void writeDataToDestination(State state, byte[] data, int bytesRead)
        throws StopRequest {
    for (;;) {
        try {
            if (state.mStream == null) {
                state.mStream = new FileOutputStream(state.mFilename, true);
            }
            state.mStream.write(data, 0, bytesRead);
            // we close after every write --- this may be too inefficient
            closeDestination(state);
            return;
        } catch (IOException ex) {
            if (!Helpers.isExternalMediaMounted()) {
                throw new StopRequest(DownloaderService.STATUS_DEVICE_NOT_FOUND_ERROR,
                        "external media not mounted while writing destination file");
            }

The WRITE_EXTERNAL_STORAGE permission should be given: AndroidManifest.xml:

...
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="18" />

...
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name_short"
        android:supportsRtl="true"
        android:requestLegacyExternalStorage="true"
        android:preserveLegacyExternalStorage="true"
        android:theme="@style/AppTheme">
...

And my build.gradle:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.2"
    useLibrary 'org.apache.http.legacy'

    signingConfigs {
        Signed {
            keyAlias ...
            keyPassword ...
            storeFile file(...)
            storePassword ...
        }
    }

    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 30
        ndk {
            debugSymbolLevel 'FULL'
        }
    }
...

I'm totally stuck and can't continue. What can I do?

thpitsch
  • 2,016
  • 2
  • 21
  • 27

2 Answers2

0

you should requested permission

 private void checkWriteStoragePermission()
{
    ArrayList<String> permissions = new ArrayList<>();
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
    {
        permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
    {
        permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
    }

    if (permissions.size() > 0)
    {
        ActivityCompat.requestPermissions(this, permissions.toArray(new String[permissions.size()]), Constants.WRITE_EXTERNAL_STORAGE());
    }
    
}

and use REQUEST_INSTALL_PACKAGES permission it can access Android/obb directory.

Pouria Hemi
  • 706
  • 5
  • 15
  • 30
  • The last line causes me problems. Constants.WRITE_EXTERNAL_STORAGE() should return a number, but which? My constants do not have this Number. – thpitsch Jul 10 '21 at 13:02
  • You can just create either a public or private variable and set it to an integer value. It doesn't matter which value you use it as long as it's not the same as the ones you use for other permissions. This value will be used for `onRequestPermissionsResult()` to determine which permissions are granted or not. – David Lee Jul 10 '21 at 18:46
  • I have done this, but it does not solve my problem. In the meantime, I know a little more about the actual problem. If the directory /storage/emulated/0/Android/obb/[PackageName]. exists, then the obb files are also written in it. So the problem does not occur. But if it doesn't exist, then the IOException occurs. So it means that the directory cannot be created. But my attempts to create the directory myself failed because I don't have permission with targetSdkVersion 30 to create a directory here. – thpitsch Jul 11 '21 at 03:48
  • Since the code provided by Google for the ExpansionFileDownoader does not work with targetSdkVersion 30, I have to create the [PackageName] directory myself under /storage/emulated/0/Android/obb/. How do I do that and how do I get permission to do that? – thpitsch Jul 11 '21 at 04:11
  • Exactly, you can not create a file in /storage/emulated/0/Android/obb folder in Android 11 I have not found a solution myself at the moment – Pouria Hemi Jul 11 '21 at 04:29
  • In Android 11 you are only allowed to write and read information in 'obj - media' folders – Pouria Hemi Jul 11 '21 at 04:33
  • but you can use REQUEST_INSTALL_PACKAGES permission it can access Android/obb directory. – Pouria Hemi Jul 11 '21 at 04:35
  • [use this for more information](https://stackoverflow.com/questions/60360368/android-11-r-file-path-access) – Pouria Hemi Jul 11 '21 at 04:42
  • I can't tell the user to change their settings first and grant more permissions before installing my app. This worked fine until targetSdkVersion 28. The problem is that Google does not provide an updated version of the downloader or instructions on how to patch it. – thpitsch Jul 11 '21 at 05:46
  • You can use a splash page at the beginning of the program to get all the necessary access – Pouria Hemi Jul 11 '21 at 06:22
0

G-o-o-g-l-e, if you yourself can't save the obb files to the obb directory, then I don't need to. I have now found another directory for it that can be written to by my app.

thpitsch
  • 2,016
  • 2
  • 21
  • 27