Android Dev#1 — С чего начать?

Android — перспективная и динамично развивающаяся операционная система. И многие программисты хотят научиться программировать приложения для OS Android, но беглый поиск структурированных материалов в сети Интернет и, в частности, Рунете, приводит их в ступор. Действительно, до сих пор существует проблема поиска обучающих статей (особенно на русском языке) по разработке приложений для этой весьма популярной операционной системы.
Ну, что ж, будем потихоньку улучшать данную ситуацию при помощи Хабра.
Сразу предупрежу, что материалы предназначены для тех, кто не имеет опыта разработки приложений для Android, но очень-очень хочет этот опыт приобрести.

Готовимся

Первое, что нам потребуется — установить и настроить IDE. Мы будем использовать Eclipse, однако важно отметить, что существует возможность использовать любую среду разработки.
Подробная инструкция по установке и настройке IDE Eclipse содержится в документации на сайте Android. Если вкратце:

  • Устанавливаем Eclipse Classic отсюда
  • Устанавливаем SDK Starter Package отсюда
  • Устанавливаем ADT Plugin при помощи данной инструкции, по той же инструкции выполняем действия, описанные в разделе Configuring the ADT Plugin
  • Запускаем Eclipse, нажимаем Window > Android SDK and AVD Manager и выбираем необходимые компоненты для установки. Самый простой вариант — выбрать всё, но необходимый минимум — SDK Platform Android 2.1(или 2.2), Android SDK Tools, Android SDK Platform-tools

После всего этого мы имеем рабочую среду для разработки приложений для ОС Android. Но нам нужно где-то проверять наши приложения, верно? И тут мы стоим перед выбором — либо осуществлять эти действия в эмуляторе, либо на реальном устройстве.
Эмулятор можно добавить в уже знакомом нам окне Android SDK and AVD Manager, нажав кнопку New… во вкладкеVirtual Devices. Заполняем поле Name, указываем версию API и добавляем наше виртуальное устройство.

Если же вы хотите тестировать свои приложения на реальном устройстве, смотрите сюда. Важно отметить, что в конечном счёте вам всё равно придётся проверять своё приложение на реальном устройстве, ведь немного странно выпускать приложение, допустим, в Android Market, как следует его не протестировав на действующих образцах телефонов/планшетов.

Создаем проект

Пришло время создать новый проект. Для этого жмём File > New > Project, выбираем в появившемся окне Android > Android Project и жмем Next. Появляется следующее окно, которое мы заполняем примерно так:

Теперь немного объяснений.
Project Name — имя проекта в среде Eclipse.
Application Name — название приложение, то самое, которое будут видеть пользователи на конечном Android-устройстве.
Package Name — название пакета. Тут всё аналогично любому Java-проекту. Важно знать, что данное имя должно быть уникальным среди всех пакетов, имеющихся на конечном устройстве. Посему достаточно эффективна классическая логика давать название, соответствующего веб-домену, записанному наоборот (как тут — ru.alwake), а далее — название самого проекта. Данный шаг в какой-то мере обеспечит уникальность названия.
Create Activity — имя класса, который в будущем будет являться подклассом класса Activity.
Min SDK Version — минимальная версия SDK. Если посмотреть выше на список Build Target в данном окне, то можно прийти к выводу, что наше приложение запускается только для устройств с Android >= 2.1 (Android 2.1 соответствует версия SDK 7). В данном случае это не очень принципиально, но пусть будет так.

Теперь можно смело нажать Finish и лицезреть свой проект в панели Package Exploper. Проект создан и неплохо бы ознакомиться с некоторой теоретической основой по устройству Android-приложений, которая неплохо изложена тут.

О нашем проекте

Для начала определимся, что мы хотим от нашего файлового менеджера. В идеале — полную замену ASTRO и eStrongs. Ну, а пока нам требуется обеспечить базовую навигацию по каталогам, причем под «базовой» мы понимаем, что нам не нужно заходить в те папки, в которые имеет доступ только root. Помимо этого, в поле сверху у нас будет отображаться наше текущее расположение в структуре каталогов.

