android TV アプリをamazon Fire TVに対応させる(またはamazon appstore審査で聞かれること)

#この記事は
Android TVアプリ開発者が自分の開発したアプリを amazon Fire TV に配信するまでに行った作業をまとめています。

##開発したアプリ

実際に開発したアプリはこちらの **EPGStationで録画を見る** になります。
リモコン片手にTV前のソファーに寝そべりながら大画面で見る、という怠惰な視聴スタイルでEPGStationの録画を消化したくなり作りました。

https://github.com/daig0rian/epcltvapp

なお↑のGitHub リポジトリには、Android Studio の New Project で プロジェクトを新規作成した直後の状態からの変更を登録しています。
何かと情報が少ないkotlin + Leanback の組み合わせのアプリの開発にお役立てください。

"EPGStationの録画を見る" は現在、 [Google Play Sotre](https://play.google.com/store/apps/details?id=com.daigorian.epcltvapp) と [amazon appstore](https://www.amazon.co.jp/dp/B0977CXK64/) の両方で公開されています。
<img width=45%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414368/9e27bf40-2088-b894-0428-708db731b398.png"> <img width=45%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414368/69cf0bc8-6289-8999-13cf-1c5c5a8041da.png">

では順番に見ていきます。

# やること1 : 必須 APIレベルを 22　まで落とす
日本で流通している主なFire TVのAPIレベルは↓の通りです。

- **Fire OS 5： Android 5.1ベース（Lollipop、APIレベル22）**
  - Fire TV - 第1世代（2014）
  - Fire TV Stick - 第1世代（2014）
  - Fire TV - 第2世代（2015）
  - Fire TV Stick - 第2世代（2016～2019）

- **Fire OS 6： Android 7.1ベース（Nougat、APIレベル25）**
  - Fire TV - 第3世代（2017）
  - Fire TV Stick 4K - 第1世代（2018）

- **Fire OS 7： Android 9ベース（Pie、APIレベル28）**
  - Fire TV Cube - 第2世代（2019）
  - Fire TV Stick - 第3世代（2020）

※ https://developer.amazon.com/ja/docs/fire-tv/fire-os-overview.html より引用整理


プライムデーの目玉商品としてよく出た "Fire TV Stick - 第2世代（2016～2019）" をカバーするにはminSdkVersion を22まで落としてやる必要があります。
また、Amazon appstore は公開途の中で minSdkVersion を落とすことができない(minSdkVersion を下げたapkを登録しようとすると怒られる)ので、
amazon appsotre へfire TV appを登録する場合は 初回公開時から22まで下げちゃうほうがいいと思います。
なおGoogle Play Sotreでは途中からminSdkVersion を下げることが可能でした。


具体的にはbuild.gradle を変更します。 

```gradle:app/build.gradle 
    defaultConfig {
        ...
        minSdkVersion 22
        ...
    }

```


# やること2：SearchSupportFragment() が 音声検索できないようにする
[Fire TV のリモコンのマイク](https://developer.amazon.com/ja/docs/fire-tv/remote-input.html)は Android TV のそれと違って、アプリから直接利用することができません。
leanback な android TVアプリでインアプリ検索を実装するために使われるのがSearchSupportFragment() ですが、FireTVではこのフラグメントが音声検索をスタートしないように修正する必要があります。でないと検索画面を開いた瞬間``java.lang.IllegalStateException: android.permission.RECORD_AUDIO required for search``でアプリがクラッシュして落ちます。

実際の修正はこんな感じ

```kotlin:app/src/main/java/com/daigorian/epcltvapp/SearchFragment.kt
...
class SearchFragment : SearchSupportFragment() , SearchSupportFragment.SearchResultProvider {
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        //もしAmazon Fire TV端末だった場合インアプリ音声検索は使えないのでコールバックをオーバーライドする
        if (requireContext().packageManager.hasSystemFeature(AMAZON_FEATURE_FIRE_TV)) {
            setSpeechRecognitionCallback {
                //Do Nothing
            }
            //　TODO Amazon Fire TV端末だったら"音声検索" プレースホルダーも混乱を招くので消す
            //　TODO Amazon Fire TV端末だったらマイクオーブも混乱を招くので消す
        }
        ...
    }
    companion object {
        ...
        private const val AMAZON_FEATURE_FIRE_TV = "amazon.hardware.fire_tv"
        ...
    }
}
```

この方法だと画面上のマイクオーブがの残ったままになるのでユーザが音声検索ができると勘違いしてしまう問題は残るのですが、いったんの対処としてはありだと思います。（某キャリアの某アニメストアの FireTV向けアプリもマイクオーブ残ったままでした）


# やること3：amazon appsotre の審査を通す
たぶん一番面倒な作業です。
###サマリ

今回私が経験した Google Play Store と Amazon appstore の審査の対応の違いをまとめてみました

|  | Google Play Store | Amazon appstore |
|:--|:--|:--|
| Passまでの所要時間  | 3 日間 |  17日間 |
| Reject 回数  | 0 回  | 6 回 |
| 審査用テストサーバ準備(テスト用認証情報) | なくても Pass | ないとReject | 

Google Play Storeがザルすぎるという感も若干ありますね。。

###特に厄介なReject理由：通称 The black-hole of Amazon's denial-of-entry system

特に「これどうしたらいいんだろう。。」となったのが以下のReject理由でした。

> Your app contains EPGStationの録画を見る. Please provide documentation demonstrating that you have the right to EPGStationの録画を見る by visiting the Contact Us page and selecting the category “Appstore” and the Topic “Content Policy Results”. The documentation must be either a confirmation letter from the intellectual property rights holder or a copy of the applicable license.
> 翻訳：アプリに"EPGStationの録画を見る"が含まれています。お問い合わせページにアクセスし、カテゴリ「Appstore」とトピック「コンテンツポリシーの結果」を選択して、"EPGStationの録画を見る"のコンテンツを表示する権利があることを示すドキュメントを提供してください。文書は、知的財産権所有者からの確認書または該当するライセンスのコピーのいずれかである必要があります。

要は権利を持たない第三者が権利者に成り代わってアプリをストアに並べるのを防ぐために、アプリの権利者であることを示す文章の提出を求めてきています。
ですがこのReject理由、一部では ["The black-hole of Amazon's denial-of-entry system."](https://forums.developer.amazon.com/questions/222009/confirmation-letter-from-the-intellectual-property.html) と揶揄されているほど何度も同じ理由で突き返されることがあるようです。。

今回は以下の対応でクリアすることができました。

- Github の LICENSE チュートリアルで ライセンスファイルを生成　https://github.com/daig0rian/epcltvapp/blob/master/LICENSE 
- LICENSE の Copyright (c) 行に amazon appstore申請に使用しているamazonアカウントのメールアドレスを記載する
- amazonに、ライセンスファイルのURLと、プロジェクトがOSSプロジェクトであること、自分がAutherであることなどを添えて回答する。



###そのほかのReject理由
>We are unable to test your app due to a lack of login credentials. Please provide credentials along with any testing instructions and re-submit the app.
> 翻訳:ログイン情報が不足しているため、アプリをテストできません。テスト手順とともにログイン情報を提供し、アプリを再送信してください。

> App must show videos contents to play and test the app functionality 
> 翻訳：アプリのテストをするために、アプリは動画コンテンツを表示する必要があります。

この時は初回でTestサーバ情報を渡していませんでした。
仕方がないのでGCPの無料枠を使ってインスタンスをひとつ立ててそこにEPGStationをデプロイ、さらにffmpegで生成したカラーバーをコンテンツとして登録して、そのＩＰアドレスを画面のどこに設定すればよいかをテスト情報として添えて提出しなおしました。


> The assets you have submitted to promote your app do not accurately reflect the content of your app. Please make sure that the long and short descriptions along with screenshots describe what users will experience when using your app.
> 翻訳：アプリを宣伝するために送信したアセットは、アプリのコンテンツを正確に反映していません。スクリーンショットと一緒に長い説明と短い説明が、ユーザーがアプリを使用するときに体験することを説明していることを確認してください。

どうもテスターが手元で表示している画面と、appstoreに表示するために提出したスクリーンショットが違いすぎると文句を言われるようです。コンテンツをバッサリ削除してスクリーンショットを取り直して登録


>While reviewing your app, we found that it is more appropriately categorized as 'Movies & TV' instead of 'Photo & Video'. We request you to resubmit your app under the 'Movies & TV' category as it will make it easier for users to find it.
> 翻訳：アプリを確認したところ、「写真と動画」ではなく「映画とテレビ」に分類されていることがわかりました。ユーザーが見つけやすくなるため、「映画とテレビ」カテゴリでアプリを再送信してください。

カテゴリが違うとのこと。そこまで見るんですね。。変更して再提出。

> We are unable to test your app as it does not function as intended. The app exits/ force closes/ freezes/ displays an error message after being launched. Please fix the issue and re-submit the app. Steps To Reproduce: 1.Install and launch the app 2.Play any video Actual Result: Observe the app video fails to load or displays error or keeps on loading. Expected Result: App video content should begin playback within 1 minute. Tested device:-Fire TV Stick Lite
> 翻訳：アプリが意図したとおりに機能しないため、アプリをテストできません。アプリの起動後、アプリを終了/強制終了/フリーズ/エラーメッセージを表示します。問題を修正して、アプリを再送信してください。再現手順：1。アプリをインストールして起動します2.ビデオを再生します実際の結果：アプリのビデオがロードに失敗するか、エラーが表示されるか、ロードを続けます。期待される結果：アプリのビデオコンテンツは1分以内に再生を開始する必要があります。テストに利用したデバイス：-Fire TV Stick Lite

再現手順までつけて問題の箇所を指摘してきてくれます。この時は初回起動時に自動的に画面がロードできないバグがあったのでそれを修正して出しなおしました。

### 最終的に
一通りの対応を終えると、提出から２日ほどで amazon appstoreに掲載されます。
appsotre への公開は、各国のamazon で実施されます。
日本のamazonで自分の公開したソフトを見るためには下記の画像のように、「amazon.comで見る」のリンクにあるASINを控えて
それをamazon.co.jpのサイトで探すことで見つけられます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414368/90dde8c2-6f86-720a-b7e6-20a5bae11b09.png)

現場からは以上です。