Pull to refresh

Как я становился разработчиком приложений для vkontakte.ru

Reading time 12 min
Views 2.2K
Чуть более месяца назад, я решил, что разработка приложений для контакта вполне может стать прибыльным делом, а прибыльное дело это как раз то, что мне надо. Никаких познаний в Action Script у меня на тот момент небыло. Так что я фактически начинал с нуля и решил задокументировать процесс. Надеюсь это кому-нибудь поможет. По мере возможностей, буду продолжать делиться своим опытом в этом блоге. Ниже мои записи точно в том виде, в каком я заносил их в evernote.

15.05.2009


Начался 11 день с момента, когда я решил стать разработчиком приложения для vkontakte.ru. Ровно 11 дней назад я скачал и впервые запустил Flex 3 Builder. По хорошему именно тогда и надо было начинать вести блог, ведь первые шаги самые трудные. С другой стороны, первые шаги идут до сих пор и самое интересное ещё впереди.

Немного предыстории.

Экономический кризис никогда меня особо не волновал и не волнует до сих пор, потому что я никогда не боялся, что окажусь в безвыходной ситуации. Тем не менее, надо признать, что я слишком расслабился и кризис привел к тому, что мои доходы стали настолько скудными и непостоянными, что мне пришлось искать новые пути для зарабатывания денег. В качетве нового пути была выбрана разработка приложений для vkontakte.ru.

Причин для этого было несколько:

1. Большой потенциал и много незанятых ниш.
2. Масса идей.
3. Простота раскрутки и монетизации готовых приложений.

Я не стал откладывать это дело в долгий ящик (что, вообще-то, очень удивительно, потому что в мой «долгий ящик» уже отложенно столько, что его размер вполне сопоставим с размером какой-нибудь «долгой Венеры») и установил себе Flex 3 Builder. В первый же день, я прошел простейший туториал, который позволил вводить слова в текстовое поле и в ответ получать картинки с Flickr. Это показалось очень легко, но пока что не проясняло как мне получить какие-нибудь данные от API вконтакте. Помыкавшись туда сюда, я решил пройти все оставшиеся туториалы из раздела Getting started. Через пару дней у меня появилось ощущение, что теперь я знаю гораздо больше, чем раньше, но никак не мог понять что конкретно я знаю и как это можно использовать для моей основной цели.

С этого момента я решил искать информацию только по тем вопросам, которые помогут мне решить текущие шаги в создании приложения. Первым своим приложением я решил сделать плеер музыки. Вконтакте уже было штук 6 плееров с разной функциональностью, но я хотел свой, причем такой, чтобы все остальные плееры показались чем-то вроде windows media player classic по сравнению с моим.

