ちょっとした知見置き場

Andoidアプリ開発における知見やメモをまとめておきます。

Epoxy(4.0.0-beta6) : package-info.java作成時にハマった話

Epoxy (4.0.0-beta6) でpackage-info.javaを作成時にハマった話

何があったか

※実装を見ていったりはしないです。ご注意ください。

この度初めてEpoxyを使ってRecyclerViewの実装をしていました。

Epoxyを使っていく中でpackage-info.javaを作成する過程があります。 READMEを参考に実装を進めていくと...

package-info.java

@EpoxyDataBindingLayouts({R.layout.header_view, ... // other layouts })
package com.airbnb.epoxy.sample;

import com.airbnb.epoxy.EpoxyDataBindingLayouts;
import com.airbnb.epoxy.R;

こちらを記述しなさいとのことですが、以下のようなエラーが出力されます。

エラー: 注釈型はこの種類の宣言に使用できません @EpoxyDataBindingLayouts({R.layout.header_view, ... // other layouts})

どのように解決するか

ReleaseNote 4.0.0-beta5によると

Breaking!

The annotation that support databinding, EpoxyDataBindingLayouts and EpoxyDataBindingPattern, must now be placed on a class or interface instead of in a package-info.java file. The interface or class must be in Java, Kotlin is not supported. This is necessary to support incremental processing.

とのことで

EpoxyDataBindingLayoutsEpoxyDataBindingPatternpackage-info.javaの代わりにclassやinterfaceに記述しろとのことでした。

Kotlinはサポートされておらず、Javaのみだそうです。

package com.example.app;
import com.airbnb.epoxy.EpoxyDataBindingLayouts;
import com.airbnb.epoxy.EpoxyDataBindingPattern;
@EpoxyDataBindingPattern(rClass = R.class, layoutPrefix = "my_view_prefix")
@EpoxyDataBindingLayouts({R.layout.header_view, ... // other layouts})
interface EpoxyDataBindingConfig {} 

公式にも記述されている通り、このように記述してあげるとうまく動きます。

おわりに

Epoxyを使ってみようとした時に、この壁に当たってしまってかなり時間を取られてしまいました。 困ったらReleaseNoteを読んでみるというのもありだなと勉強になりました。

やっとEpoxyを使った実装に入っていけそうです!!

アクションバーを消そうとしたらアプリ落ちた

何が起きたか

Androidアプリ開発の話です。

Jetpackのnavigationを使った上でアクションバー消そうとしたら、 (具体的なエラー名は分からなかったけど)アプリが開いてくれないという現象が起きました。

そもそもどうやってアクションバーを消すか

2種類紹介します。

  • values/styles.xmlのparentで ???.NoActionBar を継承
<resources>
    <!-- ココ!! -->
    <style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
</resources>
  • values/styles.xml<item name="windowsNoTitle">true</item> を追加
<resources>
    <style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
        <!-- ココ!! -->
        <item name="windowNoTitle">true</item>
    </style>
</resources>

いきなりですが、解決方法

navControllerを色々やってるところ(ActivityなりFragmentなり)

//落ちるコード
navController = Navigation.findNavController(this,R.id.nav_fragment)
bottomNav.setupWithNavController(navController)
NavigationUI.setupActionBarWithNavController(this,navController

もうお気づきかもしれませんが...

NavigationUI.setupActionBarWithNavController(this,navController)

この1行ですね。

どんなメソッドかというと(公式より)

By calling this method, the title in the action bar will automatically be updated when the destination changes (assuming there is a valid label).

developer.android.com

要するに、 このメソッドを呼び出すとアクションバーのタイトルが自動的に変更されるよ 的なことを言ってます。

だからこの1行を消してあげるとちゃんと動きます!!

結論

タイトルバーの名前を変更できるやつ使ってるのに、 タイトルバー消そうとしたらそりゃ上手くいくわけないよねって話でした。

割とピンポイントな現象だと思いますが、 ピンポイントな誰かの役に立つことができたら嬉しいです。 読んでいただきいただきありがとうございました。

CA Tech Dojo生、CA Tech Challengeに挑戦したってさ

なにがあったか

この夏株式会社CyberAgentインターンシップに参加しました。

インターンについて

CyberAgentのエンジニアインターンシップには大きく分けて3種類のインターンシップがあります。 更にその中から各分野に枝分かれしていく感じです。

僕はこちらに参加しました。

8/5-8/16(9営業日) : CA Tech Dojo Androidアプリ(Kotlin)編

9/9-9/11 : CA Tech Challenge AbemaTV Hack -クライアントサイド編-

どちらもAndroidでの参加です。 ハッカソンは初の参加となります。

こんなスタイルで書きます

TechDojoのブログはTechDojo生がたくさん書いてるので、 僕はTechDojoを経験した上でのTechChallengeっていう視点で書いてこうかなと思っております!

ここでTechDojoのブログを一部紹介します。

Challengeの課題はなんだったのか

公式での紹介はこんな感じ!!

AbemaTV Hack -クライアントサイド編-は、 サイバーエージェントの人気サービス「AbemaTV」において架空の新機能を実装していただくインターンです。 サイバーエージェントの現場で実際に働いているエンジニア社員のバックアップのもと、 お題とされる新機能を完成させることを目指していただきます。 完成した新機能は全体のコンセプト、コード、UI/UX等を総合的に評価します。 AbemaTVの核となる動画プレイヤーの部分はあらかじめ用意いたします。ここに、お題とされる架空の新機能を追加実装していただきます。

www.cyberagent.co.jp

ちょっと詳しく

本当に紹介通りでした。

  • 紹介通り架空の新機能を実装する
  • 動画プレイヤーは実装済
  • 動画データは用意されている
  • 設計: MVVMで実装されている

雰囲気

基本的には個人開発です。 メンターさんの人数は学生5人に対して2名でした(Androidチーム)。 質問があれば基本的にメンターさんにしますが、 学生同士教え合うこともありバチバチした感じではなく程よい緊張感のもと楽しく開発できます。 メンターさんはAbemaTV(現在、ABEMA)の開発をされている方なので ベースとなるコードの実装や動画周りの技術の質問にも詳しく答えてくださりました。 また、学生のアイデアを聞いて更に良いものを提案してくださったりもしました。 ハッカソンは競い合いのかなり敷居が高いものというイメージが強かったのですが、 誰か一人が分からないと発したらチーム全員反応して、 1つのPCを囲むなんてシーンも何度もありました。 完全に協力し合う雰囲気で、僕も死ぬほど助けてもらいました!! (iOS,Webフロントも同様です。)

実装について

何を実装したのか

僕のメインとなるオリジナル実装を紹介します。

「チャンネル関係なく今見ている番組の関連したものを提案する」

現状、AbemaTVはチャンネル毎にテーマは別れており、動画下に表示されるものは番組表なのですが、 僕の実装は狙いとして「今自分が見たいものを表示し、他チャンネルの視聴に繋げること」を挙げました。

どのように実装したのか

簡単に説明します。 jsonファイルの中身はざっくりいうと番組名・番組URL・番組IDなどなどでした。 そこにnewsなりsportなりのタグを追加で用意して、 Viewに表示する際にフィルターをかけて絞り込んであげる感じです。

他のサブ機能

  • 全体の番組表表示
  • light theme / dark themeで色を切り替える(TechDojoでの自由実装を活かした)
  • 動画をタップすると、番組詳細見れる
  • TVの一時停止(よくよく考えたら謎)

よかったらdark themeに関しての記事も書いてるので見てください。

zoothezoo.hatenadiary.com

TechDojoが活きた場面

ググり力

なんでもかんでも聞くよりも先にまず調べることが大事になると思います。 Dojoで2週間、 調べること自体の力、 考えに考えても無理になってから質問するメンタルを養ったので、 Challengeでも(質問はかなりしましたが)それなりに自己解決することはできたのかなと思います。

そもそもの技術

Dojoではどの技術使ってもいいから自由に実装してね!みたいな感じだったので、 基本的な機能を実装した後に自分の興味あることを学びました。

  • RecyclerView
  • Coroutine
  • Jetpackもろもろ
  • DarkTheme などなど

書ききれないですが、 こんなにも多くのことを学べました(逆にそれまでは何も知らなかった)。 Challengeではこれらの技術が平然とした顔で現れるので、 「本当にTechDojoで学んでよかった。Challengeで応用できてよかった。」 と感じました。

感想

コード美しすぎ案件

ベースとなるコードの話です。 思ったことをそのまま言うと「これがプロのエンジニアが書いたコードかぁ...」という印象です。笑

僕はDojoで初めて本格的にAndroidアプリ開発の勉強を始めたのですが、 ソースコードはぐっだぐだでファイル全てappの直下に置いてあったり、 「なんでそんなとこでviewいじってんの!?」みたいな、 もっと綺麗にコードかけるじゃんというのがたくさんあります。()

対して、 ベースのコードはディレクトリ分けもきれいに整理されており、 コードの責務も明確でした。 いろんなクラスを飛んで飛んで飛んで... 初心者の僕は「綺麗すぎて逆に分からん状態」でした。 それも例の如くメンターさん丁寧に説明していただいて、 やっと理解した気になれました。 コードの流れを知った時に本当に本当に感動しました。笑

まとめ

またまたCyberAgentさんにお世話になったのですが、 やっぱり最高でした!! どんどん新しい課題が見つかってくるので、 学ぶことが増えていきAndroidリア充になれそうです!! CyberAgentの社員さんともお話しさせていただいたり、 何より数少ない学生Androidエンジニアが、 日本中から集まって良い繋がりもできたことが嬉しくてしょうがないです。 もちろんAndroidだけじゃなく、iOS、WebFrontもです。 月1で報告会しよなんて言ってくれる仲間もいますし、 更に頑張っていかないと!!って思います!

最後まで読んでくれた方、 関係者のみなさんありがとうございました!!

ButtonでDarkThemeへ切り替え(Android)

概要

先日インターンシップでアプリを実装した際に, アプリを拡張をするということでDark Themeの実装にチャレンジしました.

という訳で今回のテーマは

ボタンでLightThemeとDarkThemeを切り替えられるように実装したい

です.

なお,初めての記事なので読みづらい点が多いと思いますが, お許しくださいませ.

何やったの

  • gradle: material designを使うよと定義
  • xml: res/night-valueを追加
  • kotlin: アプリのモードを取得して処理をする

具体的に何すればいいの

build.gradle(app)

build.gradle(app)のdependenciesに以下を追加

    //material design
    implementation 'com.google.android.material:material:1.1.0-alpha09'

XML

DayNightを継承する

DayNightのテーマを継承するため下記のどちらかを継承してあげる.

  • App Compat
<style name="AppTheme" parent="Theme.AppCompat.DayNight">
  • Material Components(自分はこっち)
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">

res/values-night

res/values(デフォルトである)と別にres/values-nightを作成. values-night内にcolor.xmlなりを定義してあげる. (自分はstyle.xmlをvaluesのみしか定義しなかったのですが, values-nightにも定義した方が良いのでしょうか... できてるからいいんですかね...)

一部のみ掲載します.

  • res/values/color.xml
    <!-- 青系 -->
    <color name="colorPrimary">#2196f3</color>
    <color name="colorPrimaryDark">#0069c0</color>
    <color name="colorPrimaryLight">#6ec6ff</color>
  • res/values-night/color.xml
    <!-- 紫系 -->
    <color name="colorPrimary">#4527a0</color>
    <color name="colorPrimaryDark">#000070</color>
    <color name="colorPrimaryLight">#7953d2</color>

Kotlin

以下でNightThemeを選択するか否かを指定することができる.

    AppCompatDelegate.MODE_NIGHT_YES
    AppCompatDelegate.MODE_NIGHT_NO

反映させるには以下に先ほど指定した状態を渡してあげる.

    AppCompatDelegate.setDefaultNightMode()

こちらで実装できました.

        //モードの初期化(LightThemeで)
        var mode: Int = AppCompatDelegate.MODE_NIGHT_NO
        nightbutton.setOnClickListener { //ボタン押すと...
            //現在のモードを取得できる
            var currentNightMode = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
            when (currentNightMode) {
                Configuration.UI_MODE_NIGHT_NO -> { // LightThemeの時の処理
                    mode = AppCompatDelegate.MODE_NIGHT_YES
                } 
                Configuration.UI_MODE_NIGHT_YES -> { // DarkThemeの時の処理
                    mode = AppCompatDelegate.MODE_NIGHT_NO
                } 
            }
            AppCompatDelegate.setDefaultNightMode(mode)
        }

スクリーンショット

色味などのエグみは今回は許してください笑

とりあえず切り替えはできたよとのことでよろしくお願いします.

  • Light Mode

  • Dark Mode

感想

今回は初めてのOUTPUTということで, 不慣れなところがご覧いただけると思いますが, これからも頑張ってちょいちょい記事書けたらなと思いますので, よろしくお願いします.

なお, コードやどんな些細なことでもアドバイスしていただけることがあれば, お待ちしております.