Androidopen sourcedeveloper-friendlymobile operational system
СодержаниеОбщее впечатление от AndroidПример архитектуры приложения (I часть)2Android first mini party
Общее впечатление от AndroidНаше самое субъективное мнение
Что знает каждыйОткрытость системы (≈4GB of sources)По-настоящему большое число устройствНовая версия ОС каждые полгода-годЛегкость разработки, хорошая документацияJavaAndroid marketУникальная модель многозадачностиЭксклюзивные плюшки от Google4Android first mini party
Что в действительности (1/3)ПроизводителиОни любят копаться в кодеОни точно знают, как сделать лучшеИх интересуют деньги, а не платформа и это нормально Google им попустительствует и это не нормальноМного девайсовВам правда потребуется много девайсовАппаратные функции телефона тестируются на устройствахscreenresolution, CPU, hardwarekeyboard, etc.5Android first mini party
Что в действительности (2/3)Новая версия ОС каждые полгода-годНовая ОС — новый девайсSupport придумали дуракиBackwardcompatibilityОткрытостьВседозволенность разработчиковБезумные идеи заказчиковПретензии начальниковНерадивые производителиJavaТормозит?Аппараты от 1GHzНикогда не поздно вспомнить JNI и C/C++6Android first mini party
Что в действительности (3/3)Прочие подводные камниЭто мультизадачность, сынок, готовься к смертиКак передать данные от Activity к Activity?А какой же здесь Context? (Смена ориентации)I WANT TO SEARCH! RIGHT NOW!Activity lifecycleSD-Card mount/unmountMediaAPI (я никогда не устану это повторять:)7Android first mini party
ПримерыОдин INSERT в Sqliteна Galaxy S занимает около секунды - что-то не получилось с файловой системойMediaRecorder.start() с выводом в AMR_NB на DROID X или зависал на стопе или искажал звукMediaRecorder.stop() на Motorola Milestone после 10 минут не хотел выполнятьсяMediaRecorder.init() на Motorola Milestone с неправильными параметрами убивал камеру до следующего перезапускаMediaRecorder.setMaxDuration() — who gives a shit?Camera.getParameters() — HashMap<String, String>Падают стандартные приложения и многое-многое другое…8Android first mini party
Так за что же тогда его любить?За его молодостьЗа работу над ошибками (3.0 мммм:)За открытые исходные кодыЗа его ориентированность на разработчиковЗа бесконечные возможности9Android first mini party
Пример архитектуры приложенияЧастные решения частых задач
ЗаданиеЕсть сервер, с которого мы получаем данные (tweets).Мы отображаем эти данные (listoftweets)Мы редактируем старые/создаем новые данные и отсылаем на сервер (reply/delete/new)Мы периодически синхронизируем данные с серверомМы храним данные локально, чтобы приложение могло быть запущено без интернетаМы предоставляем настройку периодов синхронизации и какие-то другие параметры11Android first mini party
Общее представлениеServerApplicationDBLoginActivityPreferencesActivityEditActivityMainActivity12Android first mini party
А для приготовления нам понадобятся…Android-sdk-toolsскачать как минимум версию 2.1 и Google APIsandroid-ndk-tools (для ценителей C/C++)Eclipse/Ideaможно подключить android formatter для кода ADT plugin (Eclipse)Android Java sourcesApiDemosв workspace13Android first mini party
Android-командаЛюсиДжеффБорис14Android first mini party
Первая итерация Получение списка записейпока при старте приложенияпока для hardcoded пользователяСохранение записейв базуОтображение записей на экране15Android first mini party
Над чем не стоит долго думатьHttpClient, а не java.net.URLSQLite&SQLiteOpenHelperListView&ListActivity16Android first mini party
ListView17layout.xmlList Adapter+ getItem();+ getCount();+ getView();+ getItemViewType();+ getViewTypeCount();Android first mini party
Спор Люси и БорисаСобственный StoreDomainObjectArrayAdapterСамостоятельно реализовыватьObserversА как по другому?Там что-то непонятное написано18Android first mini party
Спор Люси и БорисаContentProviderContract&CursorAdapterObservers – DONEи очень даже крутойActivity.manageCursor() помощь при с открытием и закрытие CursorContentProvider .openFile ()полезный метод для работы с binary data19Android first mini party
ContentProvider. Contractpublic final class ContentContract {public static final String AUTHORITY = "x.test.content";public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);private ContentContract() {}protected interface QuestionsColumns {	String GUID = "guid";	/** Active or closed */	String STATE = "state";	/** Rated, Read, Not read, Rejected */	String SUB_STATE = "substate";	String HAS_TRACK = "has_track";	String TRANSCRIPTION = "transcription";	String PRICE = "price";	String POST_DATE = "post_date";}public static final class Questions implements QuestionsColumns, BaseColumns {private Questions() {}public static class State {intEDITED = 0, OPENED = 1, CLOSED = 2, DELETED = 3;}public static class Substate {intPENDING = 0, READY_TO_SEND = 1;}public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "questions");public static final String CONTENT_TYPE = "vnd.android.cursor.dir/x.test.question";public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/x.test.question";}20Android first mini party
ContentProvider. URIAndroid first mini party21content:// questionscontent://questions/#content://questions/opened content://questions/closedcontent:// questions/#/answerscontent:// questions/#/attachmentsContentProvider.notifyChange(uri)ContentResolver.registerContentObserver(uri, true, observer)
Вторая итерацияЛогин на отдельной LoginActivity и переход на MainActivityПереход на EditActivityдля выбранной записи22Android first mini party
Передача данных между ActivityИсследование Джеффа23Android first mini party
Service. Что же это такое?Компонент приложения, скрытый от пользователяНацелен на выполнения фоновых задачРаботает в главном потокеЕго можно стартитьК нему можно биндитьсяЕго НУЖНО стопитьЕго ОБЯЗАТЕЛЬНО нужно стопитьПроцесс, в котором есть застарченный Service,будет умирать в последнюю очередь24Android first mini party
Service. Local binderpublic class LocalService extends Service {       private final IBindermBinder = new LocalBinder();    private final Random mGenerator = new Random();    public class LocalBinder extends Binder {        LocalServicegetService() {            return LocalService.this;        }    }    @Override    public IBinderonBind(Intent intent) {        return mBinder;    }    public intgetRandomNumber() {      return mGenerator.nextInt(100);    }}25Android first mini party
Service. Lifecycle26Android first mini party
Проблема БорисаAndroid first mini party27ThreadLooper
Решение ЛюсиAndroid first mini party28Handlerpost(Runnable r)handleMessage(Message m)obtainMessage()sendMessage()
Решение ДжеффаAndroid first mini party29 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {     protected Long doInBackground(URL... urls) {         int count = urls.length;         long totalSize = 0;         for (int i = 0; i < count; i++) {             totalSize += Downloader.downloadFile(urls[i]);             publishProgress((int) ((i / (float) count) * 100));         }         return totalSize;     }     protected void onProgressUpdate(Integer... progress) {         setProgressPercent(progress[0]);     }     protected void onPostExecute(Long result) {         showDialog("Downloaded " + result + " bytes");     } }
GOOGLE I/O 201030Android first mini party
Решение задачи передачи данныхНикакой проблемы передача данных между Activityна самом деле не существуетActivity – это взгляд с разных сторон на данные, которые находятся в Content ProviderService – это task executor (см. IntentService)Intent – это такс на выполнение, содержащий Action и URI ServiceContract/API – API для взаимодействия ссервисомService State – singleton для опционального хранения состояния ServiceBinder нужен только для частных синхронных операций31Android first mini party

