Статьи

Мерапи: мост между AIR и Java

Если вы когда-либо создавали приложение Adobe AIR, вполне вероятно, что у вас возникли проблемы с моделью безопасности Sandbox. Модель безопасности «песочницы» в AIR позволяет разработчикам не создавать приложения, которые могут извлекать информацию с компьютера пользователя или наносить ему вред. Эти меры предосторожности оправданы и делают AIR безопасной альтернативой для создания настольных приложений. Когда пользователь устанавливает приложение AIR, он всегда встречает одни и те же стандартные экраны установки и знает, что устанавливаемое им программное обеспечение является безопасным. Единственным недостатком модели Sandbox является то, что она может быть очень ограничена для разработчика. Доступ к внешним дискам, командной строке и даже спискам собственных приложений заблокирован Sandbox Security. В результате приложения часто запускаются только с некоторыми из их возможных функций. 

С выпуском AIR 2.0 для бета-версии был решен ряд проблем безопасности. Теперь приложения могут получать доступ к внешним устройствам хранения и открывать файлы в собственных приложениях, но есть некоторые ограничения. Здесь Мерапи вступает в игру.

Merapi — это мост между приложениями AIR на основе Flex и Java. Мост Merapi обеспечивает связь между двумя технологиями посредством использования сообщений. Сообщения могут содержать сложные данные, а протоколы сериализации данных AMF используются для передачи данных. Введение Java в уравнение позволяет разработчикам создавать передовые программные решения, поскольку Java способна взаимодействовать с гораздо большим количеством аспектов системы пользователя. Используя Java, можно получить доступ не только к базовому коду и функциям операционной системы пользователя, но и ко многим библиотекам, которые может предложить Java. Поскольку многие внешние устройства (такие как сканеры штрих-кода, датчики температуры и устройства GPS) часто поставляются с API на основе Java,Merapi позволяет разработчику взаимодействовать с этими API-интерфейсами и создавать приложения, разработанные специально для конкретных сценариев, которые AIR сама по себе не сможет приспособить. 

У людей часто возникают проблемы с обходом модели безопасности «песочницы» AIR; в конце концов, эта безопасность была введена в действие по причине. Они не хотят видеть рынок наводненным небезопасными приложениями, которые могут использоваться хакерами для доступа к компьютерам пользователей. Однако этого не произойдет, главным образом потому, что для использования Merapi приложение AIR и приложение Java должны выполняться одновременно. Приложение Java также должно быть установлено отдельно от приложения AIR, а само приложение AIR не может устанавливать файлы Java. Если не установить файлы Java и не запустить приложение Java до запуска приложения AIR, связь не может быть установлена. Необходимость размещения файлов Java отдельно на компьютере пользователя — это то, что мешает Merapi использоваться в основных приложениях.Приложения Merapi часто необходимо устанавливать в очень специфических средах. Это делает их идеальными для внутренних приложений внутри компании, но не настолько идеальными для массового рынка.

Кодекс 

Теперь, когда мы рассмотрели некоторые из теорий, стоящих за Мерапи, давайте посмотрим, как они используются. Чтобы дать вам хорошее представление о том, как все работает, я проведу вас через процесс создания приложения Magic Eight Ball с помощью Merapi. Интерфейсом приложения будет приложение AIR на основе Flex, которое получает вопрос от пользователя и отправляет его в приложение Java через Merapi. Затем Java-приложение сгенерирует ответ на вопрос и отправит его обратно, также через Merapi, в приложение AIR. Наконец, приложение Air отобразит сообщение. В конце этого примера вы увидите, как общение работает в разнонаправленном режиме и должно хорошо понимать силу, которую может предложить Merapi.

Первое, что вам нужно сделать, это получить последние файлы Merapi. Есть 3 SVN Repo, которые вы должны проверить, чтобы убедиться, что у вас есть последние файлы. Merapi был в публичной бета-версии только в течение нескольких месяцев, поэтому регулярно обновляются код.

В ближайшие месяцы все эти файлы будут объединены в один ствол для упрощения загрузки.

Получив последние файлы, вы можете приступить к созданию Java-приложения. При создании приложения Java рекомендуется создать основной файл Java, в котором создаются необходимые файлы обработчиков. Файлы обработчиков, которые должны находиться в пакете обработчиков, — это файлы, которые содержат большую часть логики для вашего приложения. Обработчики — это классы, которые обрабатывают входящие сообщения. Сами сообщения набираются, поэтому обработчики будут взаимодействовать только с соответствующими сообщениями. В вашем приложении вы также будете иметь классы сообщений. Для каждого типа сообщений, отправляемых или получаемых вашим приложением, будет свой класс сообщений. Расположенные в пакете сообщений, эти классы будут вызываться из классов-обработчиков.

 

