Adobe Air и его экстеншены
Запись от usacha размещена 20.01.2012 в 17:38
Прошлой осенью в эфир вышла версия 3.0 всеми горячо любимой приблуды – Adobe Air. Основной фичей этого релиза стало добавление возможности прикрутки к обычному приложению так называемых native-extension. Это было сделано в первую очередь для того, чтобы разработчики могли использовать разные специфические функции мобильных платформ (например in-app billing в Android или его аналог in-app purchase в IOS). Просто дешево сердито. В принципе дальше можно не продолжать, смело выбрасывать AIR с его флешом и начать изучать нормальные платформы (а учить их прийдеться полюбому). Но поскольку вокруг флеша крутяться толпы мини-игроделов ( вроде меня

Принцип работы экстеншенов прост - мы даем AIR-у специально собраную нативную библиотеку, он предоставляет нам механизм вызова функций этой библиотеки и передачи флешовых параметров туда и обратно. Как создать такую библиотеку неплохо описано в официальном мануале адобов. Ничего особо сложного там нет, хотя с IOS могут возникнуть проблемы (писанина под мак, и особенно ифон, всегда было особым подвидом БДСМ). Я же остановлюсь на моменте плохо прописаном в мануале - а именно сборке екстеншена (.ane - файла).
Для сборки на понадобиться:
- сорцы нативной бибилиотеки 1шт
- сорцы as3-врапера нативной билиотеки 1шт
- конфиг екстеншена
Я бы ОЧЕНЬ рекомендовал людям, которые связались с экстеншенами под андроид выяснить что такое ANT и как писать для него билд.хмл-и. Кроме того что это просто прикольная тулза, в будущем это сэкономит прорву времени и нервов.
Шаг 1 – собираем нативную либу.
Под андроидом тут проблем быть не должно. Просто берем javac компилим все в класы, и пакуем класы в jar. В качестве примера вот мой билд хмл для нативной либы андроида. (Как тут всавить спойлер?)
Код:
<?xml version="1.0" encoding="UTF-8"?> <project name="Native classes" basedir="."> <property file="../global.properties"/> <property file="../sdk.properties"/> <property file="native.properties"/> <property name="OUTPUT" value="${basedir}/${OUT_FOLDER}"/> <patternset id="ignored.files"> <exclude name="**/CVS/**"/> <exclude name="**/SCCS/**"/> <exclude name="**/RCS/**"/> <exclude name="**/.DS_Store/**"/> <exclude name="**/.svn/**"/> <exclude name="**/.pyc/**"/> <exclude name="**/.pyo/**"/> <exclude name="**/*.pyc/**"/> <exclude name="**/*.pyo/**"/> <exclude name="**/.git/**"/> <exclude name="**/*.hprof/**"/> <exclude name="**/_svn/**"/> <exclude name="**/.hg/**"/> <exclude name="**/*.lib/**"/> <exclude name="**/*~/**"/> <exclude name="**/*.o/**"/> <exclude name="**/*.obj/**"/> <exclude name="**/__pycache__/**"/> <exclude name="**/.bundle/**"/> </patternset> <path id="android.platform.classpath"> <fileset dir="${ANDROID_SDK}"> <include name="platforms/android-8/android.jar"/> </fileset> </path> <path id="module.production.classpath"> <path refid="android.platform.classpath"/> <pathelement location="${AIR_SDK}/lib/android/FlashRuntimeExtensions.jar"/> </path> <path id="sourcepath"> <dirset dir="${basedir}"> <include name="src"/> </dirset> </path> <target name="compile"> <mkdir dir="${OUTPUT}"/> <mkdir dir="${OUTPUT}/classes"/> <javac destdir="${OUTPUT}/classes" debug="${compiler.debug}" nowarn="${compiler.generate.no.warnings}" memorymaximumsize="${compiler.max.memory}" fork="true" executable="${JDK}/bin/javac"> <compilerarg line="${compiler.args}"/> <classpath refid="module.production.classpath"/> <src refid="sourcepath"/> <patternset refid="ignored.files"/> </javac> <jar destfile="${OUTPUT}/billing.jar" basedir="${OUTPUT}/classes"/> </target> </project>
Шаг 2 – собираем swc
Для того, чтобы можно было обращаться к нативной билиотке надо создать AS3-интерфейс для всего этого безобразия. В нем описаны все функции, которые можно вызывать в либе и в нем же парситься JSON, в котором либа шлет нам обьекты ивентов. Пример такого врапера:
package { import flash.events.Event; import flash.events.EventDispatcher import flash.events.StatusEvent import flash.external.ExtensionContext public class MyExtensionextends EventDispatcher { private static var extContext: ExtensionContext = null; public function MyExtension() { trace("Constructor"); if (!extContext) { initExtension(); if (extContext != null) { trace("onWaaaargh setupped") extContext.addEventListener(StatusEvent.STATUS, onStatusChanged); } } } private static function initExtension(): void { trace("onstructor: Create an extension context"); extContext = ExtensionContext.createExtensionContext("com.my.MyExtension", null); } public function start(): void { trace("start()"); extContext.call("startService"); } public function stop(): void { trace("stop()"); extContext.call("stopService"); } private function onStatusChanged(event: StatusEvent): void { trace("onStatusChanged( " + event.code + " )"); dispatchEvent(new MyEvent(event.code, JSON.parse(event.level))); } override public function dispatchEvent(event: Event): Boolean { return super.dispatchEvent(event); } } }
Код:
<target name="compile"> <mkdir dir="${AS3_WRAPPER_OUT}"/> <java jar="${COMPC}" fork="true" failonerror="true"> <arg value="+flexlib=${AIR_SDK}/frameworks"/> <arg value="+configname=air"/> <arg value="-swf-version=13"/> <arg value="-source-path"/> <arg value="${basedir}/src"/> <arg value="-include-classes"/> <arg value="${AS3_WRAPPER_CLASS}"/> <arg value="-external-library-path"/> <arg value="${AIR_SDK}/frameworks/libs/air/airglobal.swc"/> <arg value="-output"/> <arg value="${AS3_WRAPPER_OUT}/${EXT_NAME}.swc"/> </java> <unzip src="${AS3_WRAPPER_OUT}/${EXT_NAME}.swc" dest="${AS3_WRAPPER_OUT}"/> <copy file="${AS3_WRAPPER_OUT}/${EXT_NAME}.swc" todir="${AS3_WRAPPER_OUT}"/> <copy file="${AS3_WRAPPER_OUT}/library.swf" todir="${AS3_WRAPPER_OUT}"/> <copy file="${basedir}/src/extension.xml" todir="${AS3_WRAPPER_OUT}"/> <delete file="${AS3_WRAPPER_OUT}/catalog.xml"/> </target>
Шаг 3 – сборка ane
Берем adt и в нужном пордяке отдаем ему все компоненты: extension.xml (конфиг екстеншена. Как его сделать см мануал адобов), нашу свежесобраную swc, library.swf и собственно саму нативную либу. Какие параметры задать адт лучше всего видно в ANT-таске который все это пакует.
Код:
<target name="create extension" depends="build as3 wrapper"> <java jar="${ADT}" fork="true" dir="${ANE_OUTPUT}" failonerror="true"> <arg value="-package"/> <arg value="-target"/> <arg value="ane"/> <arg value="${EXT_NAME}.ane"/> <arg value="extension.xml"/> <arg value="-swc"/> <arg value="${EXT_NAME}.swc"/> <arg value="-platform"/> <arg value="Android-ARM"/> <arg value="library.swf"/> <arg line="${EXT_NAME}.jar"/> </java> <copy file="${ANE_OUTPUT}/${EXT_NAME}.swc" todir="${RES}"/> </target>
Всего комментариев 5
Комментарии
![]() ![]() |
|
Я делал экстеншен под иос, (правда без билинга) там проблема была с опциями компилятора. Тучу времени убили пока понялии что там под два проца надо собирать. (Там в мерзком Хкоде есть место где надо прописать опции armv6 armv7) Билд скриптов в хкоде нет, да и не я собирал (к счастью рядом оказался человек, который шарит в иос) потому завереный скриншоты показать не могу.
В принципе пример должен был где-то остаться... У меня есть более менее рабочий пример приложения под андроид с инап биллингом. Под иос заделать руки не дошли в свое время, а теперь хз дойдут ли. Как мне обьясняли, под иос относительно просто это делать. Вызываешь функцию и слушаешь нотификации системы. А вот под андроид запускаеться сервис, комуникация с ним налаживаеться, он при покупке загоняет приложение в бэкграунд, показывает форточку покупки поверх приклады... Короче мутно. |
|
Обновил(-а) usacha 21.01.2012 в 04:06
|
![]() ![]() |
|
Ага) Я с этим наверно не разберусь...
|
Последние записи от usacha
- Adobe Air и его экстеншены (20.01.2012)