First Android Mini-party (Part I)

  • 1.
  • 2.
    СодержаниеОбщее впечатление отAndroidПример архитектуры приложения (I часть)2Android first mini party
  • 3.
    Общее впечатление отAndroidНаше самое субъективное мнение
  • 4.
    Что знает каждыйОткрытостьсистемы (≈4GB of sources)По-настоящему большое число устройствНовая версия ОС каждые полгода-годЛегкость разработки, хорошая документацияJavaAndroid marketУникальная модель многозадачностиЭксклюзивные плюшки от Google4Android first mini party
  • 5.
    Что в действительности(1/3)ПроизводителиОни любят копаться в кодеОни точно знают, как сделать лучшеИх интересуют деньги, а не платформа и это нормально Google им попустительствует и это не нормальноМного девайсовВам правда потребуется много девайсовАппаратные функции телефона тестируются на устройствахscreenresolution, CPU, hardwarekeyboard, etc.5Android first mini party
  • 6.
    Что в действительности(2/3)Новая версия ОС каждые полгода-годНовая ОС — новый девайсSupport придумали дуракиBackwardcompatibilityОткрытостьВседозволенность разработчиковБезумные идеи заказчиковПретензии начальниковНерадивые производителиJavaТормозит?Аппараты от 1GHzНикогда не поздно вспомнить JNI и C/C++6Android first mini party
  • 7.
    Что в действительности(3/3)Прочие подводные камниЭто мультизадачность, сынок, готовься к смертиКак передать данные от Activity к Activity?А какой же здесь Context? (Смена ориентации)I WANT TO SEARCH! RIGHT NOW!Activity lifecycleSD-Card mount/unmountMediaAPI (я никогда не устану это повторять:)7Android first mini party
  • 8.
    ПримерыОдин INSERT вSqliteна Galaxy S занимает около секунды - что-то не получилось с файловой системойMediaRecorder.start() с выводом в AMR_NB на DROID X или зависал на стопе или искажал звукMediaRecorder.stop() на Motorola Milestone после 10 минут не хотел выполнятьсяMediaRecorder.init() на Motorola Milestone с неправильными параметрами убивал камеру до следующего перезапускаMediaRecorder.setMaxDuration() — who gives a shit?Camera.getParameters() — HashMap<String, String>Падают стандартные приложения и многое-многое другое…8Android first mini party
  • 9.
    Так за чтоже тогда его любить?За его молодостьЗа работу над ошибками (3.0 мммм:)За открытые исходные кодыЗа его ориентированность на разработчиковЗа бесконечные возможности9Android first mini party
  • 10.
  • 11.
    ЗаданиеЕсть сервер, скоторого мы получаем данные (tweets).Мы отображаем эти данные (listoftweets)Мы редактируем старые/создаем новые данные и отсылаем на сервер (reply/delete/new)Мы периодически синхронизируем данные с серверомМы храним данные локально, чтобы приложение могло быть запущено без интернетаМы предоставляем настройку периодов синхронизации и какие-то другие параметры11Android first mini party
  • 12.
  • 13.
    А для приготовлениянам понадобятся…Android-sdk-toolsскачать как минимум версию 2.1 и Google APIsandroid-ndk-tools (для ценителей C/C++)Eclipse/Ideaможно подключить android formatter для кода ADT plugin (Eclipse)Android Java sourcesApiDemosв workspace13Android first mini party
  • 14.
  • 15.
    Первая итерация Получениесписка записейпока при старте приложенияпока для hardcoded пользователяСохранение записейв базуОтображение записей на экране15Android first mini party
  • 16.
    Над чем нестоит долго думатьHttpClient, а не java.net.URLSQLite&SQLiteOpenHelperListView&ListActivity16Android first mini party
  • 17.
    ListView17layout.xmlList Adapter+ getItem();+getCount();+ getView();+ getItemViewType();+ getViewTypeCount();Android first mini party
  • 18.
    Спор Люси иБорисаСобственный StoreDomainObjectArrayAdapterСамостоятельно реализовыватьObserversА как по другому?Там что-то непонятное написано18Android first mini party
  • 19.
    Спор Люси иБорисаContentProviderContract&CursorAdapterObservers – DONEи очень даже крутойActivity.manageCursor() помощь при с открытием и закрытие CursorContentProvider .openFile ()полезный метод для работы с binary data19Android first mini party
  • 20.
    ContentProvider. Contractpublic finalclass ContentContract {public static final String AUTHORITY = "x.test.content";public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);private ContentContract() {}protected interface QuestionsColumns { String GUID = "guid"; /** Active or closed */ String STATE = "state"; /** Rated, Read, Not read, Rejected */ String SUB_STATE = "substate"; String HAS_TRACK = "has_track"; String TRANSCRIPTION = "transcription"; String PRICE = "price"; String POST_DATE = "post_date";}public static final class Questions implements QuestionsColumns, BaseColumns {private Questions() {}public static class State {intEDITED = 0, OPENED = 1, CLOSED = 2, DELETED = 3;}public static class Substate {intPENDING = 0, READY_TO_SEND = 1;}public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "questions");public static final String CONTENT_TYPE = "vnd.android.cursor.dir/x.test.question";public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/x.test.question";}20Android first mini party
  • 21.
    ContentProvider. URIAndroid firstmini party21content:// questionscontent://questions/#content://questions/opened content://questions/closedcontent:// questions/#/answerscontent:// questions/#/attachmentsContentProvider.notifyChange(uri)ContentResolver.registerContentObserver(uri, true, observer)
  • 22.
    Вторая итерацияЛогин наотдельной LoginActivity и переход на MainActivityПереход на EditActivityдля выбранной записи22Android first mini party
  • 23.
    Передача данных междуActivityИсследование Джеффа23Android first mini party
  • 24.
    Service. Что жеэто такое?Компонент приложения, скрытый от пользователяНацелен на выполнения фоновых задачРаботает в главном потокеЕго можно стартитьК нему можно биндитьсяЕго НУЖНО стопитьЕго ОБЯЗАТЕЛЬНО нужно стопитьПроцесс, в котором есть застарченный Service,будет умирать в последнюю очередь24Android first mini party
  • 25.
    Service. Local binderpublicclass LocalService extends Service {    private final IBindermBinder = new LocalBinder();    private final Random mGenerator = new Random();    public class LocalBinder extends Binder {        LocalServicegetService() {            return LocalService.this;        }    }    @Override    public IBinderonBind(Intent intent) {        return mBinder;    }    public intgetRandomNumber() {      return mGenerator.nextInt(100);    }}25Android first mini party
  • 26.
  • 27.
  • 28.
    Решение ЛюсиAndroid firstmini party28Handlerpost(Runnable r)handleMessage(Message m)obtainMessage()sendMessage()
  • 29.
    Решение ДжеффаAndroid firstmini party29 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {     protected Long doInBackground(URL... urls) {         int count = urls.length;         long totalSize = 0;         for (int i = 0; i < count; i++) {             totalSize += Downloader.downloadFile(urls[i]);             publishProgress((int) ((i / (float) count) * 100));         }         return totalSize;     }     protected void onProgressUpdate(Integer... progress) {         setProgressPercent(progress[0]);     }     protected void onPostExecute(Long result) {         showDialog("Downloaded " + result + " bytes");     } }
  • 30.
    GOOGLE I/O 201030Androidfirst mini party
  • 31.
    Решение задачи передачиданныхНикакой проблемы передача данных между Activityна самом деле не существуетActivity – это взгляд с разных сторон на данные, которые находятся в Content ProviderService – это task executor (см. IntentService)Intent – это такс на выполнение, содержащий Action и URI ServiceContract/API – API для взаимодействия ссервисомService State – singleton для опционального хранения состояния ServiceBinder нужен только для частных синхронных операций31Android first mini party