Today we are going to take a look at how to use Java methods with JNI.
In fact, everything is very simple. Let's start right away with an example:
Let's say we have a Java application on which there is a simple button and when this button is pressed, some code will be executed.
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
File MyFile = new File("D:\\Sample\\text.txt");
MyFile.delete();
}
As we can see, in the button click event, just the code to delete the file will be executed.
Everything looks clear and simple in Java, but how will it look in Delphi using JNI. In fact, everything is easier than it seems.
To do this, we need to parse and look into the File class, which is located at the java.io.File address . From this class, we need:
- Get the class itself
- Get the delete function , namely Name and Descriptor.
- Fill in the argument for the given function
- Use it.
And so let's get started.
The most convenient utility for disassembling a class into checks, in my opinion, is DirtyJOE. We go there the File class and look for our function in the methods. We find her Name and Descriptor. Go to Delphi and create such a function there.
function JVM_DeleteFile(JNIEnv: PJNIenv; FilePath: String): Boolean;
Note in DirtyJOE that the delete function returns a Boolean.
Everything is simple here: The name of the function and we declare the variables.
Let's declare variables for our code to work:
var
FileClass: JClass;
Delete, Init: JMethodID;
FileObj: JObject;
Args: array[0..0] of JValue;
This is all that we will look for and use further.
Now let's fill in the Arguments
Args[0].l:= WideToJString(jnienv, PwideChar(WideString(FilePath)));
Please note that we pass JString as JObject (In fact, JString is JObject)
Well, then we will receive the class and the delete method:
FileClass:= jnienv^.FindClass(jnienv, 'java/io/File');
Delete:= jnienv^.GetMethodID(jnienv, FileClass, 'delete', '()Z');
And now is not a little important stage. Please note that in Java code we create a new File object and in Delphi we need to do the same:
Init:= jnienv^.GetMethodID(jnienv, FileClass, '<init>', '(Ljava/lang/String;)V');
FileObj:= jnienv^.NewObjectA(jnienv, FileClass, Init, @Args);
And we essentially only need to use the delete method itself:
jnienv^.CallBooleanMethod(jnienv, FileObj, Delete)
But, since otherwise we noticed that the delete function returns Boolean, then let's check whether it returns True or False:
if jnienv^.CallBooleanMethod(jnienv, FileObj, Delete) = 1 then
Result:= True
else
Result:= False;
Well, let's take a look at this function ready-made:
function JVM_DeleteFile(JNIEnv: PJNIenv; FilePath: String): Boolean;
var
FileClass: JClass;
Delete, Init: JMethodID;
FileObj: JObject;
Args: array[0..0] of JValue;
begin
Args[0].l:= WideToJString(jnienv, PwideChar(WideString(FilePath)));
FileClass:= jnienv^.FindClass(jnienv, 'java/io/File');
Delete:= jnienv^.GetMethodID(jnienv, FileClass, 'delete', '()Z');
Init:= jnienv^.GetMethodID(jnienv, FileClass, '<init>', '(Ljava/lang/String;)V');
FileObj:= jnienv^.NewObjectA(jnienv, FileClass, Init, @Args);
if jnienv^.CallBooleanMethod(jnienv, FileObj, Delete) = 1 then
Result:= True
else
Result:= False;
end;
Conclusion.
In fact, everything is easier than it seems. Any Java method can be used with JNI. In this example, if you looked closely, you saw that I used a record of Arguments of type JValue and how to use them. This is a very important point .