javafxgluongluon-mobilegluonfx

How to use the Storage Attach Service for public storage access instead of private storage access?


Problem Summary

My app (in development), when run on the desktop, can both:

However, when run on Android, only private storage is accessible.

How To Replicate The Issue

Instead of sharing excerpts of my project's codebase, let me refer to another codebase we share and have - the gluon-connect-file-provider project in Gluon Samples. The sample apps only demonstrate private storage usage. None demonstrate public storage usage, so in the gluon-connect-file-provider project, you can make the following change in com.gluonhq.samples.connect.file.Main.java:

Before

static {
    ROOT_DIR = Services.get(StorageService.class)
                .flatMap(StorageService:getPrivateStorage)
                .orElseThrow(() -> new RuntimeException("Error retrieving private storage"));
}

After

static {
    ROOT_DIR = Services.get(StorageService.class)
                .flatMap(s -> s.getPublicStorage("Gluon"))
                .orElseThrow(() -> new RuntimeException("Error retrieving public storage"));
    ROOT_DIR.mkdir();
}

When starting the app on the Desktop after this change, you can first observe the directory ~/Gluon being created on your machine. Then, as you toggle the checkbox on/off in the app's Object Viewer screen, you can also confirm the underlying JSON file ~/Gluon/user.json is being updated. So, therefore, we can agree public storage works.

However, when deployed to Android, we can see file-permission related failures in the scrolling terminal during mvn -Pandroid gluonfx:nativerun. First, the Gluon directory fails to be created at startup and, consequently later, attempts to write the user.json file occur.

I thought the soluton was to define in the project the file src/android/AndroidManifest.xml. The default found at target/gluonfx/aarch64-android/gensrc/android/AndroidManifest.xml does not include the following permissions:

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

So, I copied the generated AndroidManifest.xml file to src/android, including these entries to it. Even though the Android Settings shows me my app has Storage Permission, this still didn't resolve the problem.

Note - when preparing this post asking for your help, I noticed that, without also provisioning src/android/AndroidManifest.xml file with EXTERNAL READ/WRITE permissions for the gluon-connect-file-provider, the Android device already showed the deployed app had Storage Permission enabled.

I used two different Android devices to test with.

  1. Pixel XL running Android version 10.
  2. Samsung S9 running Android version 10.

I tested with the latest GluonHQ Attach dependency 4.0.13 and also with the oldest I found available, 4.0.7.

Is there something more that must be done for the Storage Attach Service to allow public storage access on Android? Please tell me how else to modify the gluon-connect-file-provider app to make it so, thank you.


Solution

  • Resolution

    Update to Gluon Attach 4.0.14.

    <dependency>
        <groupId>com.gluonhq.attach</groupId>
        <artifactId>storage</artifactId>
        <version>4.0.14</version>
    </dependency>
    

    With this update, Storage Service will allow you to access pre-existing Android folders, like "Documents" for example. Or, as seen in this post's code excerpt above, you can define your own new directory like "Gluon", or naming the folder after your own App.

    Extra

    Another cascading result of this Attach update is, in addition to Storage Service, file sharing via the Share Service is now available on Android. Its JavaDoc states Storage Service as a requirement to use Share Service. Below is a quote from its documentation:

    Note that on Android, the file has to be located in a public folder (see StorageService#getPublicStorage), or sharing it won't be allowed.