Сегодня мы рассмотрим такую тему, как использовать Java методы при помощи JNI.
На самом деле все очень просто. Давайте сразу начнем с примера:
Допустим у нас есть некое Java приложение на котором есть простая кнопка и при нажатии на эту кнопку будет исполняться некий код.
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) { File MyFile = new File("D:\\Sample\\text.txt"); MyFile.delete(); }
Как мы видим в событии клика на кнопку будет исполняться просто код для удаления файла.
На Java все выглядит ясно и просто, но как же это будет выглядеть на Delphi с использованием JNI. На самом деле все проще чем кажется.
Для этого нам нужно разобрать заглянуть и в класс File, который находится по адресу java.io.File. Из этого класса нам нужно:
Получиться сам класс
Получить функцию delete, а именно Имя и Дескриптор.
Заполнить аргумент для данной функции
Использовать ее.
И так приступим.
Самой удобной утилитой для разборки класса на чечки на мой взгляд является DirtyJOE. КИдаем туда класс File и в методах ищем нашу функцию. Находим ее Имя и Дескриптор. Переходим в Delphi и создаем там такую функцию.
function JVM_DeleteFile(JNIEnv: PJNIenv; FilePath: String): Boolean;
Обратим внимание в DirtyJOE что функция delete возвращает назад Boolean.
Тут все просто: Название функции и объявляем переменные.
Давайте объявим переменные для работы нашего кода:
var FileClass: JClass; Delete, Init: JMethodID; FileObj: JObject; Args: array[0..0] of JValue;
Это все то что далее мы будем искать и использовать.
Теперь давайте заполним Аргументы
Args[0].l:= WideToJString(jnienv, PwideChar(WideString(FilePath)));
Обратите внимание что JString мы передаем как JObject (По сути JString это и есть JObject)
Ну а далее мы будем получать класс и метод delete:
FileClass:= jnienv^.FindClass(jnienv, 'java/io/File'); Delete:= jnienv^.GetMethodID(jnienv, FileClass, 'delete', '()Z');
А теперь не мало важный этап. Обратите внимание что в Java коде мы создаем новый объект new File и в Delphi нам требуется сделать тоже самое:
Init:= jnienv^.GetMethodID(jnienv, FileClass, '<init>', '(Ljava/lang/String;)V'); FileObj:= jnienv^.NewObjectA(jnienv, FileClass, Init, @Args);
И нам по сути осталось только использовать сам метод delete:
jnienv^.CallBooleanMethod(jnienv, FileObj, Delete)
Но, так как вначе всего мы обратили внимание что функция delete возвращает Boolean, то давайте же сделаем проверку на возврат True и False:
if jnienv^.CallBooleanMethod(jnienv, FileObj, Delete) = 1 then Result:= True else Result:= False;
Ну и давайте посмотрим на эту функцию в готовом виде:
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;
Заключение.
На самом деле все проще чем кажется. С помощью JNI можно использовать любой Java метод. В этом примере, если вы внимательно смотрели то увидели что я использовал запись Аргументов типа JValue и как нужно их использовать. Это очень важный момент.