Search code examples
javaandroiddelphijava-native-interfacedelphi-10.2-tokyo

Using Delphi's AndroidHelper or JNI to access static Java method in Delphi


Important Files to understand the question:

VpnService Java Class

VpnService Translated to Delphi

My goal is to call the public static Intent prepare(Context context) method from VpnService.java and receive the Intent.

I tried several ways to access it, for example:

var
   Intent: JIntent;
   JVC: JVpnService;
begin
   JVC := TJVpnService.JavaClass.init;
   Intent := JVC.prepare(Context); // No Method prepare

or

var
   Intent: JIntent;
   JVC: JVpnServiceClass;
begin
   JVC := JVpnServiceClass.javaClass.init; // Record, Objekt oder Klassentyp erforderlich

or

var
Intent: JIntent;
   JVC: JVpnServiceClass;
begin
   JVC := JVC.javaClass.init; //Inkompatible Typen JVpnServiceClass und JVpnService

I really have no clue how to access this static method.


Solution

  • JavaClass.init() is a constructor call to create an object instance. Static methods are accessed from the JavaClass directly. So, you should be calling TJVpnService.JavaClass.prepare() instead. If that is not working then TJVpnService is likely not setup correctly to begin with.

    Looking at the generated .pas file, I think its [JavaSignature] attribute is declaring the wrong type. That would explain why JNI can't find the prepare() method at runtime.

    The generated .pas file does not include any declarations for the VpnService.Builder inner class at all, but yet the [JavaSignaure] attribute for TJVpnService is trying to import methods from the Builder class. prepare() is a method of the VpnService class itself, not the Builder class, so try changing the [JavaSignature] attribute to [JavaSignature('android/net/VpnService')] instead of [JavaSignature('android/net/VpnService$Builder')].

    And then file a bug report with Software Union, as its Java2Pas tool imported the VpnService.java file incorrectly.