Шаги Java

Итак, обо всем по порядку — создайте новый Java-проект в eclipse и добавьте необходимые jar-файлы в библиотеку. Список необходимых jar-файлов можно посмотреть на снимке экрана ниже.

 

 После создания проекта создайте файл с именем magicEightBallRunner. Это основной файл приложения, который должен находиться в пакете по умолчанию. Как только он будет создан, добавьте следующий код:

import merapi.Bridge;
import handlers.questionHandler;

public class magicEightballRunner {

public static void main( String[] args )
{
Bridge.open();
new questionHandler();
}
}

В этом коде мы импортируем класс моста и класс questionHandler. Затем мы открываем мост и создаем новый экземпляр questionHandler, тем самым подписывая приложение на канал сообщений в мосте. Один и тот же мост используется для всех приложений Merapi, поэтому приложение будет иметь доступ ко всем сообщениям, включая те, которые относятся к приложению, и те, которые не имеют. Это вопросHandler, который выбирает, какие сообщения приложение получит, а какие нет. Для тех, кто имеет опыт работы с такими технологиями, как Blaze или LiveCycle, этот подход подписчик / производитель покажется знакомым. Эти две строки кода настроили приложение для подписки.

Следующий файл, который мы должны создать, это обработчик. Как указывалось ранее, класс обработчика содержит большую часть логики для приложения. Обработчик создается для каждого типа сообщения, которое приложение будет читать, а внутри обработчика находится функция handleMessage. Эта функция вызывается, когда обработчик распознает сообщение в мосте, которое соответствует его критериям. Другой способ думать о обработчиках — думать о них как о слушателях событий. Обработчик «слушает» мост и действует, когда встречает сообщение.

Поэтому создайте пакет обработчиков и создайте класс с именем questionHandler внутри пакета. Затем добавьте следующий код:

package handlers;

import messages.questionMessage;
import merapi.handlers.MessageHandler;
import merapi.messages.IMessage;
import java.util.Random;

public class questionHandler extends MessageHandler{
public questionHandler()
{
super( questionMessage.ASK_IT );
}

public void handleMessage( IMessage message )
{
if ( message instanceof questionMessage )
{
questionMessage qMessage = ( questionMessage ) message;
Random generator = new Random();
int randomIndex = generator.nextInt( 10 );

String answer = null;

switch(randomIndex){
case 1: answer = "As I see it, yes"; break;
case 2: answer = "It is decidedly so"; break;
case 3: answer = "Without a doubt"; break;
case 4: answer = "Reply hazy, try again"; break;
case 5: answer = "Better not tell you now"; break;
case 6: answer = "Concentrate and ask again"; break;
case 7: answer = "Don't count on it"; break;
case 8: answer = "Outlook not so good"; break;
case 9: answer = "Yes - definitely"; break;
case 10: answer = "You may rely on it"; break;

}
qMessage.setAnswer(answer);
qMessage.send();
}
}
}

Этот класс расширяет класс MessageHandler, который содержится в Merapi. В верхней части класса мы импортируем необходимые библиотеки. При создании обработчика важно импортировать соответствующий класс сообщения, чтобы вы могли получить доступ к информации, такой как тип сообщения, из класса. Также важно импортировать класс, если вы планируете отправлять какие-либо сообщения. Вы также должны импортировать классы IMessage и messageHandler из Merapi. В этом примере мы также импортируем класс java.util.Random, так как мы будем случайным образом выбирать, какой ответ предоставить. Скорее всего вам это не понадобится в других примерах.

Первая часть этого класса — конструктор. В конструкторе мы вызываем суперфункцию и передаем статическую переменную из класса questionMessage. Эта переменная является строкой, указывающей, какой тип сообщения будет обрабатывать этот обработчик. Строковое значение может быть любым, но вы должны соответствовать строковому значению в приложении AIR. В противном случае обработчик никогда не получит сообщения с моста.

