How do i enable multiDex for classes so they can be included or traced on the DexPathList?
I am using graalvm (with native-image) and gluonfx nativePackage task to generate the apk.
id 'com.gluonhq.gluonfx-gradle-plugin' version '1.0.3' //build.gradle
but when I try to access an SMS BroadcastReceiver, I get Class not found in the DexPathList ...
this is the androidManifest setup ..
<application ... package="demo" ...>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<receiver android:name=".services.SmsListener"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
</application>
and the error i get when an sms drops on the phone is as below .. Unable to instantiate receiver demo.services.SmsListener: java.lang.ClassNotFoundException: Didn't find class "demo.services.SmsListener" on path: DexPathList[[zip file "/data/app/.../base.apk"],nativeLibraryDirectories=[/data/app/...-g==/lib/arm64, /data/app/..g==/base.apk!/lib/arm64-v8a, /system/lib64, /system_ext/lib64]]
So how go I pass MultiDexEnabled True to android task? or Is there a way i can start this broadcast class through java code? project structure
The initial question is about adding Java code to the Android sources, before packaging the project into the final APK.
Since there is no automatic procedure from the gluonfx plugin yet, it is a manual process:
Run mvn -Pandroid gluonfx:build gluonfx:package
once, that will create the Android project under target/gluonfx/aarch64-android/gvm/android_project
.
Add the Java/Android sources to target/gluonfx/aarch64-android/gvm/android_project/app/src/main/java
Build manually the APK:
cd target/gluonfx/aarch64-android/gvm/android_project/
export ANDROID_SDK_ROOT=~/.gluon/substrate/Android
./gradlew app:assembleDebug
Continue the process: mvn -Pandroid gluonfx:install gluonfx:run
While this allows modifying the Android part, the main caveat is the lack of communication from this side to the Java/JavaFX/GraalVM part, so it will only work in case it is an isolated modification on the Android side.
In order to modify the Android part and also get access to the Java/JavaFX side, the best approach is to create an Attach service.
For this, one option is to clone Attach, add the new service, and publish/distribute this modified version of Attach, but better is to create just a custom Attach service outside of Attach.
This experimental repository contains a new service: LogService
, just as proof of concept.
The readme already contains instructions on how to get started and use this service.
To summarise:
./gradlew clean publishToMavenLocal
.~/.m2/repository/org/jpereda/attach/log/4.0.12-SNAPSHOT
: log-4.0.12-SNAPSHOT-android.jar
log-4.0.12-SNAPSHOT-ios.jar
log-4.0.12-SNAPSHOT-desktop.jar
log-4.0.12-SNAPSHOT.jar
Add the dependency to the pom. Note that the official Attach dependencies remain the same, but you will need 4.0.12-SNAPSHOT.
<dependencies>
<dependency>
<groupId>com.gluonhq.attach</groupId>
<artifactId>storage</artifactId>
<version>4.0.12-SNAPSHOT</version>
</dependency>
...
<dependency>
<groupId>org.jpereda.attach</groupId>
<artifactId>log</artifactId>
<version>4.0.12-SNAPSHOT</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
</repositories>
Notice that since it is not an official Attach service, it can't use the package name com.gluonhq.attach
, and it can't be added to the attachList
. Therefore, it is treated as a regular dependency, and you need to add the platform dependency based on the target:
For instance, for Android:
<profile>
<id>android</id>
<properties>
<gluonfx.target>android</gluonfx.target>
</properties>
<dependencies>
<dependency>
<groupId>org.jpereda.attach</groupId>
<artifactId>log</artifactId>
<version>4.0.12-SNAPSHOT</version>
<classifier>android</classifier>
<scope>runtime</scope>
</dependency>
</dependencies>
</profile>
From your code, call the service as usual:
LogService.create().ifPresent(service -> service.log("This is a message"));
For instance, on Android:
mvn -Pandroid gluonfx:build gluonfx:package gluonfx:install gluonfx:nativerun
First of all, read https://docs.gluonhq.com/#_device_interface for a better understanding of an Attach service.
Following the LogService
project it should be more or less straightforward to create your own service.
The more complex part is in the communication between Java(11+)/JavaFX/GraalVM and Java(7)/Android, where JNI is required. The Java side is AOT compiled and goes into lib${service}.a
and the Android side goes to the Android project and distributed as ${service}>.aar
, without JavaFX support.