Первой целью стало получить и вывести полноценный ответ от API Вконтакте. Сначала я забронировал место под собсветнное приложение, полчил соответствующий api_id и секретный код. Дальше надо было из всего этого составить полноценный запрос, главной трудностью было составление подписи с помощью md5. Тут мне очень помогло приложение «Тестовое приложение» (http://vkontakte.ru/app35569_1933734) с его помощью я смог составить запрос и получить список своих друзей. Теперь надо было отправить такой же запрос из собственного приложения. Для начала мне надо было как-то подключить шифрование md5. Для этого я использовал бесплатную библиотеку «crypto», после некоторых манипуляций я понял, как её правильно импортировать, а так же как вызвать нужную функцию, получить результат и вывести его. Здесь я впервые ощутил, что прогресс есть и это наполнило меня гордостью (которую я потом испытывал периодически и которой подпитывался). Дальше я составил запрос с помощью <mx:HTTPService> и, о чудо, получил список своих друзей.

Следующей целью стало проиграть любой аудио файл со свой страницы вконтакте. Для начала я научился с помощью запроса получать полный список моих аудио записей в формате XML. Теперь с ним надо было что-то делать.Сначала я прочитал секцию working with sound из Flex 3 Developer Guide, в теории всё опять показалось простым, но писать необходимые функции самомстоятельно не хотелось (да и знаний на это не хватало), поэтому я занялся поисками готовых flash mp3 player'ов, нашел несколько штук, долго с ними возился, опять же получил кое-какие новые знания, но так и не смог заставить их работать так, как мне надо было. Пришлось вернуться к working with sound из Flex 3 Developer Guide и тщательно изучить приведенный там пример. Из примера стало ясно, что своей цели я могу добиться через, использованную в примере, библиотеку (или что-то вроде того) SoundFocade, но сначала надо было научиться выделять нужные параметры из xml ответа со списком моих записей вконтакте. Пришлось на время отложить SoundFocade и заняться изучением xml, способам обращения к отдельным элементам xml объекта, работе со списками <mx:list>, а так с такими вещами, как Collections и dataProvider. Именно этим я занимался сегодня, 15 мая. В результате я сделал простенький интерфейс плеера и, при помощи кнопки Request tracklist смог получить список песен со своей страницы. Выглядело это так:

image

Ну вот, предыстория закончилась и теперь я могу вести блог в реальном времени. Текущая задача, добавить какое-нибудь текстовое поле и вывести туда URL выбранного трека. Пойду налью чая и почитаю справку по <mx:list>.

Даже чай не успел налить. Задача решилась элементарно, через itemClick event. В моём случае itemClick=«showURL(event)». Гораздо интереснее конструкция
event.currentTarget.selectedItem.url, с ней надо будет разобраться подробнее, особенно с currentTarget.

Ну что ж, теперь начинаются интересные штуки. Вся информация о треках у меня есть, теперь надо заставить всё это играть. Let the music play.

Готово! Всё оказалось очень просто. Выдернул нужные функции из SoundPlayer, удалил всё лишнее (не то чтобы совсем лишнее, но то без чего можно обойтись в простейшей версии). Итак, достигнута одна из важнейших промежуточных целей, мне удалось загрузить полный список песен со своей страницы и проиграть любую из них. Пора ставить новые цели.

Следующие цели:

Сделать плеер полнофунциональным.

— кнопка пауза
— трек вперед
— трек назад
— полоса прокрутки
— индикатор загрузки
— громкость
— перемешивание
— зацикливание всего плей листа
— зацикливание одной песни
— вывод текущего исполнителя и песни
— время проигрывания трека

Глобальные цели:

— Добавить в плеер запросы к API last.fm
— Сделать взаимодействие с базой данных
— Добавить перетаскивание элементов списка и сохранение этого всего
— Ваши друзья часто слушают
— Похожие вкусы вконтакте

— Кнопку пауза было сделать очень просто.
Во-первых с помощью add и remove eventListenter сделал, чтобы пауза и возобновление находились на одной кнопке. Потом полез в SoundFacade, там почему-то было сделано, что паузу можно нажать только после полной загрузки песни, быстренько добавил свою функцию:
public function pausePlayback(pos:int = 0):void
{
this.pausePosition = pos;
this.sc.stop();
this.playTimer.stop();
this.isPlaying = false;
}

И всё прекрасно заработало.

Теперь надо сделать полосу прокрутки. Сначала получилось сделать progressBar, который показывал какая часть песни уже проигралась и сколько осталось, но проблема в том, что его нельзя менять, т.е. нельзя перемотать песню, а кроме того, хотелось бы, чтобы процент загрузки отображался на том же progressBar'е, каким-нибудь бледным цветом. В общем, после некоторых поисков я вспомнил, что в английском языке это называется seek bar и быстро нашел
Flex 3 Cookbook: Chapter 8, Images, Bitmaps, Videos, Sounds, в которой как раз рассматривается этот вопрос. Будем изучать.
Так, вместо progressBar явно надо использовать HSlider. Начал я с этого:
public function onPlayProgress(evt:ProgressEvent):void
{
var playbackPercent:uint = 100 * (evt.bytesLoaded / evt.bytesTotal);
pbSlider.value = playbackPercent;
}
Слайдер исправно движется вслед за музыкой, теперь надо сделать, чтобы музыка двигалась вслед за ним.

Методом проб и ошибок добился нужного результата, музыку можно перематывать. Теперь надо как-то совместить перемотку и индикатор загруженности трека. Кроме того натолкнулся на неожиданное препятствие: если проигрывать трек, который уже полностью в кеше, то не получается переключиться на какой-нибудь другой. Есть подозрение, что проблема в методе .close(), который пытается закрыть не существующее соединение. Ура! Как и ожидалось, проблема была в .close(), только искал я его не в том месте, оказывается первое обращение к .close() было ещё раньше. Правда теперь индикатор загрузки начал вести себя как-то странно, но это ерунда, по сравнению с предыдущей проблемой. Сейчас плеер выглядит так:

image

В общем, программа максимум на сегодня даже перевыполнена. Уже час ночи, можно ложиться спать.

16.05.09



Сегодня суббота и можно было бы отдохнуть, но не терпится продолжить проект. Программа максимум на сегодня такова:

— починить индикатор загрузки
— громкость
— трек вперед
— трек назад
— зацикливание одной песни
— вывод текущего исполнителя и песни
— время проигрывания трека

Проблема индикатором загрузки успешно решилась. Проблема была в том, что я переборщил с методом .close(), и соединение с недогруженными треками вообще перестало закрываться, в результате this.s.addEventListener(flash.events.ProgressEvent.PROGRESS, onLoadProgress); стал обрабатывать сразу несколько потоков и соответственно поочередно выводить прогресс каждого в один и тот же progressBar. Эта проблема решена, теперь я заметил, что при моем соединении некоторые «тяжелые треки» не успевают подгрузиться и я получаю нервирующее заикание. Так что надо увеличить buffer time.

bufferTime почему-то не реагирует на мои дейстия, но возможно это потому что надо чтобы приложение уже было загружено на сервер контакта, пока что не буду на этом заморачиваться.

Переходим к громкости.



С громкостью особых проблем небыло, подключаем flash.media.soundtransform, создаем новые объект, передаем ему значение volumeSlider, если оно изменилось.
Меня начинает беспокоить, плохая структурированность проекта, всё напихано в разнобой. После завершения работ над всеми функциями плеера, возьмусь за дизайн, рефакторинг и оптимизацию кода.

Теперь кнопки вперед-назад.
Как и следовало ожидать, с кнопками проблем не возникло, вот такая функция и всё в порядке:
trackList.selectedIndex=trackList.selectedIndex+1;
var newUrl:String = trackList.selectedItem.url;
pbSlider.value=0;
load(newUrl);

Зацикливание одной песни

Опять без проблем, вот такой комбинацией:

this.s.addEventListener(flash.events.Event.SOUND_COMPLETE, onPlayComplete);
public function onPlayComplete(evt:Event):void
{
if(repeatTrack.selected==true) this.s.play();
}

Надо доделать «вывод текущего исполнителя и песни» и «время проигрывания трека», а потом исправить проблему с громкостью, при перемотке громкость возвращается в изначальное состояние.

17.05.09


К сожалению, вчера отвлекся на евро видение и не довлел запланированное до конца.

18.05.09



17 мая хотел поработать несмотря на выходной, но всё таки пришлось отдыхать. Позвонил друг с утра, думал погулять часа два-три, в результате пришел домой ближе к ночи, может и к лучшему, а то я на самом деле начинал терять контакт с людьми, всю неделю провел дома, ни с кем толком не общался.

Ладно, сегодня надо сделать следующее:

Вывод текущего исполнителя и песни
Подправить вывод треков в плей листе
Вывод времени проигрывания трека
Исправить проблему с громкостью
Перемешивание
Зацикливание всего плей листа
Громкость исправил. Опять появилась пробелема с незакрытым соединением, на этот раз с паузой. Буду решать.
Проблема решена.

Все остальные вопросы я тоже решил, никаких особенных ситуаций не возникало, так что описывать нет смысла. На завтра оставил только перемещивание плей листа, после того, как будет готово перемешивание, можно будет приступать к чистке кода, дизайну плеера и тому подобным вещам, т.е. буду приводить плеер в товарный вид.

19.05.09



На сегодня из обязательных дел только перемешивание плейлиста. Дальше начну работу по полировке плеера. Для перемешивания, скорее всего, надо будет использовать массив из номеров треков, перемешанных случайным образом. Как всегда лезем в google и ищем «flex 3 array random» и «flex 3 array shuffle»
Скорее всего подойдет вот этот код:

package com.interactiveSection.utils{
public class RandomArray{
public function RandomArray():void{};
public static function generateRdmArray(numElements:int, origArray:Array=null):Array{
if (origArray==null || numElements>origArray.length) {
origArray = (origArray==null)? new Array():origArray;
for (var i:int = origArray.length; numElements>i; i++){
origArray.push(i);
}
}
//
var tempArray:Array = new Array();
tempArray = origArray.slice();
var resultArray:Array = new Array();
while (tempArray.length>0 && numElements>resultArray.length){
var rdm:int = Math.floor(Math.random()*tempArray.length);
resultArray.push(tempArray[rdm]);
tempArray.splice(rdm,1);
}
trace(«returning generated array: „+resultArray);
return resultArray;
}
}
}

Удивительно, но проигрывание случайного трека заработало с первого раза, видимо понемножечку я начинаю понимать, что к чему во Flex и ActionScript.

Итак, у меня есть полноценный плеер со следующими функциями:
— Вывод плей листа
— Проигрывание, стоп, пауза
— Перемотка
— Громкость
— трек вперед, трек назад
— Зацикливание трека или всего плей листа
— Вывод исполнителя и названия песни
— Вывод полного времени трека и времени текущего проигрывания

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

Проработку мелочей я начал с настройки отображения названий песен и исполнителей. Проблема была в том, что если в песне встречались спец симоволы, вроде ' или &, то они дважды экранировались и из & получалось, что-то вроде &amp$#39;, в результате на месте ', я получал какие-то коды. Сначала я думал, что должна быть какая-то простая функция вроде decode или unescape, такие функции на самом деле нашлись, но на мой случай их действие не распространялось. Я долго искал простой способ, но в конце концов решил делать всё это через .replace и регуряные выражения. К счастью, перед этим я успел запостить свою проблему везде, где угодно и в том, числе написал в контакте Ростиславу Сирык. Ростислав мне очень помог, предложив способ через htmlText в ItemRenderer. Большое ему спасибо за ценный совет, параллельно я узнал ещё много полезного.

Сейчас в некотором затруднении, как именно мне чистить код. По всей видимости надо делать собственные компоненты и выносить as код в отдельные файлы. Вопрос в том, как это лучше организовать. Пожалуй начну с создания собственных компонентов, со временем плеер наверняка надо будет отделять от основного приложения.

20.05.09



Не сделал вообще ничего. Стыд мне и позор.

21.05.09


Ещё позор

22.05.09


Ещё

23.05.09


Сегодня я всё таки взялся за ум. Перед тем, как чистить код, я решил почитать документацию и примеры приложений, чтобы был какой-то пример “как правильно».
Для начала составлю список того, что надо чистить:
1. Передача списка песен через Collection, а не просто XML.
В общем, оставшееся время я читал «Getting started with flex 3»

24.05.09



Начал чтение учебника по AS «Action Script 3.0 Essential». Прочитал 180 страниц, в принципе из учебника мне понадобится ещё страниц 400-500, на этой неделе должен прочитать до конца. Думаю это даст большой рывок в понимании, как всё устроено и куда двигаться дальше. После этой книги прочитаю руководство по созданию собственных компонентов, думаю это тоже необходимый шаг, перед дальнейшей разработкой.

25.05.09



Продолжаю читать учебник «Action Script 3.0 Essential». Дополнительно скачал «Application Architecture Guide 2.0» patterns & practices.

Прочитал всю основную информацию из «Action Script 3.0 Essential», многое стало в разы понятнее. Начал читать «Creating and extending adobe flex 3 components», информации много, но читать её всю на английском будет долговато, так что ограничусь пока что главой 7 «Chapter 7: Advanced MXML Components» думаю, там будет вся нужная информация по созданию собственных компонентов. На сегодня всё.

26.05.09



Прочитал про создание собственных компонентов, основую суть понял, если что буду обращаться к документации. Создал новый проект в Flex 3 Builder, в котором буду делать более чистую версию плеера, уже разнесенную по компонентам, классам, модулям и т. п., заодно буду и дизайн приделывать.

6.06.09



Целых 11 дней я ничего не записывал, но при этом с головой был погружен в работу. Настолько погружен, что даже всё сделал, хотя в последние дни приходилось работать буквально ночи напролет, чтобы успеть завершить плеер ровно через месяц после установки Flex 3 Builder. В общем, просто в кратце опишу с какими вопросами я сталкивался в эти 11 дней. Сначала я создал новый проект, в этот раз я не стал писать весь код прямо в основном файле, а отвел ему роль «контейнера» для отдельных модулей. Элементы я решил разместить так: сверху шапка и горизонтальное меню (которого пока что нет, но планируется в будущем), под шапкой две колонки: в левой колонке плеер, а в правой всякая дополнительная информация. Разметив основной файл, я принялся за создание компонента с плеером. File -> New -> MXML Component. Так как код уже был написан (хотя и в черновом варианте), то начал я с дизайна. Дизайн я решил сделать серым, минималистичным и «под метал», такой выбор был сделан потому что тратить много времени на насыщенный дизайн я не мог, а серый и минималистичный, хотя и не вызовет восторга, но и отторжения тоже (надеюсь). Открыл Fireworks MX, сделал фон. Сверху нужна была бегущая строка с названием песни, и я в очередной раз полез в Google за соответствующим примером. Искал по словам «scrolling text», нашел много всякой ерунды, пока не оказалось, что гораздо лучше нужный результат описывается словом marque. «Flex marque» в гугле дал гораздо более полезные результаты, которые я легко приспособил под свои нужды. Со строкой готово. Чуть ниже должена размещаться полоса прокрутки. Это было уже сложнее. Во-первых стандартная полоса и ползунок мне не нравились, а во-вторых мне каким-то образом нужно было отображать процесс загрузки музыкального файла на этой полосе. Опять google, опять поиски. В конце концов, я сделал полосу прокрутки невидимой, оставив только ползунок и разместил её поверх компонента Progress Bar, который изображал полосу прокрутки, хотя на самом деле ей не являлся, но отлично показывал процесс загрузки. Сам ползунок я переделал при помощи свойства thumbSkin. C этим решил, дальше надо было сделать показ времени проигрывания. Тут ничего сложного, TextArea + embedded font. Дальше опять сложности, необходимо сделать визуализацию. Тут я застрял надолго, просмотрел кучу исходников, пока не наткнулся на подходящий компонент, слегка его настроил, вставил в плеер, и к моему удивлению он заработал. Я был очень рад. Потом шли всяческие кнопки и громкость, ничего сложного небыло, подробно описывать смысла нет. После кнопок надо было сделать ComboBox (выпадающий список) со всеми друзьями пользователя. Сам ComboBox было сделать легко, заполнить его тоже легко. Вот с отображением надписей в списке была проблема, опять надо было использовать htmlText для отображения спецсимволов, некоторый опыт у меня уже был, так что я быстренько добавил комбинацию из ItemRenederer и Label, спецсимволы стали отображаться, но вот в качестве выбранного пункта постоянно отображалась надпись . Я долго, долго бился с этой проблемой, так и не понял в чем её причина и, наконец, в лучших традициях быдло кодинга просто закрыл надпись на выбранном пункте с помощью canvas, а в canvas поместил Label и присваивал ему тексты выбранного пункта. Наврядли, это лучшее решение, но иначе у меня не получилось. Потом добавил DataGrid для плейлиста и с дизайном было готово. Программная часть для плеера уже была готова, я её просто причесал и быстренько прикрепил. Дальше нужно было сделать компонент, который бы отображал информацию об исполнителе с помощью LastFM API. Сначала я по традиции подготовил дизайн компонента (с которым я не заморачивался), подготовил нужные поля. Потом наладил взаимодействие с API. Для передачи текущего трека из компонента плеера в компонент с LastFM, я использовал собственный event, который передавал информацию о треке в основное приложение, а оно перенаправляло запрос к компоненту с LastFM. Ну а дальше быстренько добавил шапку. Сделал логотип и готово. Плеер запущен. В данный момент он доступен здесь: vkontakte.ru/app593265

image
Tags:
Hubs:
+38
Comments 32
Comments Comments 32

Articles