28.10.2014

Урок 4: изучаем Java (тут также общий список рекомендуемых ресурсов)

Перечень рекомендуемой литературы

  1. Введение в разработку приложений для ОС Android (основной учебник на 1 семестр)
  2. Введение в разработку приложений для смартфонов на ОС Android (кратко)
  3. Разработка приложений для смартфонов на ОС Аndroid (продвинутый)
  4. Google Android - это несложно (100 бесплатных уроков для начинающих разработчиков)
  5. Java. Экспресс-курс
  6. Изучаем Android за месяц (Android Studio) (30 уроков. Внимание: используется не Eclipse, а  Android Studio!!!)
  7. Mobile computing (англ.) (общий обзор)
  8. Android Tutorial (англ.)
  9.  Разработка приложений для Modern UI: Windows 8
  10. 60+ средств разработки мобильных приложений
  11. Учебник по Java (Электронный wiki-перевод книги Брюса Эккеля. 4 издание)
  12. Java: вводная видеолекция (С.Немчинский)/ Часть 1, ООП, JVM
    Часть 2, UML, описание класса, видимость полей, методы, конструкторы
    Часть 3, Объект Object
    Часть 4, Обзор юнит-тестов
    * Часть 5, разработка веб-приложений - обзор
    * Остальные части не очень хорошо
  13. Java: другой видеокурс (А.Владыкин)/ 12 лекций.
    Обязательно к просмотру 1-6 части. Полезна и 12 - работа с сетью.
    2. Типы данных
    3. Преобразование типов, Массивы и строки
    4. Объекты
    5. Управляющие консттрукции
    6. Ввод и вывод

Авторские ресурсы:

1. Блог для выдачи еженедельных заданий:   " Разработка мобильных приложений"
2. Форум: для обсуждения и вопросов: закрытая группа Google
3. Презентация по языку Java лежит тут (введение).

Курсы по теме от других университетов:

27.10.2014

Урок 3. Изучаем создание интерфейса приложения подробнее

Привет!
Вы уже научились размещать копки и текстовые поля, а также обрабатывать их события в программе. Теперь изучаем подробно все элементы графического пользовательского интерфейса по лекциям Интуита:

Дополнительно советую почитать рекомендации практиков дизайна:

  1. http://habrahabr.ru/post/183836/ - как таки должен работать дизайнер для учета всего зоопарка устройств
  2. Простые примеры управления интерфейсом: http://developer.alexanderklimov.ru/android/ - день 3 - 10.   
В результате у вас должно сложиться общее представление о пользовательском интерфейсе андроид-приложения.  
В заключение попробуйте нарисовать от руки эскизы всех экранов вашего приложения. Постарайтесь уложиться в 5 экранов! 

Ваши идеи предлагаю обсудить на семинаре во вторник и на форуме https://groups.google.com/forum/#!topic/pengtu_mobile/U62cfT6zxqs.



22.10.2014

Урок 2: создание простейшей программы из двух окон, текстового поля и кнопки

Урок 2: построение простого пользовательского интерфейса программы для Android


Графический пользовательский интерфейс для Android приложений построен с использованием иерархии объектов View- и ViewGroup . Первый класс объектов применяют обычно для создания видимых элементов интерфейса (кнопки, текстовые поля), а ViewGroup  - это невидимые контейнеры для первых, например, они применяются,  чтобы разместить кнопки по сетке или в виде вертикального списка.
Android предоставляет XML-словарь, который содержит описания подклассов элементов и их групп, так что ​​пользовательский интерфейс можно описывать с помощью XML, используя иерархию элементов интерфейса.

В этом уроке вы создадите в файле XML макет, который включает текстовое поле и кнопку. Затем напишем программу, которая после нажатия кнопки отправит содержание текстового поля на другую Activity.

Создаем линейный макет ( Linear Layout).

В Эклипсе при открытии файла макета вы сначала видите графический редактор  макета, который позволяет размещать элементы интерфейса в режиме WYSIWYG. Но в этом уроке мы будем работать напрямую с XML-файлом, в котором сохраняется описание макета. Для открытия XML-редактора щелкните внизу экрана по закладке activity_main.xml. Файл макета находится в  папке  res/layout/ .
Шаблон макета  BlankActivity, который мы выбрали на прошлом уроке для нашего приложения, включает файл activity_main.xml с корневой вьюшкой RelativeLayout и дочерней  TextView.
Сначала удалим элемент TextView и заменим элемент RelativeLayout на  <LinearLayout>. Потом добавим атрибут  android:orientation, установив ему значение horizontal. Другие атрибуты -  ширина и высота – обязательны для всех вьюшек. В результате должно получиться:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   
xmlns:tools="http://schemas.android.com/tools"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
   
