Введення в розробку додатків для Android TV

Дана стаття познайомить вас з розробкою простої програми для Android TV. В першу чергу вона орієнтована на тих, хто вже мав якийсь досвід в розробці додатків для Android, тому я не буду тут пояснювати що таке Activity, Fragments і т. д.

В інтернеті є багато російськомовної інформації по розробці додатків для Android і не мало статей з написання HelloWord для нього ж. Зацікавившись розробкою додатків для Android TV, я відразу ж почав вивчати цю тему на англомовних сайтах. На мій подив матеріалу виявилося не так вже й багато, і я вирішив подивитися що ж є російською. Російською нічого знайти не вдалося (можливо погано шукав). Загалом я маю намір виправити цю ситуацію.

Так як інтерфейс додатків для телефонів Android TV має істотні відмінності, то ми повинні створити інтерфейс програми, відповідний для взаємодії на TV. Наприклад, нам слід створювати додатки з якими можна взаємодіяти, використовуючи тільки клавіші ↑ ↓ → ←. В реалізації такого інтерфейсу нам може допомогти бібліотека LeanbackSupport, що дозволяє легко створювати UI, який буде зручний при роботі з додатками на Android TV.

Створення проекту в Android Studio
Запустивши Android Studio, необхідно створити новий проект. При створенні вибрати платформу TV і вказати мінімальну версію SDK. Android Studio запропонує нам створити «Android TV Activity», однак на даний момент слід вибрати «No Add Activity», т. к. якщо ви виберіть створення Activity, то AS створить багато класів і файлів, в яких спочатку складніше розібратися.

Створення Activity
Для початку необхідно створити новий XML файл під ім'ям activity_main.xml, який буде містити розмітку для нашої Activity. Код розмітки ми змінимо пізніше.

Тепер слід створити клас успадкований від Activity. Для цього потрібно створити новий клас з ім'ям MainActivity і успадкувати його від класу Activty. Визначити метод onCreate(Bundle SIS) і встановити в ньому вміст для Activity зі створеного файлу розмітки.

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R. layout.activity_main);
}
}

Оголошення Activity у файлі маніфесту програми
Якщо ви спробуєте запустити додаток на даному етапі, то воно звісно не запуститься, так як у файлі AndroidManifest.xml у нас не оголошено ні однієї Activity.

Файл маніфесту потрібно додати наступний код.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.simpletvapp">

<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
<uses-feature
android:name="android.software.leanback"
android:required="true" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.Leanback">
<activity
android:name=".MainActivity"
android:icon="@drawable/app_icon_your_company"
android:label="@string/app_name"
android:logo="@drawable/app_icon_your_company" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

Тепер розберемо деякі моменти. Частину коду наведена нижче відключає тач.

<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />

В цій частині ви вказуєте, що додаток повинен запускатися тільки на Android TV. Якщо ви розробляєте додаток не тільки для TV, то вам слід встановити значення false.

<uses-feature
android:name="android.software.leanback"
android:required="true" />

При оголошенні Activity ми вказуємо в intent-filter, що Activity повинна запускатися на Android TV.

<category android:name="android.intent.category.LEANBACK_LAUNCHER/>

Створення фрагменту
Зараз потрібно створити клас Java з ім'ям MainFragment і успадкувати від класу BrowseFragment з бібліотеки LeanbackSupport. BrowseFragment дозволяє створити стандартний інтерфейс додатків для Android TV.

Тепер ми можемо прив'язати створений фрагмент до нашої Activity, для цього в файл розмітки Activity (в моєму випадку це activity_main.xml) слід помістити наступний код розмітки.

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_browse_fragment"
android:name="com.simpletvapp.MainFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />

Запуск програми
Щоб запустити додаток, потрібно створити емулятор Android TV. Його можна створити в Android Virtual Device Manager.

Після створення емулятора можна запустити на ньому наш додаток. На даний момент воно має наступний вигляд.



Тут ви бачите порожній BrowseFragment. Ви можете побачити RowsFragment в лівій частині додатка (фрагмент відповідає за відображення списку заголовків) і HeaderFragment в правій частині екрана (відповідає за відображення контенту заголовків).

Далі ми заповнимо HeaderFragment, RowsFragment і розглянемо їх докладніше. Перед цим встановимо основні кольори UI і назву програми.

Налаштування стилю програми
Тут я додав метод setupUI() MainFragment.java і викликав його у визначений методі onActivityCreated.

@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setupUI();
}


private void setupUI() {
setTitle("Hello Android TV!");
int color = ContextCompat.getColor(getActivity(), R. color.fastlane_background);
setBrandColor(color);
}