Ну, а сначала поговорим о структуре проекта:

/res/drawable-*dpi — в этих трёх папках у нас содержатся ресурсы, предназначенные для разных расширений экрана. На данный момент там имеется всего-навсего файл icon.png, то есть иконка нашего приложения.
/res/layout — в данной папке содержатся xml-файлы, описывающие внешний вид форм и различных элементов форм. После создания проекта там уже имеется файл main.xml, также там нужно создать файл row.xml, который будет описывать внешний вид каждого отдельно взятого ряда (то есть элемента списка нашего файлового древа).
/res/values — тут у нас располагаются какие-либо константы, которые мы можем использовать в нашем проекте.

Стоит отметить, что данные XML-файлы можно редактировать как в визуальном режиме, так и в текстовом (меняя непосредственно xml-код). Мы будем действовать по второму способу. Для редактирования кода необходимо нажать правой кнопкой по xml-файлу в панели Package Explorer и выбрать Open with > Text Editor. Это так, на будущее ;)

Файл FileManager.java — в данном файле, собственно, содержится наш основной класс для главной и единственной формы приложения. Весь наш код в данном проекте будет размещаться тут.
Файл AndroidManifest.xml — файл с основными свойствами нашего проекта, в частности, заданными при создании проекта (такими как, например, название). Соответственно, чтобы поменять, предположим, название, нам нужно ковырять данный файл.

Остальные файлы нас пока мало интересуют.

Начинаем писать код

В общем-то, всё что было выше — базовые сведения, которые каждый Android-программист обязан знать. А теперь пришла пора разбираться непосредственно с нашим кодом.

Файл main.xml:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">

<TableRow>
<TextView android:id=»@+id/titleManager»
android:layout_width=»fill_parent»
android:layout_height=»fill_parent»
android:padding=»5dip»
/>
</TableRow>
<TableRow>
<ListView android:id=»@id/android:list»
android:layout_width=»fill_parent»
android:layout_height=»fill_parent»
android:layout_weight=»2″
android:drawSelectorOnTop=»false»/>
</TableRow>
</TableLayout>

* This source code was highlighted with Source Code Highlighter.

Здесь у нас задается разметка для нашего основного Layout’а формы. TableLayout здесь значит, что элементы у нас выстроены в виде таблицы. Далее в верхней ячейке таблицы размещается элемент TextView (текстовое поле), а в нижней ячейке — ListView (список). Оба элемента имеют id, используя который, мы можем изменять содержимое элементов. Например, используя R.id.titleManager для нашего текстового поля TextView.

Файл row.xml:

<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="40sp"
android:padding="5dip"
android:gravity="center_vertical"
/>

* This source code was highlighted with Source Code Highlighter.

Здесь мы задаем разметку для каждого элемента нашего ListView, то есть непосредственно для каждой отдельно взятой папки или каждого файла. В данном коде у нас задается ширина каждого элемента, высота, отступ (padding) и выравнивание center_vertical — то есть центрование по вертикали.