android:orientation="horizontal" >
</LinearLayout>
Мы установили для размеров значения "match_parent", то есть «вычислить по размеру родителя». А поскольку  LinearLayout – корневой объект макета, то родитель для него – само приложение и он заполнит всю область экрана, доступную программе.  
Теория: Что такое макет (http://developer.android.com/guide/topics/ui/declaring-layout.html#load) – (переведено не полностью, до раздела «Атрибуты»)
Макет – это описание структуры пользовательского интерфейса программы. Макет можно описать 2-мя способами: в XML-файле или в тексте программы. Рекомендуется описание макета интерфейса в XML, так как это позволяет отделить управление поведением (код) от интерфейса, а также полезно для подстройки интерфейса под размер экрана устройства. Например, вы можете создать несколько версий макета и указать системе использовать один на «малых», а другой - на «больших» экранах, при различных ориентациях экрана, для разных языков. Также затем можно изменять интерфейс без перекомпиляции программы. Можно сочетать эти 2 метода описания макета: значения по умолчанию задать в XML,  а в программе изменить их во время выполнения. Подробнее см. о  поддержке различных типах устройств   (http://developer.android.com/training/basics/supporting-devices/index.html).

Чем отличаются RelativeLayout и LinearLayout
RelativeLayout - макет, где позиции дочерних объектов могут быть описаны по отношению друг к другу или к родительскому объекту. Не допустимы циклические зависимости объектов.
LinearLayout – макет, в котором дочерние объекты укладываются в одну строку или в один столбец (по умолчанию – горизонально), последовательно в порядке их описания в XML. Можно задать поля и выравнивание (вправо, влево и по центру) для всех или каждого дочернего объекта. Направление  можно установить атрибутом Orientation.
http://developer.android.com/guide/topics/ui/declaring-layout.html#CommonLayouts – подробнее о разных макетах.

Структура XML-файла описания макета

Каждый файл макета должен содержать только один корневой элемент, который должен быть объектом View или ViewGroup. После того как вы определили корневой элемент, можно добавить дополнительные объекты в качестве дочерних элементов, чтобы постепенно получилась иерархия View. Например, вот XML макет, который использует вертикальный линейный шаблон (LinearLayout) и выводит текстовое поле и кнопку:
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

              android:layout_width="fill_parent" 

              android:layout_height="fill_parent" 

              android:orientation="vertical" >

    <TextView android:id="@+id/text"

              android:layout_width="wrap_content"

              android:layout_height="wrap_content"

              android:text="Hello, I am a TextView" />

    <Button android:id="@+id/button"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="Hello, I am a Button" />

</LinearLayout>
После описания макета надо сохранить  файл с расширением .xml в папке проекта res/layout/.
Загрузка XML-ресурсов. После компиляции программы каждый XML-файл макета становится ресурсом VIEW. Вы должны загрузить его в вашем коде с помощью метода обратного вызова (callbackActivity.onCreate(). Делайте это при вызове  setContentView(), передавая ему ссылку на ресурс макета : .R.layout layout_file_name. Например,  пусть ваш файл имеет имя main_layout.xml. Для его загрузки используйте код:
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_layout);
}
.... Продолжим упражнения урока

Добавим текстовое поле

Чтобы создать элемент, позволяющий пользователю вводить текст, добавим на макет  элемент <EditText> и определим его свойства в XML-файле внутри элемента <LinearLayout>:
<EditText android:id="@+id/edit_message"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:hint="@string/edit_message" />
Рассмотрим его атрибуты.
android:id – уникальный идентификатор, используемый для ссылки на объект в коде программы, знак @ нужен, когда вы из xml-файла ссылаетесь на любой ресурс; затем идет тип ресурса (ID), косая черта и имя ресурса ( edit_message ).
Знак + перед типом нужен только в первый раз при описании нового типа ресурса.  При компиляции имя ресурса будет использовано для создания нового идентификатора в файле GEN / R.java. После этого остальные ссылки на этот ресурс пишутся без плюса.  (см. ниже -  ТЕОРИЯ: РЕСУРСЫ ).
Android: layout_width и Android: layout_height – мы не пишем конкретные размеры в мм, а используем значение wrap_content, которое указывает, что размер элемента подстраивается под размер его содержимого. Если бы мы указали значение "match_parent", то элемент стремился бы заполнить все свободное место на экране, так как родитель его - LinearLayout.
android:hint – этот атрибут описывает значение текстового поля по умолчанию, пока пользователь не ввел текст.   Мы не стали писать конкретный текст прямо в коде, а сделали ссылку на  ресурс, где и будет храниться наша текстовая строка. Поскольку тут ссылка не на идентификатор, а на конкретный ресурс, то знак + не пишем. Так как мы еще этот ресурс не описали, то компилятор выдаст ошибку, но мы ее исправим в следующем разделе.
Примечание: этот строковый ресурс имеет имя, совпадающее с идентификатором элемента (edit_message). Но так как типы ресурсов разные (строка и ID), то проблемы не будет.

                ТЕОРИЯ: РЕСУРСЫ.                             


Объект типа «ресурс» - это просто уникальный числовой идентификатор, ссылка на ресурс программы, например, - рисунок, текстовую строку или файл макета.  Каждому ресурсу в программе соответствует объект ресурса, описываемый в проекте в файле GEN / R.java. Имена объектов из класса R можно использовать для ссылок на конкретные ресурсы, например, указать, где находится текст значения по умолчанию (android:hint).
Также можно создать произвольные идентификаторы ресурсов для видимых элементов с атрибутом (Android:ID), которые позволяют ссылаться на эти элементы из другого кода.
Никогда не изменяйте вручную  файл  R.java! Он создается автоматически при компиляции программы. Подробнее о ресурсах и их размещении - http://developer.android.com/guide/topics/resources/providing-resources.html

Добавим строковый ресурс

Когда вам надо в интерфейсе показать некий текст, то всегда определяйте  каждый текст  как строковый ресурс. Строковые ресурсы позволяют вам сосредоточить все надписи в интерфейсе программы в одном месте, поэтому их проще искать и изменять. Особенно это полезно при переводе интерфейса  на несколько языков, когда каждый текстовый ресурс может иметь альтернативные описания.
По умолчанию в проекте строковые ресурсы находятся в файле res/values/strings.xml. Добавим новую строку под именем "edit_message" и установим ей значение "Enter a message." Кстати, строку "hello_world" можно удалить.
Заодно добавим строку под именем "button_send" со значением "Send" для надписи на кнопке.
В результате файл strings.xml должен выглядеть так:
<?xml version="1.0" encoding="utf-8"?>
<resources>
   
<string name="app_name">My First App</string>
   
<string name="edit_message">Enter a message</string>
   
<string name="button_send">Send</string>
   
<string name="action_settings">Settings</string>
   
<string name="title_activity_main">MainActivity</string>
</resources>
Попробуйте ввести русские значения строк: «Введите сообщение» и «Послать». Имена ресурсов не изменяем!
Тут сведения о том, как правильно строковые ресурсы использовать для многоязычных приложений (http://developer.android.com/training/basics/supporting-devices/index.html )

Добавим кнопку

Сразу после текстового поля добавим в макет элемент КНОПКА:
<Button
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:text="@string/button_send" />
Размеры кнопки установлены в "wrap_content" , чтобы кнопка подстраивалась под длину надписи на ней. Кнопке не нужен атрибут  Android: ID , потому что на нее из кода активности не будет ссылок.

Сделаем текстовое поле шириной во весь экран

Пока что размеры наших элементов такие, что им требуется минимальное место на экране (рис.).

Для кнопки – это нормально, но для текстового поля – плохо, если пользователь захочет ввести что-то подлиннее. Можно неиспользованную ширину экрана перераспределить в пользу текстового поля. Для этого применяют атрибут   android:layout_weight. (вес элемента).
Вес элемента – это число, которое определяет какую долю свободного места на экране должен занять элемент по отношению к другим элементам этого же уровня иерархии. Чем больше вес – тем пропорционально больше места занимает элемент. Это аналогично описанию рецепта: две части водки и 1 часть ликера. То есть в напитке – 2/3 водки.
По умолчанию все веса =0. Если задать вес>0 только для одного элемента, то он заполнит все свободное место, оставленное другими элементами. Если вес каких-то элементов  не задан, то они занимают только минимально необходимое место, а  остальная ширина окна делится между элементами с заданным весом>0 пропорционально значению веса. 
Таким образом, чтобы текстовое поле заняло все оставшееся от кнопки место, придадим ему вес 1.  Одновременно при этом для повышения эффективности программы лучше задать ширину текстового поля =0 (ODP), так как прежнее значение "wrap_content" требует от программы рассчитывать ширину родительского окна, которая тут не нужна: ведь применение веса заставляет программу рассчитывать ширину окна по другому алгоритму.
<EditText
Android: layout_weight = "1"
Android: layout_width = "0DP"
        ... />
Результат показан на рисунке:
В итоге всех изменений текст макета имеет вид:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   
xmlns:tools="http://schemas.android.com/tools"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
   
android:orientation="horizontal">
   
<EditText android:id="@+id/edit_message"
       
android:layout_weight="1"
       
android:layout_width="0dp"
       
android:layout_height="wrap_content"
       
android:hint="@string/edit_message" />
   
<Button
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:text="@string/button_send" />
</LinearLayout>
Этот макет будет применен к классу Activity, который был автоматически сгенерирован  во время создания нового проекта. 
Теперь можно запустить программу, чтобы посмотреть результат.  В Эклипсе нажмите кнопку Run.

Приложение с двумя Activity

Добавим код, который загрузит вторую активность, когда пользователь щелкнет по кнопке.

Ответ на событие кнопки

Откройте файл макета activity_main.xml  и добавьте к кнопке атрибут Android:OnClick. Значение этого атрибута – это имя метода, который будет  вызван при щелчке по кнопке.

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/button_send"
    android:onClick="sendMessage" />
Откройте класс MainActivity (он находится в папке проекта src/) и добавьте метод sendMessage:
/** Called when the user clicks the Send button */
public void sendMessage(View view) {
    // Do something in response to button
}
Он требует импортировать класс View – В Эклипсе нажмите  Ctrl + Shift + O. Обозначение метода должно точно совпадать!.
import android.view.View;

Построение намерения (Intent)

Интент (намерение) – это объект, который связывает отдельные компоненты, чаще всего он используется, чтобы начать новую Activity. Также он может передавать данные.
Внутри метода SendMessage () создайте намерение DisplayMessageActivity :
Intent intent =newIntent (this,DisplayMessageActivity.class);
Здесь используется 2 параметра:  контекст this и класс того компонента, к которому направлено  намерение (здесь – та Activity, которую надо запустить). В эклипсе будет выдана ошибка, так как эта активность и ее класс еще не описаны, но пока не обращаем на нее внимания.
В методе SendMessage ()используйте findViewById () , чтобы получить значение элемента EditText и добавить его к намерению:
Intent intent = new Intent(this, DisplayMessageActivity.class);
EditText editText = (EditText) findViewById(R.id.edit_message);
String message = editText.getText().toString();
intent.putExtra(EXTRA_MESSAGE, message);
Примечание: Теперь нужно импортировать эти команды в android.content.Intent и android.widget.EditText. Одновременно определите константу EXTRA_MESSAGE .
Намерение может нести собой набор данных различных типов, который называется EXTRAS, например, пары ключ-значение.  Метод PutExtra ()  принимает ключ в первый параметр и значение в качестве второго параметра.
Чтобы EXTRA-данные воспринялись следующей активностью, нужно описать ключ данных Вашего Интента с помощью общей константы. Для этого добавляем в начале текста класса  MainActivity  определение EXTRA_MESSAGE:
public class MainActivity extends Activity {
    public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";
    ...
}

Запуск  второй активности

Вызываем  startActivity () и передаем ему наше намерение. Система выполняет вызов и запускает новый экземпляр активности, определенной в этом намерении. Теперь полный текст кода метода SendMessage () выглядит так:
/** Called when the user clicks the Send button */
public void sendMessage(View view) {
   
Intent intent = new Intent(this, DisplayMessageActivity.class);
   
EditText editText = (EditText) findViewById(R.id.edit_message);
   
String message = editText.getText().toString();
    intent
.putExtra(EXTRA_MESSAGE, message);
    startActivity
(intent);
}
Теперь нужно создать класс DisplayMessageActivity, чтобы это заработало.

Создаем вторую активность:

1.     Нажмите кнопку NEW Новый на панели инструментов.
2.     В появившемся окне откройте папку Android и выберите Android Activity. Click Next.
3.     Выберите BlankActivity и нажмите кнопку Следующее .
4.     Заполните подробности (см.рис):
o   Проект : MyFirstApp
o   Название деятельности : DisplayMessageActivity
o   Имя макета : activity_display_message
o   Название : My Message
o   Иерархический Родитель : com.example.myfirstapp.MainActivity
o   Тип  навигации: None
Нажмите Finish.

Откройте файл DisplayMessageActivity.java. В эклипсе при создании активности:
- класс уже включает вставку для метода onCreate()
- также там есть заготовка метода onCreateOptionsMenu(), но он нам тут не нужен, его можно удалить,
- оставьте на месте заготовку метода onOptionsItemSelected(), который обрабатывает событие UP панели действий (ActionBar – панель в верхней части окна активности).
Поскольку элементы  ActionBar  доступны только на HONEYCOMB и выше (начиная с Андроид 11), необходимо добавить условие вокруг метода getActionBar () для проверки текущей версии платформы. Кроме того, необходимо добавить тег  @ SuppressLint ("NewApi")  в метод OnCreate (), чтобы избежать ошибок при компиляции.
Класс DisplayMessageActivity будет выглядеть так:
public class DisplayMessageActivity extends Activity {

   
@SuppressLint("NewApi")
   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       
super.onCreate(savedInstanceState);
        setContentView
(R.layout.activity_display_message);

       
// Make sure we're running on Honeycomb or higher to use ActionBar APIs
       
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
           
// Show the Up button in the action bar.
            getActionBar
().setDisplayHomeAsUpEnabled(true);
       
}
   
}

   
@Override
   
public boolean onOptionsItemSelected(MenuItem item) {
       
switch (item.getItemId()) {
       
case android.R.id.home:
           
NavUtils.navigateUpFromSameTask(this);
           
return true;
       
}
       
return super.onOptionsItemSelected(item);
   
}
}
В Эклипс обновите класс DisplayMessageActivity кодом, показанным выше.

