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)













