понедельник, 15 октября 2012 г.

Пишем приложение для Android в Appcelerator (Titanium Studio)

Небольшой tutorial "как писать приложения под Android" от человека, который под телефоны никогда ничего не писал, Java не знает и вообще PHP-разработчик.

PHP-разработчики не всегда знают Java, зато они все должны знать JavaScript. Есть такая штука, Titanium Studio, позволяет писать мобильные приложения на JavaScript. Она еще и бесплатная. Какая удача!


Установка

Первым делом качаем Titanium отсюда http://www.appcelerator.com/ (придется зарегистрироваться и желательно с честным аккаунтом).
Скачанный архив разворачиваем где нибудь, там уже все готово к запуску, запускаем бинарник ./Titanium_Studio/TitaniumStudio. Будет задан вопрос, где держать рабочие проекты (workspace), по-умолчанию в хомяке, ну и пусть. Открывается студия, при первом запуске она сама начнет докачивать mobile SDK. Видим вкладку Dashboard и под "Configure Native SDK" кнопку Android, жмем ее и "Install or Update Android SDK".
Далее все просто, выбрать папку установки и начнется процесс. По окончании откроется SDK Manager, где нужно выбрать версии Android, под которые планируется писать. Я ставил Android 2.2, 2.3 и 4.0.3. Также нужно выбрать Android SDK Tools. Студия работает минимум с Android 2.2, так что ставить придется версии не ниже этой.
После нажатия "Install N packages" пойдет процесс установки, во время которого может выскакивать окно с предложением ввести какие-то данные для авторизации где-то, хз что это, можно отменять их, просто соответствующие пакеты не будут установлены.

Создание проекта

Create project -> Titanium Mobile Project -> Tabbed Application (например)
Project name: test
AppID: com.appcelerator.test
Finish.

Взору предстает куча файлов. Фактически нас интересует папка Resources. Разбираем, что есть что.
app.js - "точка входа", основной файл приложения. Hello world можно написать прямо в нем и на этом закончить :). При создании проекта этот файл содержит некий мультиплатформенный скелет, который пытается определить, приложение запущено на планшете или на телефоне и подгружает соответствующий файл ApplicationWindow (тоже что-то вроде функции main()).
В папке ui будет храниться весь код.
Наш tabbed-пример загружает ui/handheld/ApplicationWindow, где определяется, какой тип окон (вкладок) будет использоваться в приложении. Также загружает ui/common/ApplicationTabGroup, это собственно основное окно (контейнер вкладок), которое будет видно.

Уже можно нажать Ctrl+F11 и посмотреть, как выглядит тестовый пример в эмуляторе.

Пример создания приложения в titanium

Вот API http://docs.appcelerator.com/titanium/2.1/index.html#!/api. Довольное богатое, надо сказать.
Поставим приложению несколько задач:
 1. различать свернутое состояние (фоновая работа) от развернутого
 2. выводить уведомления из фонового режима
 3. хранить состояние между перезапусками
 4. обращаться к серверу за данными


Для начала определимся, где будем писать код. Вся движуха происходит в файле ui/common/ApplicationTabGroup.js. Там создается нужное число вкладок, рисуется интерфейс, настраиваются события и т.д.
Очистим функцию ApplicationTabGroup от всего лишнего и приведем к такому виду:

function ApplicationTabGroup() {
//create module instance
var self = Ti.UI.createTabGroup();
//create app tabs
var win1 = Ti.UI.createWindow({ url: 'ui/tab1.js' }),
win2 = Ti.UI.createWindow({ url: 'ui/tab2.js' });
var tab1 = Ti.UI.createTab({
title: L('home'),
icon: '/images/KS_nav_ui.png',
window: win1
});
win1.containingTab = tab1;
var tab2 = Ti.UI.createTab({
title: L('settings'),
icon: '/images/KS_nav_views.png',
window: win2
});
win2.containingTab = tab2;
self.addTab(tab1);
self.addTab(tab2);
return self;
};

т.е. остались все те же 2 вкладки, но окна теперь создаются файлами ui/tab1.js и ui/tab2.js. Для теста можно в них поместить alert('tab1'); и alert('tab2');. Заметим, что алерты срабатывают 1 раз при первой активации вкладки.

1. Фоновое состояние

