Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Регистрация Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > usacha

Рейтинг: 4.80. Голосов: 5.

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>
Вероятность собрать что-либо под ифон без проблем с первого раза стремиться к нулую. Вероятно тут прийдеться выставить пива ифонщику, долго гуглить, и по методу научного тыка таки выставить правильные опции компилятора. Впрочем, это к AIR-у не относиться.

Шаг 2 – собираем swc
Для того, чтобы можно было обращаться к нативной билиотке надо создать AS3-интерфейс для всего этого безобразия. В нем описаны все функции, которые можно вызывать в либе и в нем же парситься JSON, в котором либа шлет нам обьекты ивентов. Пример такого врапера:

Код AS3:
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);
        }
    }
}
Берем в руки compc и собираем swc. Эту swc мы сохраняем, подключем в проекте и тд. Дальше веселее: если кто не знает – swc это по сути zip с упаковаными library.swf и catalog.xml. Нам нужно взять swc, и зипом вынуть из нее library.swf. (смотри екзампл ант-таргета)

Код:
    <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

Комментарии

Старый 21.01.2012 01:15 Astraport вне форума
Astraport
 
Аватар для Astraport
Можно я без приглашения т. к. совсем не эксперт
Спасибо за инфу, может быть пригодиться в будущем. Все же кажется не все так просто, т. к. до сих пор не нашел нормального расширения для in-app billing для Android и для него же получение списка контактов с телефонной книги, например для отправки им SMS (отдельное подключение и передачу данных реализовал через Share, но хотелось бы внутри приложения).
Старый 21.01.2012 01:20 usacha вне форума
usacha
Цитата:
не нашел нормального расширения для in-app billing для Android и для него же получение списка контактов с телефонной книги
Может просто никому не надо было, потому и не писал. А если и писал то не выкладывал. Собсно это оборотная сторона этих экстеншенов - надо иметь под рукой человека который умеет писать под андроид или ифон. Платформы сложные. Особенно андроид. Без специалиста трудно (
Старый 21.01.2012 01:37 Zebestov вне форума
Zebestov
 
Аватар для Zebestov
Эх! Если бы ты выложил здесь пример сборки готового приложения для iOS с применением какого-то native extension (особенно in-app purchase интересует, и есть в сети бесплатный) — цены бы тебе не было!
Старый 21.01.2012 03:08 usacha вне форума
usacha
Я делал экстеншен под иос, (правда без билинга) там проблема была с опциями компилятора. Тучу времени убили пока понялии что там под два проца надо собирать. (Там в мерзком Хкоде есть место где надо прописать опции armv6 armv7) Билд скриптов в хкоде нет, да и не я собирал (к счастью рядом оказался человек, который шарит в иос) потому завереный скриншоты показать не могу.

В принципе пример должен был где-то остаться...

У меня есть более менее рабочий пример приложения под андроид с инап биллингом. Под иос заделать руки не дошли в свое время, а теперь хз дойдут ли. Как мне обьясняли, под иос относительно просто это делать. Вызываешь функцию и слушаешь нотификации системы. А вот под андроид запускаеться сервис, комуникация с ним налаживаеться, он при покупке загоняет приложение в бэкграунд, показывает форточку покупки поверх приклады... Короче мутно.
Обновил(-а) usacha 21.01.2012 в 04:06
Старый 25.01.2012 17:03 argoniummm вне форума
argoniummm
Ага) Я с этим наверно не разберусь...
 
Последние записи от usacha

 


Часовой пояс GMT +4, время: 12:24.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.