Появилась у меня как-то идея(или расcчётка по мобильным платформам) написать приложения под android на своём любимом ruby. И тут я вспомнил про проект который несколько раз упоминался в RubyNoName подкасте, собственно речь пойдёт о Ruboto.
Ну что ж приступим. Для программирования нам понадобится:
- JDK
- Android SDK
- JRuby
- Gem Ruboto
Расписывать установку я не стану, лучше приведу ссылку на достаточно подробную документацию
После того как всё установили генерируем основу нашего приложения.
ruboto gen app --package ru.nitrodev.demo_app
Переходим в директорию demo_app
и любуемся заботливо подготовленной структурой приложения. В папке src
уже лежит наше первое активити, собственно к нему мы и перейдём.
В качестве примера разберу такие базовые вещи как:
- Создание интерфейса
- Воспроизведение аудио с помощью MediaPlayer
- Создание активити
- Определение координат касания экрана
- Работа с Intent (открытие страницы, набор номера)
- Создание меню
Пойдём по порядку.
Создание интерфейса
В любом приложении нам понадобится интерфейс, мы можем использовать стандартный способ создания интерфейса с помощью XML ресурса, но тогда мы теряем всю гибкость ruby. Поэтому интерфейс будем описывать в коде, для этого мы можем вызывать Android API или использовать ruboto/widget.rb
который является обвёрткой над API и предоставляет простой DSL для создания интерфейса.
Рассмотрим сначала первый способ на примере создания LinearLayout содержащего одно текстовое поле и 4 кнопки.
Первым делом импортируем нужные компоненты интерфейса
java_import "android.widget.Button"
java_import "android.widget.TextView"
java_import "android.widget.LinearLayout"
Описываем сам интерфейс
ll = LinearLayout.new(@ruboto_java_instance)
ll.orientation = LinearLayout::VERTICAL
tv = TextView.new(@ruboto_java_instance)
tv.text = "Прощай Java"
ll.add_view tv #Добавляем наще TextView в LinearLayout
params = tv.get_layout_params
params.width = ViewGroup::LayoutParams::MATCH_PARENT
btn1 = Button.new(@ruboto_java_instance)
btn1.text = "Play"
btn1.on_click_listener = proc{ Play }
ll.add_view btn1
params = search_b.get_layout_params
params.width = ViewGroup::LayoutParams::MATCH_PARENT
btn2 = Button.new(@ruboto_java_instance)
btn2.text = "Pause"
btn2.on_click_listener = proc{ Pause }
ll.add_view btn2
params = search_b.get_layout_params
params.width = ViewGroup::LayoutParams::MATCH_PARENT
btn3 = Button.new(@ruboto_java_instance)
btn3.text = "Второй экран"
btn3.on_click_listener = proc{ twoActivity }
ll.add_view btn3
params = search_b.get_layout_params
params.width = ViewGroup::LayoutParams::MATCH_PARENT
btn4 = Button.new(@ruboto_java_instance)
btn4.text = "Третий экран"
btn4.on_click_listener = proc{ threeActivity }
ll.add_view btn4
params = search_b.get_layout_params
params.width = ViewGroup::LayoutParams::MATCH_PARENT
setContentView ll
Вы должны признать что данный код является таким же громоздким как java и вряд ли кому-то понравится в ruby сообществе. Более элегантным будет использовать DSL Ruboto. Рассмотрим аналогичный код использующий путь Ruboto.
ruboto_import_widgets :Button, :LinearLayout, :TextView
self.content_view =
linear_layout :orientation => :vertical do
text_view :text => 'Только Ruby - только хардкор', :width => :match_parent
button :text => 'Play', :width => :match_parent, :on_click_listener => proc { play }
button :text => 'Pause', :width => :match_parent, :on_click_listener => proc { pause }
button :text => 'Второй эран', :width => :match_parent, :on_click_listener => proc { twoActivity }
button :text => 'Третий эран', :width => :match_parent, :on_click_listener => proc { threeActivity }
end
Как видно колличество кода сократилось в 4-5 раз.
Результат этого кода
Воспроизведение аудио с помощью MediaPlayer
Для воспроизведения звука импортируем MediaPlayer и AudioManager
java_import "android.media.MediaPlayer"
java_import "android.media.AudioManager"
java_import "android.net.Uri"
Затем получаем uri файла и создаём MediaPlayer
java_file = java.io.File.new("/mnt/sdcard/naive.mp3")
uri = Uri.fromFile(java_file)
@player = MediaPlayer.create(self, uri);
Работать с нашим плеером можем стандартными функциями
@player.start
@player.pause
Создание активити
Остальные пункты нашего манула создадим в отдельных активити.
Основным способом создания RubotoActivity является использование start_ruboto_activity
.
start_ruboto_activity
— это эквивалент Android startActivity в Ruboto. Он имеет два обязательных параметр: строка содержащая глобальную ссылку на создаваемую активити и блок который будет выполняться один раз при создании активити.
Создадим вторую активити
start_ruboto_activity("$activity_two") do
def on_create(bundle)
super
setTitle 'Вторая активити'
end
end
Определение координат касания экрана
Отслеживание касания осуществляется с помощью функции on_touch_event данный метод является эквивалентом андроид метода onTouchEvent
Отслеживаем касание одним пальцем
def on_touch_event(event)
index = event.find_pointer_index(0)
x = event.getX(index)
y = event.getY(index)
toast "Position: #{x}, #{y}"
true
end
Работа с Intent
Для работы с Intent импортируем соответствующие Android API
java_import "android.content.Intent"
Дальнейшая работа с Intent производится аналогично java
intent = Intent.new(Intent::ACTION_CALL)
intent.setData(Uri.parse("tel:5551234"))
startActivity(intent)
intent = Intent.new(Intent::ACTION_VIEW)
intent.setData(Uri.parse("http://ruboto.org/"))
startActivity(intent)
Добавим соответствующие разрешения в AndroidManifest
<uses-permission android:name="android.permission.CALL_PHONE" />
Создание меню
Для работы с меню используется стандартный коллбек on_create_options_menu
. Тут всё просто: создаём пункты меню и вешаем на них слушателя, при клике в toast
будет выводиться сообщение с названием пункта меню.
def on_create_options_menu(menu)
m1 = menu.add('Action 1')
m1.set_on_menu_item_click_listener do |menu_item|
@text_view.text = menu_item_title
toast menu_item.title
true
end
m2 = menu.add('Action 2')
m2.set_on_menu_item_click_listener do |menu_item|
@text_view.text = menu_item.title
toast menu_item.title
true
end
true
end
Вот собственно и всё.
Весь данный код можно посмотреть на github
Ссылки для более глубокого погружения в Ruboto:
Wiki: github.com/ruboto/ruboto/wiki
Readme: github.com/ruboto/ruboto/blob/master/README.md
Отличная презентация с примерами: jay.mcgavren.com/files/presentations/ruboto/
Автор: Nitrino