Файл FileManager.java:

  1. package ru.alwake.filemanager;
  2. import java.io.File;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import android.app.AlertDialog;
  6. import android.app.ListActivity;
  7. import android.content.DialogInterface;
  8. import android.content.Intent;
  9. import android.content.DialogInterface.OnClickListener;
  10. import android.net.Uri;
  11. import android.os.Bundle;
  12. import android.view.View;
  13. import android.widget.ArrayAdapter;
  14. import android.widget.ListView;
  15. import android.widget.TextView;
  16. public class FileManager extends ListActivity {
  17.   private List<String> directoryEntries = new ArrayList<String>();
  18.   private File currentDirectory = new File(«/»);
  19.   //when application started
  20.   @Override
  21.   public void onCreate(Bundle icicle) {
  22.     super.onCreate(icicle);
  23.     //set main layout
  24.     setContentView(R.layout.main);
  25.     //browse to root directory
  26.     browseTo(new File(«/»));
  27.   }
  28.   //browse to parent directory
  29.   private void upOneLevel(){
  30.     if(this.currentDirectory.getParent() != null) {
  31.       this.browseTo(this.currentDirectory.getParentFile());
  32.     }
  33.   }
  34.   //browse to file or directory
  35.   private void browseTo(final File aDirectory){
  36.     //if we want to browse directory
  37.     if (aDirectory.isDirectory()){
  38.       //fill list with files from this directory
  39.       this.currentDirectory = aDirectory;
  40.       fill(aDirectory.listFiles());
  41.       //set titleManager text
  42.       TextView titleManager = (TextView) findViewById(R.id.titleManager);
  43.       titleManager.setText(aDirectory.getAbsolutePath());
  44.     } else {
  45.       //if we want to open file, show this dialog:
  46.       //listener when YES button clicked
  47.       OnClickListener okButtonListener = new OnClickListener(){
  48.         public void onClick(DialogInterface arg0, int arg1) {
  49.           //intent to navigate file
  50.           Intent i = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(«file://» + aDirectory.getAbsolutePath()));
  51.           //start this activity
  52.           startActivity(i);
  53.         }
  54.       };
  55.       //listener when NO button clicked
  56.       OnClickListener cancelButtonListener = new OnClickListener() {
  57.         public void onClick(DialogInterface arg0, int arg1) {
  58.           //do nothing
  59.           //or add something you want
  60.         }
  61.       };
  62.       //create dialog
  63.       new AlertDialog.Builder(this)
  64.         .setTitle(«Подтверждение») //title
  65.         .setMessage(«Хотите открыть файл «+ aDirectory.getName() + «?») //message
  66.         .setPositiveButton(«Да», okButtonListener) //positive button
  67.         .setNegativeButton(«Нет», cancelButtonListener) //negative button
  68.         .show(); //show dialog
  69.     }
  70.   }
  71.   //fill list
  72.   private void fill(File[] files) {
  73.     //clear list
  74.     this.directoryEntries.clear();
  75.     if (this.currentDirectory.getParent() != null)
  76.       this.directoryEntries.add(«..»);
  77.     //add every file into list
  78.     for (File file : files) {
  79.       this.directoryEntries.add(file.getAbsolutePath());
  80.     }
  81.     //create array adapter to show everything
  82.     ArrayAdapter<String> directoryList = new ArrayAdapter<String>(this, R.layout.row,this.directoryEntries);
  83.     this.setListAdapter(directoryList);
  84.   }
  85.   //when you clicked onto item
  86.   @Override
  87.   protected void onListItemClick(ListView l, View v, int position, long id) {
  88.     //get selected file name
  89.     int selectionRowID = position;
  90.     String selectedFileString = this.directoryEntries.get(selectionRowID);
  91.     //if we select «..» then go upper
  92.     if(selectedFileString.equals(«..»)){
  93.       this.upOneLevel();
  94.     } else {
  95.       //browse to clicked file or directory using browseTo()
  96.       File clickedFile = null;
  97.       clickedFile = new File(selectedFileString);
  98.       if (clickedFile != null)
  99.         this.browseTo(clickedFile);
  100.     }
  101.   }
  102. }

* This source code was highlighted with Source Code Highlighter.

В начале указывается название пакета (package name).
Строки 2-18 отвечают за импорт нужных нам библиотек. Важно отметить, что импорт библиотек Eclipse может производить автоматически, как только встретит что-нибудь неизвестное.
В данном коде у нас всего 5 достаточно очевидных функций, в которых несложно разобраться. И это — скелет приложения, обеспечивающий основную навигацию по файловой структуре. Однако у данного приложения существует одна проблема — при попытке зайти в директорию, доступ к которой разрешен только суперпользователю, мы получаем ошибку и приложение завершает работу.
Соответственно, в следующий раз мы подумаем как избавиться от этой ошибки, а также о том, как сделать отображение иконок, соответствующих типу файла. Кроме того, мы подумаем о реализации функции Copy-Paste в нашем файловом менеджере.

В конечном счёте предполагается получить большое и грамотное приложение, которое должно дать основную информацию об аспектах программирования под Android.

Добавить комментарий

Войти с помощью: 

Ваш e-mail не будет опубликован. Обязательные поля помечены *