Якщо ви запустите додаток на даному етапі, то ви повинні побачити ось такий UI.



Заповнення BrowseFragment
Давайте спочатку розберемося на прикладі готового додатки Android TV зміст BrowseFragment. Кожен заголовок у лівій частині фрагмента (HeaderItem) має ряд з контентом в правій частині. Комбінацію «заголовок (HeaderItem) + контент в правій частині додатка», містить клас ListRow. Зміст BrowseFragment являє собою список з ListRow. Заголовок і список з контентом в правій частині має відношення один до одного.



Розглянемо ListRow детальніше. За список з контентом відповідає ArrayObjectAdapter. В даному випадку CardInfo це елемент контенту. CardInfo може бути будь-яким об'єктом. Як створити і відобразити CardInfo ми розглянемо пізніше.



Зараз ми можемо зробити наступні висновки:

ArrayObjectAdapter — відповідає за список з ListRow
ListRow = HeaderItem (заголовок) + ArrayObjectAdapter (список контенту в правій частині)

Клас Presenter
Заповнення елементів контенту визначається за допомогою класу Presenter з библотеки LeanbackSupport. Він визначає відображення елемента контенту. Presenter є абстрактним класом, тому ми повинні створити новий клас і успадкувати його від Presenter. Коли ви створите новий клас, ви повинні визначити як мінімум 3 методи:

onCreateViewHolder(ViewGroup parent);
onBindViewHolder(ViewGolder, viewHolder, Object item);
onUnbindViewHolder(ViewHolder viewHolder);

Presenter містить внутрішній клас ViewHolder, який дозволяє посилатися до View (елемент контенту). Ми можемо отримати доступ до View через ViewHolder за конкретні події, наприклад в методах класу Presenter onBind() або onUnbind()

Заповнення HeadersFragment і RowsFragment
Давайте перейдемо до справи. Тут ми створюємо клас GridItemPresenter успадкований від класу Presenter. У цьому додатку Object (елемент контенту) відображає рядок, а ViewHolder містить у собі TextView для відображення цього рядка. View створюється в методі onCreateViewHolder(), а її заповнення проводиться в методі onBindViewHolder().


public class GridItemPresenter extends Presenter {

private static final int WIDTH_ITEM = 300;
private static final int HEIGHT_ITEM = 200;

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent) {
TextView view = new TextView(parent.getContext());
view.setLayoutParams(new ViewGroup.LayoutParams(WIDTH_ITEM, HEIGHT_ITEM));
view.setFocusable(true);
view.setFocusableInTouchMode(true);
view.setGravity(Gravity.CENTER);
view.setBackgroundColor(ContextCompat.getColor(parent.getContext(), R. color.default_background));
view.setTextColor(Color.WHITE);
return new ViewHolder(view);
}

@Override
public void onBindViewHolder(ViewHolder viewHolder, Object item) {
TextView textView = (TextView) viewHolder.view;
String str = (String) item;
textView.setText(str);
}

@Override
public void onUnbindViewHolder(ViewHolder viewHolder) {

}
}

В клас MainFragment додаємо метод loadRows() і викликаємо його в зумовленій методі onActivityCreated()

private void loadRows() {
// адаптер, який відповідає за ListRow (ListRow = заголовок + контент)
ArrayObjectAdapter rowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
// клас відповідає за заголовок, в конструкторі вказуємо що це перший заголовок у списку,
// і сам заголовок содерэит текст "Заголовок 1"
HeaderItem headerItem = new HeaderItem(0, "Заголовок 1");
// наш клас, відповідальний за заповнення елементів контенту
GridItemPresenter itemPresenter = new GridItemPresenter();
// адаптер, відповідає за відображення контенту в правій частині
ArrayObjectAdapter gridAdapter = new ArrayObjectAdapter(itemPresenter);
// додавання трьох елементів контенту
gridAdapter.add(0, "Эемент 1");
gridAdapter.add(1, "Эемент 2");
gridAdapter.add(2, "Эемент 3");
// у адаптер, який відповідає за ListRows, додаємо ListRow.
// конструктор передаємо клас, відповідальний за заголовок і адаптер, який відповідає за
// відображення вмісту
rowsAdapter.add(new ListRow(headerItem, gridAdapter));
setAdapter(rowsAdapter);

}

Тепер ви можете запустити додаток і побачити екран представлений нижче.



На цьому все. У цій статті я спробував пояснити деякі з основних принципів створення програми для Android TV.

За основу даної статті були взяті і туторіали.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.