неділю, 3 квітня 2011 р.

Ruboto: Ruby на Android

Автор статті - Chris King, програміст, фрілансер.
Оригінал: http://www.ibm.com/developerworks/web/library/wa-ruby/

Вступ

Більшість цікавих робіт з розробки програмного забезпечення сьогодні відбуваються в одній із двох крайнощів: великі сервери хмарних обчислень і крихітні мобільні пристрої. Ці області вирішують значно несхожі проблеми, і, відповідно, мають різні засоби підтримки. Розробка для серверів часто використовує скриптові мови, щоб зв'язувати разом різні компоненти і виконувати складні автоматизовані завдання. В той час як розробка для мобільних пристроїв зосереджена на конкретних можливостях і потребах конкретного пристрою і користувача.

Однак, ці дві крайності об'єднує спільна мова: Java. Чи то мобільна платформа Android, чи фреймворк Spring, багатьма з найбільш популярних технологій сьогодні прийнято мову, яка здобула широке розповсюдження і підтримку в усьому світі. Ця спільна мова може призвести до деяких дивних взаємодії між областями, про які ви схильні думати як різні. Java відкриває двері для багатьох крос-платформових варіантів, таких як, легке портування коду сервера на пристрій Android або зв'язування у рідні здібності платформи з існуючих компонентів.

У цій статті розглядається Ruboto. Проект, який усуває розрив між скриптовими мовами і Android. Ви дізнаєтеся про Ruby і Android, як вони можуть разом прийти у віртуальну машину Dalvik, як створювати і розгортати власні скрипти, і чому ця технологія має потенціал для підвищення продуктивності праці програмістів і гнучкості застосування.


Ruby

Багато скриптових мов конкурують за прихильність програмістів. Але на даний час Ruby займає сильні позиції. Найвідоміше, він підтримує веб-фреймворк Rails. Багато розробників також захоплюються Ruby за його поєднання лаконічності і елегантності. Об'єктно-орієнтована скриптова мова з багатьма сучасними функціями, такими як качина типізація і метапрограмування, Ruby є досить надійною щоб підтримувати складні архітектури, і досить простою для виконання спеціальних задач.

Ruby поставляється в декількох різновидах, включаючи популярний JRuby. JRuby - це інтерпретатор Ruby, написаний на мові Java і може працювати у віртуальній машині Java(JVM). На відміну від офіційного Ruby, JRuby дозволяє викликати скрипти Ruby з коду Java, так само, як і викликати Java API з Ruby скриптів.

Android

Android був розроблений альянсом Open Handset Alliance, але найчастіше його сприймають, як проект Google. Сьогодні Android займає чверть ринку смартфонів, і його частка продовжує зростати.

Всередині Android працює на модифікованому ядрі Linux. Більшість додатків виконуються у віртуальній машині Dalvik, яку Google розробив з нуля для оптимальної роботи на мобільних пристроях.

Багато нових розробників Android пропускають те, що вихідний код Java, який вони пишуть не виконується як байт-код Java. Замість цього інструментарій Android перетворює байт-код Java в байт-код Dalvik. Ці перетворені файли, які мають розширення .dex, упаковуються в додаток, який ви розгортаєте на пристрій. До того часу як пристрій виконує вашу програму, там не залишається байт-коду Java.

Android + Ruby = Ruboto

Чарльз Наттер(Charles Nutter) один із розробників ядра JRuby мав прозріння: так як набір інструментів Android може конвертувати скомпільований Java-код у Dalvik файли, і тому що JRuby має інтерпретатор Ruby у скомпільованому байт-коді Java, то він повинен мати можливість запускати Ruby на Android. У дивно короткий час(прим. перекладача: йому це вдалося усього за годину), він виконав це завдання, і так народився Ruboto. Завдяки зусиллям кількох інших розробників, Ruboto став активним проектом, який стає все більш інтригуючим для Android і Ruby розробників.

Сьогодні, Ruboto поставляється в двох варіантах: ruboto-irb і ruboto-core. ruboto-irb це інтерактивна оболонка Ruby, яка працює на Android. Цей проект дозволяє запускати довільні скрипти Ruby, які можуть також отримати доступ до Android API. Цей інструмент може бути дуже корисним для розробників, які хочуть проводити тести або виконувати завдання на їхньому пристрої, але, ймовірно, не підходить для створення програмного забезпечення, яке необхідно пізніше поширювати.

