Android — основанная на linux платформа для мобильных устройств использующая изменённую виртуальную машину Java построенную для учёта компактности файлов и энергоэффективности Dalvik. Из-за этого используется не Mobile Edition и тем более не Java SE, а свои библиотеки.
Приложения соответсвенно пишутся на Java, либо же через обходные пути — Titanium, AppInventor, Adobe AIR. Интересно что из библиотек есть SQLite и OpenGL — не прийдётся изобретать велосипеды. Кроме того в системе есть менеджеры для обмена данными между приложениями, сенсорами и тп.
Многозадачность системы реализуется на программном уровне. Если в ПК приложения постоянно висят в оперативной памяти, а процессор прыгает между ними, то здесь каждое приложение это экземпляр класса Activity который может быть в разных состояниях
Обучающий материал для андроида пишется в двух разных мирах — для игр и для приложений.
Я рассматриваю именно приложения. Итак — скачиваем и устанавливаем JRE, JDK, SDK, Eclipse + plugin и открываем новый Android-проект. Я думаю до этого вы сами дойдёте. Типичное приложение может состоять из 4 основных мега-блоков — Activity, Intent Receiver, Service, Content Provider которые описываются в AndroidManifest.xml, вместе с запрашиваемыми привилегиями.
Делаем страницу (Activity)
Страница делается просто наследованием Activity класса и использовании менеджера ресурсов указывающем на внешний вид
public class MyKillerActivity extends Activity { //моя убийственная страничка
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); //использует шаблон main.xml через менеджер ресурсов
}
}
Продумываем внешний вид (View)
Шаблоны отвечающие за внешний вид как и прочие данные лежат в XML-формате в /res папке. Локализация под другие страны и языки делается визардом который просто добавляет префиксы к файлам или папкам.
- layout/*.xml — собственно шаблоны UI элементы со всякими кнопочками и текстовыми полями
- values/strings.xml где лежат переводы для текстов UI
- colors.xml, menu.xml, settings.xml
Для размеров и местоположения элементов используются разрывающие мозг единицы — px, pt, dip, sp.. Для дебага есть Hierarchy Viewer. В отличие от умного HTML в андроиде позиционирование элементов задаётся структурными элементами
- LinearLayout — дети ставятся друг за другом внутри родителя в заданном направлении. Если задан weight, то свободное место родителя перераспределяется между детьми
- RelativeLayout — дети ставятся относительно родителя или ранее поставленного элемента
- FrameLayout — дети ставятся сверху слева относительно и поверх родителя
- TableLayout — аналог HTML-таблиц но без объединения ячеек
- AbsoluteLayout — устарел из-за разных размеров устройств
Наполняем данными (Adapters)
Адаптеры нужны для показа динамического содержания на наследующих ListActivity страницах, которые могут содержать контейнер элементов — вертикальный список (ListView), таблицу (GridView), галерею (Gallery), выпадающий список (Spinner) или сгруппированный список (ExpandableListView). Адаптеры же передают данные из массивов/БД/интернета в шаблон. Связывается адаптер вызовом метода..
setListAdapter(new ArrayAdapter(this,
android.R.layout.simple_list_item_1, //встроенный шаблон для каждого ряда
new String[]{"item 1", "item 2"} //собственно данные
));
Есть много готовых адаптеров — ListAdapter, SimpleAdapter, ArrayAdaptor, CursorAdapter, SimpleCursorAdapter… и всегда можно написать свой, унаследовав абстрактный BaseAdapter.
При наполнении данными могут понадобится всякие фичи. Например форматирование дат зависит от настроек пользователя..
Calendar c = Calendar.getInstance();
c.setTimeInMillis(1000*json_row.getLong("timestamp")); //конвертируем int-timestamp полученный из mysql по json. Из секунд в миллисекунды
android.text.format.DateFormat.getTimeFormat(getApplicationContext()).format(date_added); //время вида 12:10AM
android.text.format.DateFormat.getDateFormat(getApplicationContext()).format(date_added); //дата вида 5/12/2010
Или например если вы хотите ссылки в своём TextView, то HTML частично преобразовывается с помощью Html.fromHtml() метода и android:autoLink=»web» параметра у элемента. А если надо вручную у «X ребёнка» что-то сделать то есть getChildAt метод.
Добавляем ссылки (Intent)
С помощью Intent пользователя можно переносить на другую страницу, в телефонную книжку, браузер и тп. При этом текущая Activity приостанавливается и в неё можно будет вернуться back-кнопкой. В передаваемую activity можно передавать дополнительные данные не только в формате key-value но и используя Bundle объект. Вот как это выглядит..
startActivity(new Intent(MyKillerActivity.this, MyWeakMinionActivity.class)); //перейдёт к другой странице по именам классов
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://kurapov.name"))); // открыть сайт в браузере
Intent search = new Intent(Intent.ACTION_WEB_SEARCH); //браузерный поиск
search.putExtra(SearchManager.QUERY, "куплю снег");
startActivity(search);
Ещё один мощный тип управления это меню (Submenu) выскакивающее при нажатии одноимённой кнопки устройства. Ещё есть его расширение (вертикальный список) и контекстные меню при долгом нажатии на View-элемент, но сейчас не об этом. Меню добавляется как xml файл и прикрепляется к Activity как метод onCreateOptionsMenu, а для обработки нажатия используется onOptionsItemSelected метод, куда и нужно вставлять Intent в зависимости от выбранного элемента.
Подгружаем данные (AsyncTask)
К этому моменту у нас есть шаблон, есть возможность передачи данных в него и даже переходы между страницами, но нет самой основы — подгрузки данных из интернета или БД. Первое надо при простейшей небезопасной авторизации.. Долгие процессы надо выделять в асинхронные запросы (AsyncTask) что-бы приложение не подвисало. Кроме того к авторизации надо прикрутить SSL, абстрагироваться http-запроса выделив его в отдельный класс если данные будут запрашиваться часто. И встроить в Activity производный от него класс что-бы получать доступ к Activity-методам.. выглядит это в примерно так
А что-бы процесс было видно пользователю — можно добавить ProgressBar диалог..
this.progressDialog = new ProgressDialog(MyKillerActivity.this); //диалог в контексте страницы
//учитываем локализацию
this.progressDialog.setMessage(getApplicationContext().getResources().getString(R.string.dialog_logging_in));
this.progressDialog.show();
...
protected void onPostExecute(Object responce){
this.progressDialog.dismiss(); //когдм AsyncTask заканчивается - прячем диалог
}
Храним настройки (SharedPreferences)
Настройки приложения вовсе не значат управление ими пользователем через интерфейс (для этого есть странички типа PreferenceActivity). Настройки это один из видов постоянного хранения данных наряду с файлами и SQLite. С их помощью можно хранить данные между запусками
SharedPreferences settings = getSharedPreferences("MyKillerAppSettings", MODE_PRIVATE);
settings.edit().putString("MyMinionName", MyKillerActivity.minionName).commit(); //пишем
settings.getString("MyMinionName",""); //читаем
Полезно по теме
- Основные понятия андроид-приложений
- Дарья Ряжских — адаптеры и написание игры с Surface
- Exploring the world of android и Как реализовать загрузку изображений — динамическая подгрузка изображений
- Getting Reference to Calling Activity from AsyncTask