Android TVアプリの開発

このエントリーは、エキサイト Advent Calendar 2016 の 12/20 の記事です。

エキサイトとしては初のAdvent Calendar参戦です。


こんにちは、ビジネス開発技術部の伊藤です。
寝たまんまヨガは11月にAndroid TVへの対応を行いました。
今回はその時の開発について書こうと思います。

※ このページは、ある程度のAndroidの知識がある前提で書かれています。
※ 詳細な情報は、公式ドキュメントを参照ください。

アプリをAndroid TVに対応させる

アプリはそのままではAndroid TV用のアプリとして認識されないので、AndroidManifestに以下の定義を追加する必要があります。

下記のintent-filterを含むActivityを定義することで、ホームスクリーンからアプリを起動することができるようになります。
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>

Android TVにはタッチスクリーンの機能は存在しないため、タッチスクリーンの機能が不要であることを明記しなければなりません。
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />

ホームスクリーンに表示するアプリのバナーを登録します。
また、設定画面などではアプリのアイコンも表示されるため、こちらも忘れずに登録しておきましょう。
<application
---
android:banner="アプリのバナー"
android:icon="アプリのアイコン" >

以上で、晴れてAndroid TV用のアプリとして認識されるようになります!

必要な機能を実装する

ここからは、アプリに必要な機能を実装していきます。
Support LibraryにはLeanback LibraryというAndroid TV用のものが用意されており、これを使用することで手軽に便利なユーザーインターフェースを提供することができます。
今回はアプリの機能とLeanback Libraryが見事にマッチしていたため、フルに活用することにしました。

ブラウザ画面

ユーザーが一覧からアイテムを選択するような画面は、Leanback LibraryのBrowseFragmentで実現することができます。
下の画像が完成イメージです。
f0364156_11285732.png

概要

BrowseFragmentではアイテムをどのような配置にするかを決めます。今回はリスト型の配置としました。
行の情報はAdapter、一つ一つのセルはPresenterで情報を持ちます。

コード

※ 実際のコードとは異なります。
BrowseFragment

/* 配置をリスト型にするためListRowPresenterを使用 */
ArrayObjectAdapter baseAdapter = new ArrayObjectAdapter(new ListRowPresenter());
/* プレイリストにはImageCardPresenterを使用 */
ArrayObjectAdapter playlistAdapter = new ArrayObjectAdapter(new ImageCardPresenter());
--- playlistAdapterにプレイリストを詰める ---
ListRow playlistRow = new ListRow(new HeaderItem("プレイリスト"), playlistAdapter);

/* サービス概要にはTextPresenterを使用 */
ArrayObjectAdapter aboutAdapter = new ArrayObjectAdapter(new TextPresenter());
--- aboutAdapterにサービス概要を詰める ---
ListRow aboutRow = new ListRow(new HeaderItem("サービス概要"), aboutAdapter);

baseAdapter.add(playlistRow);
baseAdapter.add(aboutRow);
setAdapter(baseAdapter);
setOnItemViewClickedListener(アイテムタップ時のリスナー);
setOnItemViewSelectedListener(アイテム選択時のリスナー);

public class ImageCardPresenter extends Presenter {
--- プレイリストの定義 ---
}

public class TextPresenter extends Presenter {
--- サービス概要の定義 ---
}
f0364156_11294366.png

背景の変更

概要

Leanback Libraryには、背景を制御するためのBackgroundManagerが用意されています。
BackgroundManagerに画面を紐付け、リソースを設定することで背景を滑らかに変更することができます。
上記のBrowseFragmentと組み合わせることで、下記のような制御が可能です。
f0364156_18102149.gif

コード

※ 実際のコードとは異なります。
final BackgroundManager backgroundManager = BackgroundManager.getInstance(this);
backgroundManager.attach(getWindow());
setOnItemViewSelectedListener(new OnItemViewSelectedListener() {
@Override
public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, RowPresenter.ViewHolder rowViewHolder, Row row) {
Bitmap bitmap = --- itemで画像を取得 ---
backgroundManager.setBitmap(bitmap);
/* backgroundManager.setDrawable(画像); DrawableでもOK */
}
});

詳細画面

アイテムの詳細表示や、アイテムに対するアクションを行うような画面は、Leanback LibraryのDetailsFragmentで実現することができます。
下の画像が完成イメージです。
f0364156_11401383.png

概要

DetailsFragmentではどのような情報を表示するかを決めます。今回は詳細情報およびアクション、ロゴ画像を配置することにします。
基本的な構造はBrowseFragmentと同じです。

コード

※ 実際のコードとは異なります。
DetailsFragment

/* 詳細表示のPresenterを作成 */
FullWidthDetailsOverviewRowPresenter detailsPresenter = new FullWidthDetailsOverviewRowPresenter(new DetailsPresenter(), new LogoPresenter());
detailsPresenter.setBackgroundColor(詳細情報欄の色);
detailsPresenter.setActionsBackgroundColor(アクション欄の色);
detailsPresenter.setOnActionClickedListener(アクションタップ時のリスナー);