У протиставлення, ruboto-core забезпечує фреймворк, який дозволяє створювати свої власні проекти Ruboto. Використовуючи ruboto-core, ви можете додати потужну та гнучку підтримку скриптів для вашого проекту, зберігаючи при цьому доступ до Android API. Малюнок нище показує процес збирання ruboto-core: автоматично згенеровані вихідні файли Java і ваші скрипти Ruby упаковані разом в пакет APK, який буде працювати на пристрої.

Решта цієї статті буде присвячена створенню Ruboto-проекту. Ruboto ще досить молоде програмне забезпечення; остання версія на момент написання цієї статті 0.0.2. Він продовжує активно розвиватися, і тому може вести себе трохи інакше на той час, коли ви читаєте цю статтю.

Прим. перекладача: напевно, потрібно відзначити що програма тестувалася і розроблялася на платформі Linux/Ubuntu і я не перевіряв її під іншими платформами і дистрибутивами, але повинно працювати.

Створення скрипту для SMS

Об'єднавши разом Ruby і Android дозволить створювати прості скрипти, які можуть отримувати доступ до потужних функцій Android. Ви будете писати скрипт Ruboto, який дозволяє користувачам замовляти морепродукти зі служби доставки. Цей простий додаток використовує сильні сторони кожної платформи. На стороні Android ви будете мати простий спосіб створення повідомлень SMS, що містить ваше замовлення; додаток розміщує замовлення, навіть не вимагаючи сервера. На стороні Ruby ви будете використовувати існуючу бібліотеку обробки, яка буде нормалізувати ваші замовлення в легкий для читання формат.

Розпочнемо!

Щоб побудувати і розгорнути Ruby скрипти на Android потрібно кілька компонентів. Можливо, деякі з них у вас уже встановленні; і якщо так, то ви можете використовувати вже існуючі інструменти.

Тому як Android і Ruby є мультиплатформними, ви можете запускати Ruboto на Linux, Mac OS X або Windows. У цій статті ви будете використовувати командний рядок.

Java

Вам знадобиться робочий Java Development Kit(JDK). Щоб перевірити чи він вже встановлений, введіть наступну команду:

$ javac -version
javac 1.6.0_20

Якщо ця команда знаходить версію JDK, ви встановлені. Якщо ні, встановіть останню версію, яку можна завантажити за посиланням.
В Ubuntu просто виконайте:

$ sudo apt-get install openjdk-6-jdk

Ant

Android поставляється з власною версією Ant, але Ruboto знадобиться доступ до Ant також із власних скриптів. Якщо у вас не встановлена автономна версії Ant, завантажте його за посиланням і розпакуйте в будь-який каталог. Знову ж таки, додайте його каталог з виконуваними файлами до PATH. Переконайтеся, що ви можете запустити команду Ant.
Для Ubuntu просто виконайте:

$ sudo apt-get install ant

Android

Перейдіть на Android Developer Site і встановіть Android SDK для вашої операційної системи. Після цього запустіть команду android, що знаходиться в директорії tool. Це запустить SDK менеджер, як показано на малюнку. Вам необхідно встановити наступні пакети, які перераховані у списку наявних пакетів(Available packages):

  • SDK Platform Android 2.2, API 8, revision 2
  • Android SDK Tools, revision 10
  • Android SDK Platform-tools, revision 3

Створіть образ Android для розробки, відкривши розділ Virtual devices у Android SDK and AVD Manager. Посилаючись до малюнку нище, створіть віртуальний пристрій з назвою Froyo, в полі Target виберіть Android 2.2 - API Level 8. Також ви можете створити віртуальну картку SD.

Додатки Ruboto працюватимуть на вашому пристрої, але розробка буде набагато простішою, якщо у вас є права на запис у довільні директорії, що потребують використання емулятора або root'ного пристрою. Далі в цій статті розглядається використання емулятора. Після завершення проекту, він буде однаково добре працювати і на пристрої Android під управлінням програмного забезпечення версії 2.2 або більш пізньої.

Додайте директорії platform-tools та tools до PATH:

