Using Android API’s in JavaFX.

In a previous blog entry, I talked about the JavaFX to Android porting project. Now that this seems to be on the rails, it’s time for some more integration. In this blog post, I will quickly show how you can use the Android API’s in your JavaFX application.

Before showing the code, I should stress that the current way of calling Android services from a JavaFX application is probably not the recommended way in the future. I am looking into better ways, but for now, this is the way it works.

We will create an example that retrieves and prints the location of the user (or the device, that is).

 

We assume you have the Android SDK and the JavaFX-Dalvik runtime, as explained in https://bitbucket.org/javafxports/android.
You have to create a JavaFX project. I use Netbeans 7.4 beta, and create a new JavaFX Application. The code of my application is here:

package locationandroid;

import android.location.Location;
import android.location.LocationManager;
import android.location.LocationProvider;
import java.util.List;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafxports.android.FXActivity;
public class LocationAndroid extends Application {

    private LocationManager lm;
    private String provider;

    @Override
    public void start(Stage primaryStage) {
        final Label l = new Label ("Location");
        FXActivity f = FXActivity.getInstance();
        if (f != null) {
            Object systemService = f.getSystemService(FXActivity.LOCATION_SERVICE);
            lm = (LocationManager)systemService;
            List providers = lm.getAllProviders();
            if ((providers != null) &&(providers.size()>0)) {
                this.provider = providers.get(0);
            }
        }
        Button btn = new Button();
        btn.setText("Retrieve location");
        btn.setOnAction(new EventHandler() {

            @Override
            public void handle(ActionEvent event) {
                Location loc = lm.getLastKnownLocation(provider);
               l.setText("Location: "+loc.getLatitude()+";"+loc.getLongitude());
            }
        });
        VBox all = new VBox();
        all.getChildren().addAll(btn, l);
        StackPane root = new StackPane();
        root.getChildren().add(all);
        Scene scene = new Scene(root, 300, 250);
        primaryStage.setTitle("JavaFX/Android Location");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

In the NetBeans project, we added 2 libraries:

  • android.jar, which is located in the Android SDK
  • jfxdvk.jar, which is located in the dalvik-sdk/rt/libs directory

You need the android.jar in order to use the Android API’s, and you need jfxdvk.jar in order to access the FXActivity class, which is the bridge between JavaFX and the Dalvik runtime. We use a static method on the FXActivity to retrieve the FXActivity, which extends the Android Context. This Context can be used to lookup Android services. As you can see, we obtain the Android LocationManager by calling

FXActivity.getSystemService(FXActivity.LOCATION_SERVICE);

The obtained LocationManager can be used to retrieve a list of LocationProviders. We just take the first one, and will use that to query the LocationManager and retrieve the current location whenever the user presses the “Retrieve Location” button.

When you want to run this, you need to ask permission to obtain the location. The AndroidManifest.xml file that is created when setting up your javafx android application needs to have this line:

<uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION”></uses-permission>

 

 

Again, this is just a very quick sample and it is not showing any best practices, but hopefully you can now start writing JavaFX Applications that leverage the Android API’s.