Попробуем научить приложение различать свернутое состояние от развернутого.
Для этого добавим в функцию ApplicationTabGroup() следующий код (код довольно дерьмовый, зато работаем по-взрослому, через события!):

// при сворачивании приложения срабатывает только blur текущей вкладки, blur tabGroup не срабатывает
win1.addEventListener('blur', function () { Ti.App.fireEvent('app_backgrounded', {r: true}); });
win2.addEventListener('blur', function () { Ti.App.fireEvent('app_backgrounded', {r: true}); });
// при разворачивании срабатывает focus вкладки, focus tabGroup не срабатывает
win1.addEventListener('focus', function () { Ti.App.fireEvent('app_backgrounded', {r: false}); });
win2.addEventListener('focus', function () { Ti.App.fireEvent('app_backgrounded', {r: false}); });
// фокус от tabGroup идет последним событием при переключении вкладок, поэтому означает bg=false
self.addEventListener('focus', function () { Ti.App.fireEvent('app_backgrounded', {r: false}); });

имя события, кстати, можно придумать любое, и параметры тоже передать какие угодно.
А ловить событие будем в tab2.js, используя такой код:

var win = Ti.UI.currentWindow;
Ti.App.addEventListener('app_backgrounded', function (e) {
win.isBackgrounded = e.r;
Ti.API.info(e.r ? 'Backgrounded' : 'Unbackgrounded');
});
Запускаем по Ctrl+F11, смотрим в консоль, кликаем по вкладкам, сворачиваем, разворачиваем, последнее сообщение всегда соответствует состоянию приложения. SOLVED!

2. Уведомления из фонового режима

Раз уж у нас состояние мониторится только во вкладке tab2, то и уведомления будем слать оттуда же, т.е. сейчас правим файл tab2.js. Создадим некую фейковую активность - с интервалом в секунду будем обновлять текст в окне, но если работаем в фоне - то и уведомление посылать.
Вот эта замечательная функция позволяет послать уведомление из фонового режима и при клике на нему развернуть свернутое Android-приложение.
function sendNotification() {
var intent = Ti.Android.createIntent({
action: Ti.Android.ACTION_MAIN,
   flags : Ti.Android.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Ti.Android.FLAG_ACTIVITY_SINGLE_TOP,
   className : 'com.appcelerator.test.TestActivity',
});
intent.addCategory(Ti.Android.CATEGORY_LAUNCHER);
// Create a PendingIntent to tie together the Activity and Intent
var pending = Ti.Android.createPendingIntent({
activity: Ti.Android.currentActivity,
   intent: intent,
   type: Titanium.Android.PENDING_INTENT_FOR_ACTIVITY,
   flags: Titanium.Android.FLAG_UPDATE_CURRENT
});
// make notification
var note1 = Ti.Android.createNotification({
contentIntent: pending,
contentTitle: 'New message',
tickerText: 'You have new message',
contentText: 'You have new message(s) in background',
});
Ti.Android.NotificationManager.notify(1, note1);
}

А тестовую активность будет генерировать такой код

var label = Ti.UI.createLabel({
text: 'Random: -',
top: 0
});
win.add(label);
setInterval(function() {
var rand = Math.random();
if (rand > 0.2) {
return;
}
label.text = 'Random: ' + rand;
if (win.isBackgrounded) {
sendNotification();
Ti.API.info('message in background mode');
}
}, 1000);

Запускаем, палим консоль, получаем уведомления, разворачиваем приложение, все работает. SOLVED


3. Храним состояние между перезапусками

Тут все настолько просто, что и писать много не буду. В API есть такая штука как Ti.App.Properties, например если нужно хранить число запусков приложения, тогда пишем где нибудь:

var counter = Ti.App.Properties.getInt('counter');
counter++;
Ti.App.Properties.setInt('counter', counter);


4. Обращения к серверу


тоже ничего сложного, это знакомо любому, кто юзал jQuery
var url = "http://ya.ru/";
var client = Ti.Network.createHTTPClient({
// function called when the response data is available
onload : function(e) {
alert(this.responseText);
},
// function called when an error occurs, including a timeout
onerror : function(e) {
alert(e.error);
},
timeout: 1000  // in milliseconds
});
client.open("GET", url);
client.send(); 

ну и напоследок - в документации можно найти дохрена фич, и описаны они очень хорошо.

Есть вики - https://wiki.appcelerator.org (не пользовался).



Комментариев нет:

Отправить комментарий