/* アクションを作成 */
ArrayObjectAdapter actionAdapter = new ArrayObjectAdapter();
--- actionAdapterにアクションを詰める ---

/* 詳細情報にアクションを設定 */
DetailsOverviewRow detailsRow = new DetailsOverviewRow(アイテム);
detailsRow.setActionsAdapter(actionAdapter);

/* アイテムのAdapterを設定 */
ClassPresenterSelector presenterSelector = new ClassPresenterSelector();
presenterSelector.addClassPresenter(DetailsOverviewRow.class, detailsPresenter);
ObjectAdapter itemAdapter = new ArrayObjectAdapter(presenterSelector);
itemAdapter.add(detailsRow);
setAdapter(itemAdapter);

public class DetailsPresenter extends AbstractDetailsDescriptionPresenter {
--- 詳細情報の定義 ---
}

public class LogoPresenter extends DetailsOverviewLogoPresenter {
--- ロゴの定義 ---
}
f0364156_11404379.png

再生画面

動画や音源を再生するような画面は、Leanback LibraryのPlaybackOverlayFragmentで実現することができます。
→ Leanback Library v25.1.0で、PlaybackOverlayFragmentはdeprecatedとなりました。代わりにPlaybackFragmentを使用してください。
下の画像が完成イメージです。
f0364156_11412738.png

概要

PlaybackFragmentでは再生情報の表示や各種アクションの設定を行います。
基本的な構造はBrowseFragmentと同じです。

コード

※ 実際のコードとは異なります。
PlaybackFragment

/* 再生制御のPresenterを作成 */
PlaybackControlsRowPresenter controlsPresenter = new PlaybackControlsRowPresenter(new PlaybackItemPresenter());
controlsPresenter.setBackgroundColor(アクション欄の色);
controlsPresenter.setOnActionClickedListener(アクションタップ時のリスナー);

/* 再生制御の情報を設定 */
PlaybackControlsRow controlsRow = new PlaybackControlsRow(item);
controlsRow.setTotalTime(合計の再生時間);
controlsRow.setCurrentTime(現在の再生時間);

/* 再生制御のアクションを設定 */
ArrayObjectAdapter actionsAdapter = new ArrayObjectAdapter(new ControlButtonPresenterSelector());
--- actionsAdapterにアクションを詰める ---
controlsRow.setPrimaryActionsAdapter(actionsAdapter);

/* 再生制御のAdapterを設定 */
ClassPresenterSelector presenterSelector = new ClassPresenterSelector();
presenterSelector.addClassPresenter(PlaybackControlsRow.class, controlsPresenter);
ArrayObjectAdapter controlsAdapter = new ArrayObjectAdapter(presenterSelector);
controlsAdapter.add(controlsRow);
setAdapter(controlsAdapter);

public class PlaybackItemPresenter extends AbstractDetailsDescriptionPresenter {
--- アイテム情報の定義 ---
}
f0364156_11414323.png
※ 上記は表示部分のみのため、実際の再生処理やそれに伴う表示の更新などは適宜実装してください。

おすすめコンテンツ

ユーザーに対しておすすめのコンテンツを表示することができます。下記のようなコンテンツを表示すると効果的です。
・ユーザーが現在体験していることの続きとなるコンテンツ
・新しく追加されたコンテンツ
・過去のユーザーの行動と関連性のあるコンテンツ
f0364156_11421313.png

概要

おすすめコンテンツは実際にはNotificationとして扱われ、ContentRecommendation.Builderを通して作成します。

コード

※ 実際のコードとは異なります。
Notification recommendation = new ContentRecommendation.Builder()
.setColor(選択時の色)
.setBadgeIcon(アイコン)
.setIdTag(タグ)
.setTitle(タイトル)
.setText(文言)
.setContentImage(画像)
.setContentIntentData(遷移先のインテント)
.build().getNotificationObject(context))

NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(通知ID, recommendation)
f0364156_11422847.png
以上で基本的な機能は実装することができました。

おわりに

Leanback Libraryは既存のAndroid開発で使うものとは少し毛色が異なっており、最初のうちは戸惑うことが多いかと思います。
ただ慣れてしまえば、一から実装するよりも遥かに簡単に一定の水準のものを作ることができるので、ぜひ挑戦してみましょう。

まだまだAndroid TVに対応しているアプリは少ないですが、これはまたチャンスということでもあります。
Android SDKやLeanback Libraryには上記で紹介した以外の機能も豊富に含まれているため、よりエキサイティングなアプリの作成を目指してみてください。
皆さんの手でどんどん盛り上げていきましょう!

明日はAndroidのアプリ内課金についてのお話です。わくわくしますね!

エンジニア募集

エキサイトではエンジニアとして一緒に働いてくださる方を
新卒採用中途採用で募集しています。
詳しくは、こちらの採用情報ページをご覧ください。


[PR]
by ex-engineer | 2016-12-20 00:00