$ PATH=~/android-sdk-linux_x86/tools:~/android-sdk-linux_x86/platform-tools/:$PATH
Тепер ви повинні мати можливість запускати наступні команди:
$ aapt version
Android Asset Packaging Tool, v0.2
$ adb version
Android Debug Bridge version 1.0.26

JRuby

JRuby пропонує неймовірно просту установка. Просто перейдіть за посиланням і дотримуйтесь інструкцій. Якщо необхідно, додайте директорію з виконуваними файлами до PATH. Переконайтеся, що установка завершилася успішно, ввівши наступну команду:

$ jruby -v
jruby 1.6.0 (ruby 1.8.7 patchlevel 330) (2011-03-15 f3b6154) (OpenJDK Client VM 1.6.0_22) [linux-i386-java]

Оскільки Ruboto розміщений на захищеному сервері, вам необхідно встановити jruby-openssl. Ви можете зробити це за допомогою наступної команди:

$ gem install jruby-openssl

Також необхідно встановити rake, еквівалент команд make або ant для Ruby. Введіть наступну команду:

$ gem install rake

Нарешті, настав час встановити власне сам Ruboto. Ruboto поставляється gem'ом, тому установка є простою. Введіть наступну команду:

$ gem install ruboto-core

Створення проекту Ruboto

Ruboto створює проект з нуля, що гарантує, що ваш маніфест налаштований правильно, скрипти розміщені в правильному зборі, і у вас є доступ до необхідних бібліотек. Ви повинні прийняти цей підхід, а не намагатися створити його самі або змінити існуючий проект.

Щоб створити проект, перейдіть в директорію проекту і введіть наступну команду:

$ ruboto gen app --package us.cirion.ruboto.demo --path fishmonger --name Fishmonger --target android-8 --activity Fishmonger

Ця команда виконує наступні дії:

  • gen app каже Ruboto створити новий проект Android з нуля.
  • --package надає унікальне ім'я пакету Android.
  • --path вказує Ruboto де зберігати проект; це повинно бути ім'я нової директорії.
  • --name назва додатку, яка буде відображатися на пристрої Android.
  • --target визначає версію Android для компіляції проекту. У цій статті, ви повинні використовувати android-8. Необов'язковий аргумент --min_sdk заявляє, що ваш додаток може працювати і на більш ранніх версій Android; пропускаємо його.
  • --activity це додатковий аргумент, який вказує Ruboto створити новий Android activity та ініціювати його.

Тут дозволю собі відійти від оригінальної статті. Для тих хто не знайомий з розробкою під Android можливо буде корисним. Activity представляє собою візуальний інтерфейс (окремий екран) для однієї дії, які користувач може зробити. Наприклад, додаток для обміну текстовими повідомленнями може мати одне activity для відображення списку контактів, інше - для написання повідомлення вибраному контакту, третє - для перегляду повідомлень і ще один для зміни налаштувань. Всі ці activity формують єдиний користувальницький інтерфейс, але не залежать один від одного. Кожне з них реалізовано у вигляді підкласу базового класу Activity.

Ви можете дослідити вміст директорії fishmonger. Вона містить всі автоматично згенеровані файли, необхідні для побудови та запуску основної Activity. Оскільки додаток буде відправляти SMS-повідомлення, ви повинні зробити одну зміну у файлі AndroidManifest.xml. Вставте наступний тег в якості першого дочірнього для елементу <manifest>:

<uses-permission android:name="android.permission.SEND_SMS" />

Якщо ви опустите цей дозвіл, ви все одно будете в змозі побудувати і завантажити скрипт, але ви отримаєте помилку часу виконання(run time error), коли програма намагатиметься відправити SMS повідомлення.

Запуск проекту

З коробки Ruboto генерує Activity і скрипт, який буде встановлюватися і запускатися на пристрої або емуляторі. Якщо ваш емулятор ще не запущений, ви можете зробити це за допомогою наступної команди:

$ emulator -avd Froyo

Зачекайте доки емулятор закінчить завантаження на головний екран. Для впевненості у тому, що всі Ruboto файли побудовані і розгорнуті належним чином, перейдіть у директорію fishmonger і виконайте наступну команду:

$ rake install