Редактирование файла манифеста

Все Activity должны быть объявлены в файле манифеста  AndroidManifest.xml с помощью элемента <Activity>. Эклипс сам создает этот элемент при создании новой Активити, а при использовании другой оболочки его надо добавлять вручную. Примерный вид манифеста:
<application ... >
    ...
   
<activity
       
android:name="com.example.myfirstapp.DisplayMessageActivity"
       
android:label="@string/title_activity_display_message"
       
android:parentActivityName="com.example.myfirstapp.MainActivity" >
       
<meta-data
           
android:name="android.support.PARENT_ACTIVITY"
           
android:value="com.example.myfirstapp.MainActivity" />
   
</activity>
</application>
Примечание: Здесь атрибут android:parentActivityNameимя родительской активности, которое используется в Андроид 4.1 и выше для навигации по приложению. В более старых системах можно использовать библиотеку android.support,  и для этого добавляется элемент <meta-data>, как показано в примере. Эту библиотеку надо специально установить, если вы не применяете ADT Bundle, на шаге добавления платформ и пакетов.
Теперь в Эклипсе можно запустить программу на выполнение: после нажатия кнопки должна открываться новая активность все с тем же приветом по умолчанию «Hello world».

Получение намерения

Каждая активность вызывается Интентом (намерением).  Вы можете получить имя и данные того интента, который запустил текущую активность. Для этого есть метод getIntent (): вставьте в метод OnCreate () класса DisplayMessageActivity  команды:
Intent intent = getIntent();
String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);

 Вывод сообщения на экран

Создадим виджет  TextView и зададим текст сообщения с помощью setText(). Потом добавим его как корневой элемент в макет активности с помощью обращения  к методуsetContentView(). После этого метод onCreate() для DisplayMessageActivity будет выглядеть следующим образом:
@Override
public void onCreate(Bundle savedInstanceState) {
   
super.onCreate(savedInstanceState);

   
// Get the message from the intent
   
Intent intent = getIntent();
   
String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);

   
// Create the text view
   
TextView textView = new TextView(this);
    textView
.setTextSize(40);
    textView
.setText(message);

   
// Set the text view as the activity layout
    setContentView
(textView);
}
Можно теперь запустить программу. Когда она откроется, введите какое-то сообщение в текстовое поле, нажмите кнопку Send,  после чего во второй активности должно быть выведено это сообщение. Итак, ваша первая программа готова!



В заключение: прошу извинить за форматирование текста...