Вторая часть этого класса — функция handleMessage. Как указано выше, каждый обработчик должен иметь функцию handleMessage. Эта функция принимает IMessage, который является объектом сообщения от моста. Это IMessage затем приводится как тип сообщения, который обрабатывает обработчик. Если у вас есть переменная сообщения в нужном вам формате, вы можете использовать любую логику, необходимую для достижения вашей цели. Если бы вы создавали приложение, которое взаимодействовало с каким-либо сторонним API, вы бы разместили эту логику здесь. В этом примере мы генерируем случайное число, которое мы используем в операторе switch для выбора ответа, который мы хотим предоставить. Затем мы устанавливаем значение ответа для объекта questionMessage, который мы создали ранее, и вызываем функцию send. Вызов функции отправки отправляет сообщение обратно на мост,где он будет ждать, чтобы быть поднятым приложением AIR.

Теперь давайте посмотрим на класс сообщений. Создайте новый пакет с именем messages, и в этом пакете создайте новый класс под названием questionMessage. Внутри класса поместите следующий код:

package messages;
import merapi.messages.Message;

public class questionMessage extends Message{

public static final String ASK_IT = "magicQuestion";

public questionMessage()
{
super();
}

public String getQuestion() { return __question; }
public void setQuestion( String val ) { __question = val; }

public String getAnswer() { return __answer; }
public void setAnswer( String val ) { __answer = val; }

private String __question = null;
private String __answer = null;

}

Как видите, это очень простой класс. Создается переменная с именем ASK_IT (вы можете помнить, что это переменная, которую мы вызываем из класса обработчика), и ей присваивается значение magicQuestion. Это значение используется для различения разных типов сообщений, которые могут присутствовать в мосте. В классе конструктора мы вызываем суперфункцию, а затем настраиваем методы получения и установки, необходимые для объекта. В этом примере объект может хранить как вопрос, так и ответ, а также извлекать указанные значения.

Теперь, когда у вас есть все необходимые файлы, запустите приложение и убедитесь, что нет ошибок. Если все пойдет хорошо, приложение запустится, и ничего не произойдет. Это один из немногих случаев, когда ничего не видно — это хорошо.

Flex Stuff

Теперь, когда Java работает, давайте перейдем к созданию нашего приложения AIR.

Файлы для приложения AIR по структуре схожи с файлами Java. Существует основной файл приложения и класс сообщений, но вместо того, чтобы иметь класс обработчика, эта функциональность часто просто размещается везде, где есть функциональность Merapi. 

Первое, что вам нужно сделать, чтобы создать приложение AIR, — это создать новый проект в Flex Builder. При создании проекта не забудьте выбрать, что это настольное приложение. Когда вы попадете в раздел библиотеки, добавьте SWC-файлы, которые вы извлекли из Merapi Repo.

Создав свой проект, откройте основной файл MXML и поместите в него следующий код.

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:merapiproject="http://merapiproject.net/2009"
layout="absolute"
>
<merapiproject:MessageHandler
id="questionHandler"
type="{ questionMessage.ASK_IT }"
result="handleResult(event)"/>

<mx:Script>
<![CDATA[
import mx.rpc.events.ResultEvent;
import merapi.messages.IMessage;
import merapi.messages.Message;
import com.magiceightball.messages.*;

private function askIt():void{
var q:questionMessage = new questionMessage();
q.question = question.text;
q.send();
}

private function handleResult(e:ResultEvent):void{
var message:questionMessage = e.result as questionMessage;
answerReceived.text = message.answer;
questionAsked.text = message.question;
question.text='';
}
]]>
</mx:Script>

<mx:Label x="40" y="42" text="What is your question?"/>
<mx:TextInput x="181" y="40" id="question"/>
<mx:Button x="108" y="94" label="Ask" click="askIt()"/>
<mx:Label x="150" y="168" id="answerReceived"/>
<mx:Label x="40" y="142" text="Question Asked:"/>
<mx:Label x="40" y="168" text="Answer Received:"/>
<mx:Label x="150" y="142" id="questionAsked"/>

</mx:WindowedApplication>

Изучив этот код, вы увидите много общего между этим кодом и кодом Java. Частично это происходит из-за сходства между ActionScript и Java, а частично из-за того, что Merapi использует объекты, которые в целом очень похожи от языка к языку. Самое большое различие, которое вы увидите в коде Flex, состоит в том, что вместо отдельного класса обработчика этот код определяет обработчик сообщений с помощью тега MessageHandler. В этом теге мы указываем тип сообщения, которое оно обрабатывает, и какую функцию вызывать при получении сообщения. Если вы создаете приложение, которое будет использовать различные типы сообщений, вам нужно будет использовать несколько тегов MessageHandler. В этом примере, как и в примере с Java, тип сообщения хранится в классе сообщений как статическая переменная.В этом случае класс сообщения называется questionMessage. Значением этой переменной, как и в примере с Java, является magicQuestion.