Якщо ви зіткнулися з помилкою, спробуйте запустити команду ще раз. Іноді час з'єднання обривається під час процесу збірки. Початкова побудова займає деякий час, але пізніше оновлення відбуваються швидше. Після завершення установки, подивіться на значок позначений Fishmonger в емуляторі. Запустіть його і зачекайте. На момент написання статті, Ruboto потрібен значний час для завантаження. Зрештою, ви побачите екран, схожий на малюнку нище.

Налаштування проекту

Тепер, давайте встановимо Fishmonger. По-перше, додамо підтримку природної мови. Ruby має відмінний gem, який називається linguistics, який пропонує безліч англійськомовних можливостей. На момент написання статті, Ruboto не обробляє вкладену структуру директорій бібліотеки linguistics, тому завантажте ZIP файл з цієї статті і розпакуйте вміст у fishmonger/assets/scripts. Це оброблений linguistics gem, із зміненою структурою директорій. У майбутньому, ви зможете лише зв'язувати gem з вашим скриптом ruboto.

Написання скрипта

Тепер ви готові перейти до змісту самого проекту. Фреймворк Ruboto бере на себе весь код Java і інфраструктуру Android, тому всі ваші дії будуть у файлі fishmonger.rb. Стріть вміст файлу. Ви почнете шляхом додавання наступного тексту.

require 'ruboto.rb'
require 'linguistics'
include Linguistics::EN

import "android.telephony.SmsManager"

ruboto_import_widgets :Button, :EditText, :LinearLayout,
  :RadioGroup, :RadioButton, :TextView

Перші два рядки завантажують Ruboto та бібліотеку linguistics. Наступна команда include зробить англійську граматику доступною у даному модулі.

Перший імпорт буде виглядати знайомим користувачам JRuby: ви додаєте підтримку для іншого класу. Відзначимо, що в цьому випадку, ви насправді використовуєте клас Android Dalvik, не частину стандартної бібліотеки Java. Ruboto буде використовувати відображення(reflection) під час виконання для завантаження цього класу і зробить його доступним для вас.

ruboto_import_widgets веде себе аналогічно. Тут ви додаєте декілька Android-специфічних графічних віджетів. Вони зазвичай використовуються в Android діяльності(activities), і Ruboto додає деякі зручні методи, які дозволяють більш легко налаштувати користувацький інтерфейс.

Далі, визначимо метод handle_create, як показано нище.

$activity.handle_create do |bundle|
  setTitle 'Freddy\'s Fresh Fish'

  setup_content do
    linear_layout :orientation => LinearLayout::VERTICAL do
      text_view :text => "What would you like to order?"
      @group = radio_group do
        radio_button :text => "Tuna", :id => 0
        radio_button :text => "Trout", :id=> 1
        radio_button :text => "Salmon", :id => 2
        radio_button :text => "Crab", :id => 3
        radio_button :text => "Lobster", :id => 4
      end
      @quantity = edit_text :hint => "Quantity"
      button :text => "Place Order"
    end
  end

handle_create викликається, коли користувач запускає додаток. В Android це там де ви обробляєте необхідні настройки. Стандартний Android додаток зазвичай використовують XML для визначення макету, але в Ruboto ви робите це в скрипті.

Знову ж таки, скористаємося функціями Ruboto, які є сполучною ланкою між вашим скриптом і Android. Незалежно від ваших знань Ruby або Android, ви повинні бути в змозі зрозуміти, що відбувається в setup_content. Ви створюєте вертикально орієнтований макет, який містить кілька віджетів один на одному. Це включає в себе текст(text_view), радіо-кнопки(radio_button) для вибору типу риби для замовлення, текстове поле(edit_text) для введення кількості, і кнопка(button) для розміщення замовлення. Для налаштування віджетів ви можете використовувати синтаксис Ruby, замість багатослівного синтаксису Java, що зазвичай використовується в Android.

Встановлення атрибуту id для кожного radio_button пізніше дає вам простий спосіб подивитися, яка кнопка була обрана.

Android буде автоматично обробляти всі взаємодії користувача з радіо-кнопками і текстовим полем.

  handle_click do |view|
    if view.text == "Place Order"
      count = @quantity.text
      food = @group.child_at(@group.checked_radio_button_id).text.downcase
      order = Linguistics::EN::plural(food,count)
      toast "Please send #{count} #{order}"
      SmsManager.default.send_text_message("4155551234", nil, "Please send #{count} #{order}", nil, nil)
      finish
    end
  end
