Предисловие
Это перевод заключительной, третьей части цикла статей о создании нативных библиотек расширения для OpenFL. Во второй части рассказавалось как создать библиотеку расширений для iOS. В данной части, будет рассказано о создании библиотеки расширений для платформы Android, на языке Java и, как будет видно далее, для Android сделать это несколько проще, чем для iOS.
Java, Haxe и все, все, все!
Для своей следующей игры, я придумал показывать справку в виде встроенной HTML страницы и нашел следующий проект: NMEWebview. Этот проект хорошо демонстрирует, как мы можем использовать код на Java в нашем приложении на haxe.
Пришло время проверить взаимодействие с кодом на Java.
Создадим каталог для расширения:
cd project
mkdir android
mkdir android/testextension
И файл TestExtension.java
package testextension;
class TestExtension {
public static String doSomething(String in){
return in+"n"+in;
}
}
testextension.TestExtension.doSomething(String):String наша тестовая функция и нам нужно экспортировать ее в haxe.
Так как мы пишем на Java, мы уже не можем использовать cpp.Lib.load для доступа к расширению и должны использовать для этого openfl.utils.JNI.
Вот таким образом я сделал обертку на haxe в TestExtension.hx:
#if android
// К сожалению, мы не можем использовать функции JNI до выполнения функции main.
// Я пробовал, верьте мне :)
private static var testextension_dosomething : Dynamic;
private static function init(){
if (testextension_dosomething != null)
return;
testextension_dosomething = openfl.utils.JNI.createStaticMethod(
"testextension/TestExtension",
"doSomething",
"(Ljava/lang/String;)Ljava/lang/String;"
);
}
public static function doSomething(str:String) : String {
init();
return testextension_dosomething(str);
}
#end
openfl.utils.JNI.createStaticMethod работает аналогично cpp.Lib.load. Первые два параметра этой функции это названия класса и название статического метода, который мы собираемся использовать. А вот третий аргумент самая сложная часть — это сигнатура метода.
Можно сказать, что () обозначают метод, и то что внутри скобок это аргументы, а то что снаружи — тип результата.
(Ljava/lang/String;)Ljava/lang/String; соответствует String->String в haxe.
Подробнее про обозначение сигнатур в JNI (с примерами) вы можете прочесть здесь, но хочу заметить, что это первая ссылка, которую я нашел в Google. Я думаю, что существует и более простая документация.
У нас нет необходимости компилировать наше Java расширение перед использованием, компиляция будет происходить при сборке приложения и нам нужно указать как это делать.
Для этого в файл include.xml в каталоге с расширением добавим следующую строчку:
<java path="project/android" if="android" />
После этого, вызов TestExtension.doSomething() в приложении TestApp будет прекрасно работать.
Код из этой статьи вы можете найти в репозитории на GitHub'e.
Имейте в виду, что я также добавил файл android/Tweet.cpp (но не реализовал функцию Tweet), чтобы избежать условной компиляции и добавления #if ios по всему коду.
Следующее, что я хочу сделать в связке Java/haxe — научиться передавать HaxeObject и вызывать функции там и тут (на данный момент openfl.utils.JNI немного ограничен, но я думаю мы сможем экспортировать все необходимые C++ методы из JNI в haxe).
От переводчика
На этом заканчивается цикл статей о создании нативных библиотек расширений от Laurent Bédubourg. Цикл описывается необходимый минимум, достаточный, чтобы начать работу над своим расширением. Когда я начал работу над своим набором расширений, данных статей не было и информацию приходилось искать в различных блогах.
Если вы захотите создать расширение для Android и вам понадобятся возможности последних SDK, то вот здесь можно найти статью о том, как собрать расширение для нужной версии SDK.
Автор: zzzzzzerg