Функция askIt () — это функция, используемая для создания и отправки сообщения в Java. Эта функция создает экземпляр questionMessage и заполняет его предоставленными пользователем данными. Затем он вызывает функцию отправки, которая отправляет сообщение на мост. Попав в мост, сообщение может быть получено любыми другими приложениями, подключенными к мосту.

Функция handleResult () вызывается всякий раз, когда из Java поступает новое сообщение. Сообщение передается функции через resultEvent, а затем приводится как QuestionMessage. Как только он будет в правильном формате, ответ, который был сгенерирован Java, извлекается и отображается пользователю.

Давайте посмотрим на финальный файл, который нам нужно будет создать для этого примера, класс questionMessage. Создайте новый класс ActionScript с именем questionMessage в пути com / magiceightball / messages. Лучше всего хранить все классы сообщений в папке сообщений, как в Java. В классе добавьте следующий код:

package com.magiceightball.messages
{
import merapi.messages.Message;
[RemoteClass( alias="messages.questionMessage" )]

public class questionMessage extends Message
{
public static const ASK_IT : String = "magicQuestion";
public var question : String = null;
public var answer : String = null;

public function questionMessage()
{
super( ASK_IT );
}

}
}

Как видите, для создания класса сообщений не требуется много кода, но код этого класса очень специфичен и должен точно соответствовать Java-эквиваленту этого класса. В этом классе вы заметите функцию remoteClass. В нем мы устанавливаем значение псевдонима. Значение псевдонима — это точный путь, который имеет класс questionMessage в приложении Java. Каждый раз, когда вы создаете новый тип сообщения, вы должны установить псевдоним, который отображает его в том месте, где находится его Java-эквивалент. В коде Java мы запускаем сравнение, чтобы убедиться, что мы имеем дело только с объектами одного типа. Использование псевдонима гарантирует, что Java увидит этот объект как один и тот же. Когда вы разрабатываете свое приложение, если у вас есть экземпляр, когда вы запускаете сообщения из своего приложения AIR, а Java их не получает, проверьте псевдоним,так как это, скорее всего, будет корнем проблемы. Много часов было потеряно для этой единственной строки кода.

Этот класс должен также соответствовать переменным своего Java-аналога. Вы заметите, что в этом классе есть переменные вопрос и ответ, а в классе Java есть методы получить / задать вопрос и получить / установить ответ. Важно, чтобы оба объекта имели одинаковые методы, но поскольку ActionScript автоматически генерирует методы получения и установки для своих открытых переменных, вам нужно только создать переменные в классе ActionScript.

Теперь, когда у нас есть весь код, созданный для этого приложения, давайте рассмотрим его. Первое, что вы захотите сделать, это запустить приложение Java. Перейдите к файлу magicEightballRunnner и запустите его. Как только он будет работать без ошибок, запустите приложение AIR. Вы увидите текстовую область и кнопку. Введите вопрос и нажмите кнопку. Если все идет хорошо, под кнопкой вы должны увидеть заданный вопрос и ответ от Java. Все, что отображается под кнопкой — и вопрос, и ответ — это данные из приложения Java. Теперь у вас есть первое полнофункциональное приложение Merapi! Потратьте некоторое время, чтобы осмотреться и поиграть с некоторыми методами, пока вы не почувствуете себя достаточно комфортно, чтобы создать собственное приложение.

Как видно из этого примера, очень легко создавать приложения, которые взаимодействуют через мост Merapi. Один этот пример был создан менее чем за 45 минут. Открытие приложений Java для AIR обеспечивает совершенно новую область разработки приложений. Приложения могут не только связываться с другими технологиями, к которым ранее можно было получить доступ только через веб-серверы, но и теперь приложения могут взаимодействовать и управлять устройствами, доступными через последовательные порты и USB-накопители. Если вы посмотрите на веб-сайт Merapiвы увидите, что уже есть несколько видеороликов, демонстрирующих приложения AIR, взаимодействующие со сканерами RFID, устройствами GPS и даже роботами Lego Mindstorm. Это лишь некоторые из бесконечных возможностей, которые вы имеете при подключении приложений AIR к Java. Мой вопрос к вам: что вы собираетесь строить?