end

Якщо ви раніше писали Android додатки, ви помітите, що використовуєте різні парадигми для обробки вибору. Android розробники, як правило, пишуть унікальні обробники кнопки вибору для кожного пункту. У Ruboto все ж простіше створити глобальний обробник натискань для Activity, і всередині нього перевіряти, на який елемент користувач натиснув.

Ви витягуєте кількість і тип риби, яку вибирає користувач. Якщо вони не виберуть радіо-кнопки, Ruboto викличе помилку часу виконання. В іншому випадку, текст буде переданий до бібліотеки linguistics, щоб створити відповідну форму іменника. Бібліотека може обробляти різні правила для плюралізації, тому він буде генерувати значення, як 1 salmon, 2 salmon, 1 crab, 2 crabs, і так далі. Він навіть визначає номери прописом, тому він також буде створювати фрази, як one lobster, three lobsters, і так далі. Вражаюче як для одного рядка коду. Це демонструє силу для ефективного використання існуючих скриптів, щоб легко додавати можливості для вашого додатку.

Більше того, відправлення SMS повідомлення вимагає лише однорядкове звернення до підходящого методу Android. Ruboto дозволяє використовувати Ruby-синтаксис для виклику цього методу; еквівалентний код на Java матиме такий вигляд:

SmsManager.getDefault().sendTextMessage()

Ви надаєте номер одержувача та текст повідомлення, і nil для необов'язкових параметрів. Якщо ви працюєте на пристрої, і хотіли би насправді відправити повідомлення, змініть номер телефону на діючий. Якщо ви хочете протестувати в емуляторі, ви можете замінити номер порту емулятора, такий як "5554".

Запуск скрипта

Один з найбільш сильних аспектів Ruboto є те, що ви можете змінити функціональність просто завантаживши оновлений скрипт. Навіть якщо ви повністю змінили поведінку додатку, вам не потрібно повторно збирати додаток або перезавантажувати APK. Замість цього введіть наступну команду в командному рядку:

$ rake update_scripts

Ця команда скопіює скрипти linguistics і ваш новий скрипт на емулятор або на підключений пристрій. Коли ви перезапустите додаток, ви побачите новий екран, як показано на малюнку нище.

Якщо ви працюєте на не root'нутому пристрої або вносили зміни у файли Java або маніфест, ви можете завантажити оновлення, повторно набравши команду rake install. Відзначимо, що навіть не root'нуті пристрої можуть оновлювати свої скрипти на льоту. Наприклад, ви можете завантажувати нові скрипти з інтернету або створювати їх під час виконання. Обмеження прошивки накладається тільки на надсилання файлів через USB.

Проведіть деякі маніпуляції з додатком. Після того як ви зробите правильний вибір і натиснете кнопку замовлення, екран автоматично закриється. Якщо ви використовуєте дійсну адресу одержувача, вони швидко побачать ваші повідомлення.

На фотографії нище можна побачити запус додатку Fishmonger на Samsung i5800 під управлінням програмного забезпечення Android версії 2.2.


Висновок

Ruboto молодий проект. Але навіть у його нинішньому стані він забезпечує дуже корисний і гнучкий спосіб написання і поширення програмного забезпечення для Android. Успішні результати Ruboto від сильних JRuby і Android. JRuby проробив важкий шлях по реалізації інтерпретатора Ruby на мові Java. А набір інструментів для Android забезпечує перетворення стандартного байт-коду Java в байт-код Dalvik.

Як ви бачили, Ruboto скрипти можуть бути дуже короткими, і в той жу час пропонувати сильні можливості Ruby і Android. Здатність змішувати і поєднувати Ruby скрипти, Ruby та Java синтаксис, і Android API дає багато можливостей для підвищення продуктивності.

Ruboto є переконливим мостом для розробників по обидві сторони кордону клієнт-сервер. Android розробники по достоїнству оцінять його силу, яка дає їм можливість для оновлення можливостей програми "на льоту". Розробники Ruby отримали досить безболісний спосіб привести свій досвіду на мобільну платформу і можуть використовувати існуючий код Ruby для створення нових додатків. Обидва табори з великим інтересом будуть стежити за подальшим розвитком цього проекту.

Ресурси

Немає коментарів: