How to choose image from android directory/gallery in javafxmobile-plugin
. I am unable to choose files like images
in android device. when i open directory app hangs and suddenly close. Any help???
I already have tried in android device using javafx file chooser
&& directory choose
but notthing helps. also i found no helpful post on the stackoverflow
my build.gradle
file:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.3.16'
}
}
apply plugin: 'org.javafxports.jfxmobile'
repositories {
jcenter()
maven {
url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
}
}
mainClassName = 'com.maqboolsolutions.directorychooserandroid.App'
ext.CHARM_DOWN_VERSION = "1.0.0"
dependencies {
compile "com.gluonhq:charm-down-common:$CHARM_DOWN_VERSION"
desktopRuntime "com.gluonhq:charm-down-desktop:$CHARM_DOWN_VERSION"
androidRuntime "com.gluonhq:charm-down-android:$CHARM_DOWN_VERSION"
compile 'com.airhacks:afterburner.mfx:1.6.3'
}
jfxmobile {
javafxportsVersion = '8.60.11'
android {
manifest = 'src/android/AndroidManifest.xml'
packagingOptions {
exclude 'META-INF/INDEX.LIST'
}
dexOptions {
javaMaxHeapSize "4g"
}
}
}
.java
codding:
@FXML
private void btnCooserOnAction(ActionEvent event) {
DirectoryChooser directoryChooser = new DirectoryChooser();
Stage primaryStage = (Stage) stackPaneRoot.getScene().getWindow();
File selectedDirectory = directoryChooser.showDialog(primaryStage);
if (selectedDirectory == null) {
lblPath.setText("No Directory selected");
} else {
lblPath.setText(selectedDirectory.getAbsolutePath());
}
}
App not response. and close...
After some digging and based on helpful comments from @josé-pereda, here’s the updated and final answer for anyone revisiting similar issues, even though JavaFX Mobile and Charm Down for JDK 1.8 have been deprecated for years. While GluonFX is the recommended modern replacement (supporting Java 11+ via GraalVM), here’s a solution for those still relying on older setups.
PicturesService
plugin to access the gallery or take photos without needing a paid Gluon Mobile license (which only removes the nag screen in the free version).buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.3.18'
}
}
apply plugin: 'org.javafxports.jfxmobile'
repositories {
jcenter()
maven {
url 'https://nexus.gluonhq.com/nexus/content/repositories/releases'
}
}
mainClassName = 'org.javafxports.hellofx.App'
dependencies {
// compile 'com.gluonhq:charm-down-plugin-pictures-android:3.8.6'
compile 'org.lsposed.hiddenapibypass:hiddenapibypass:4.3'
}
jfxmobile {
downConfig {
version = '3.8.6'
plugins 'display', 'lifecycle', 'statusbar', 'storage', 'pictures'
}
android {
manifest = 'src/android/AndroidManifest.xml'
compileSdkVersion '35'
buildToolsVersion '35.0.0'
dexOptions {
incremental true
javaMaxHeapSize "7g"
}
}
}
project.afterEvaluate {
explodeAarDependencies(project.configurations.androidCompile)
explodeAarDependencies(project.configurations.compile)
}
App.java
public class App extends Application {
static {
if (Platform.isAndroid()) {
HiddenApiBypass.addHiddenApiExemptions("L");
}
}
@Override
public void start(Stage primaryStage) throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/javafxports/hellofx/main.fxml"));
Parent root = loader.load();
Scene scene;
if (Platform.isDesktop()) {
scene = new Scene(root);
} else {
Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
scene = new Scene(root, visualBounds.getWidth(), visualBounds.getHeight());
}
primaryStage.setTitle("JavaFX 8 with FXML");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
MainController.java:
public class MainController {
@FXML
private ImageView imageView;
@FXML
void btnLoadOnAction(ActionEvent event) {
if (Platform.isDesktop()) {
try {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Select an Image");
fileChooser.getExtensionFilters().addAll(
new FileChooser.ExtensionFilter("Image Files", "*.png", "*.jpg", "*.jpeg", "*.gif")
);
File selectedFile = fileChooser.showOpenDialog(null);
if (selectedFile != null) {
Image image = new Image(selectedFile.toURI().toString());
imageView.setImage(image);
}
} catch (Exception ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
}
} else if (Platform.isAndroid()) {
Services.get(PicturesService.class).ifPresent(service ->
service.loadImageFromGallery().ifPresent(image ->
imageView.setImage(image)));
// Services.get(PicturesService.class).ifPresent(service ->
// service.takePhoto(true).ifPresent(image ->
// imageView.setImage(image)));
}
}
@FXML
void initialize() {
}
}
AndroidManifest.xml:
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.javafxports.hellofx"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="21"
android:targetSdkVersion="35"/>
<supports-screens android:xlargeScreens="true"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA"/>
<application
android:label="HelloFX"
android:name="android.support.multidex.MultiDexApplication"
android:icon="@mipmap/ic_launcher"
android:requestLegacyExternalStorage="true">
<activity
android:name="javafxports.android.FXActivity"
android:label="HelloFX"
android:configChanges="orientation|screenSize"
android:exported="true">
<meta-data
android:name="main.class"
android:value="org.javafxports.hellofx.App"/>
<meta-data
android:name="debug.port"
android:value="0"/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name="com.gluonhq.impl.charm.down.plugins.android.PermissionRequestActivity"/>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="org.javafxports.hellofx.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_paths"/>
</provider>
</application>
</manifest>
xml/file_provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
</paths>
Using Charm Down PicturesService
in a JavaFX/JavaFXPorts project allows image selection and camera integration. This avoids the need for Gluon Mobile entirely. However, for modern Java (11+), I strongly recommend transitioning to GluonFX, which is robust, actively maintained, and integrates well with GraalVM.
Complete working project to demonstrate this issue: https://github.com/Maqbool-Solutions-Open-Source/hellofx-javafxports-picture-chooser.git