20200730のAndroidに関する記事は6件です。

Firebase Dynamic Links について

はじめに

Firebase Dynamic Links で Android の Deeplink を実装することになったので、そのメモとして残しておきます。

Android プロジェクトに Firebase を追加する

公式に手順がまとめられているの
https://firebase.google.com/docs/android/setup?hl=ja

※ SHA-1 情報は Firebase Dynamic Links で必要になるため忘れないようにする。さらに App Links を利用する場合は、 SHA-256 情報も必要になる。
※ ディープリンク URL は有効な URL でなければならない。

google-services.json をダウンロードして設定

app
└── src
    ├── main
    │   ├── AndroidManifest.xml
    │   ├── java
    │   └── res
    ├── dev
    │   └── google-servicesjson.json
    ├── stg
    │   └── google-services.json
    └── prd
       └── google-services.json

DynamicLinks の設定

コンソール上で作成する

or

手動で以下のようにする

{DynamicLinksのURL}/
?link={http(s)://で始まるリンク、主にアプリ用のURLエンコード済みのDeepLinkURL}
&apn={Androidアプリパッケージ名}
&ibi={iOSアプリバンドルID}
&isi={iOSアプリストアID}
&ius={iOSアプリをフックするカスタムスキーム}
&dfl={デスクトップ用リンク}

※ クエリパラメータを使う場合には基本的には後者を利用する

詳しくは以下をご覧ください
https://firebase.google.com/docs/dynamic-links/create-manually

Android で Firebase Dynamic Links を受信する

https://firebase.google.com/docs/dynamic-links/android/receive?hl=ja#kotlin+ktx

おわりに

まだ、きちんとした実装に入っていないため、追記+修正すると思います :sunglasses:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Android: VideoをBitmapに変換する

はじめに

Android で、Video のデコードは、MediaCodecで、簡単に実装できる。
が、MediaCodecではデコード結果は、ImageByteBufferとして取得できる。
これをBitmapに変換する方法に苦労したので知見をここに残す。

開発環境

Android, Kotlin

コード

サンプルコードは https://github.com/kenmasumitsu/VideoToImages 参照

解説

一言で言うと、
Android CameraXのドキュメント で言及されている、YuvToRgbConverter.kt を使って、 ImageBitmap に変換のがポイント。

ググると、

など見つかるが、うまく動かない。

は、正しく動くが、処理時間が長い。YuvToRgbConverter.kt の 約6倍。 (Pixel 3)

補足

https://bigflake.com/mediacodec/ で紹介されている、https://bigflake.com/mediacodec/ExtractMpegFramesTest_egl14.java.txt でも、同程度高速に正しく動作する。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

内部アプリ共有したアプリでGoogleログインができない

結論

内部アプリ共有では、ビルド時に指定した署名ファイルのSHA-1フィンガープリントではなく、内部アプリ共有用のフィンガープリントで、OAuthクライアントを指定してやる必要がある。

手順

AndroidでGoogleログインする際には、Google Developer ConsoleにてOAuthクライアントの認証情報を設定してやる必要がありますよね。
その際に、アプリの署名のSHA-1フィンガープリントを設定する項目があります。
image.png

内部アプリ共有でテスターにアプリを配信する際、この項目を内部アプリ共有用のSHA-1フィンガープリントにしてやる必要があります。
本番用の設定を変更して本番のアプリが動かなくなっても困るので、「内部アプリ共有用」とでも名前をつけたOAuthクライアント認証情報を新たに作成してやるのがいいかと思います。
パッケージ名は認証情報同士で重複しても平気なようです。

内部アプリ共有用のSHA-1フィンガープリント

で、その内部アプリ共有用のSHA-1フィンガープリントがどこで手に入るかというと、GooglePlay Consoleです。
内部アプリ共有の中に「アプリの証明書」というタブがあるので、その中にある「SHA-1 証明書のフィンガープリント」をコピーしてGoogle Developer Consoleに設定してあげてください。
image.png

背景

ローカルでUSB経由で実機にデプロイしたリリースビルドだと動作するのに、内部アプリ共有だとGoogleから「DEVELOPER_ERROR」が返ってきて何事だよ…と思ったらこういうことでした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

シンボルを見つけられません。import android.support.v4.app.ActivityCompatの読み込みエラー

ReactNativeでAndroidのネイティブモジュールを実装しようとしたところ、前使っていたコードが動かないことがわかりました。

/path/project/android/app/src/main/java/com/project/TestModule.java:28: エラー: シンボルを見つけられません
import android.support.v4.app.ActivityCompat;
                             ^
  シンボル:   クラス ActivityCompat
  場所: パッケージ android.support.v4.app

というエラーがでました。

どうやら、android.v4はサポートが切れ、
代替えとして、androidx.に移行する必要があるようです。

調べたところ、やることは2つで、

① dependencyの追加

build.gradleのdependenciesに

implementation "androidx.core:core-ktx:+"

を追加

② importするパッケージの変更

import android.support.v4.app.ActivityCompat -> import androidx.core.app.ActivityCompat
import android.support.v4.content.ContextCompat -> import androidx.core.content.ContextCompa

に変更することで動くようになります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

新卒プログラマの学習ログ 〜 其の二 〜

App Architecture

Codelabsをとりあえず一周、手を動かしながら進めてみました。

その中で、書かれているコードのパターンが、MVVM(Model-View-ViewModel)と呼ばれるアーキテクチャです。
Googleより推奨されているライブラリを用いた実装パターンで、これに従うことでメンテナンス性、可読性に優れたプログラムとして開発を行うことができるとされています。
しかし、普及としては割と最近のようで、Androidアプリ開発者用の参考書ではまだまだ異なるパターンの記述が多い印象です。

MVVMとは?

先述の通りModel-View-ViewModelを表しています。

Model

データを管理する役割を担います。
APIやデータベースを扱う際のDaoやdataクラスに当たります。

View

UIコントローラーの役割を担います。
画面表示や遷移、Fragmentの切り替えやユーザーのアクションを検知するリスナーをここで設定します。
Viewの管理はDataBindingのライブラリによって行っています。
下記のコードではフラグメントでの実装です。

MainFragment.kt
class MainFragment : Fragment() {

    // OnCreateView以外でも参照するため、lateinitで定義しておきます
    private lateinit var binding: MainFragmentBinding

    private lateinit var viewModel: ViewModel

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {

        binding = DataBindingUtil.inflate(
                inflater,
                R.layout.game_fragment,
                container,
                false
        )
        Log.i("MainFragment", "Called ViewModelProviders.of")

        // viewModelの取得
        viewModel = ViewModelProviders.of(this).get(GameViewModel::class.java)

        binding.sampleButton.setOnClickListener { onClick() }


        return binding.root
    }

    /** ボタンクリック時に実行するメソッド **/

ViewModel

Modelからデータを取得するViewとModel間の仲介的役割を担います。

とりあえず。。

メモ代わりに書いていますが、これから理解が深まれば書き足していきます。

初学者から一人前まで、、

ここでは一人前のプログラマの定義を
「おおよそ自力で様々なツールを活用しながら、ある程度思い通りの実装ができること」
とします。

また、人生においてプログラミングに向き合う時間として、現時点で2000時間取り組めればある程度の基盤が備わると仮定しています。
(言語やツールに依存しない思考法や情報収集能力)

プログラミングは大学で学んで来ましたが、特に根詰めてやってきていないので、ノーカウントとして取り組みます。

現在までの学習時間
およそ340時間
どんどん更新していきます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ConstraintLayout入門その3 - percent

ConstraintLayoutを使用するための設定については、ConstraintLayout入門その1をご覧ください。

ConstraintLayout自動変換があればFrameLayoutやLinearLayoutを捨てられる?

Android Studioは、レイアウトXMLファイルに書かれた既存のViewを他のViewクラスに自動変換する機能を持っており、これを使ってLinearLayoutなどをConstraintLayoutに変換することができます。しかし、本稿執筆時点の最新安定版のAndroid Studio ver.4.0.1でこの機能を試してみた結果は期待はずれ、とても自動変換だけでそのままアプリに使えるConstraintLayoutになってくれません。LinearLayoutで垂直ないし水平に並んだViewの並びをConstraintLayoutの制約表現に変える機能だけならまだしも、LinearLayoutでよく使われる android:layout_weight などの指定が入ったレイアウトをConstraintLayoutに変換するには手作業が不可欠のようです。本稿ではその辺りを突っ込んでみます。

percent

LinearLayoutは単に子Viewをまっすぐ並べるだけでなく、 android:layout_weight という属性を子Viewに持たせることによって、その長さを柔軟に設定することができます。ConstraintLayoutでは、 app:layout_constraintWidth_percent, app:layout_constraintHeight_percent の2つの属性がそれに近い機能を果たします。
ConstraintLayoutの他の多くの属性と同様、1つの子Viewに水平方向と垂直方向に独立にpercentを設定できる点において、LinearLayoutよりも柔軟です。

layout_constraint_1
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="horizontal"
    android:background="#CAEB5E"
    tools:showIn="@layout/activity_main">

    <TextView
        android:id="@+id/txtC11"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintWidth_default="percent"
        app:layout_constraintWidth_percent="0.167"
        android:gravity="center_horizontal"
        android:background="@drawable/rect_frame"
        android:textColor="@android:color/black"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/txtC12"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toEndOf="@id/txtC11"
        app:layout_constraintWidth_default="percent"
        app:layout_constraintWidth_percent="0.333"
        android:gravity="center_horizontal"
        android:background="@drawable/rect_frame"
        android:textColor="@android:color/black"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/txtC13"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toEndOf="@id/txtC12"
        app:layout_constraintWidth_default="percent"
        app:layout_constraintWidth_percent="0.5"
        android:gravity="center_horizontal"
        android:background="@drawable/rect_frame"
        android:textColor="@android:color/black"
        android:textSize="14sp" />

</androidx.constraintlayout.widget.ConstraintLayout>

上の記述例のポイントは、子Viewに android:layout_width="0dp" を設定しているところです。ConstraintLayoutは、「長さゼロ」に MATCH_CONSTRAINT, すなわち従来からの MATCH_PARENT や WRAP_CONTENT のような特別な意味を割り当てています。「長さゼロ」のときにのみ、 app:layout_constraintWidth_percent が無視されず意味を持ちます(同様に、 app:layout_constraintHeight_percent を有効にするには、 android:layout_height="0dp" が必要)。
一般に app:layout_constraintWidth_percent, app:layout_constraintHeight_percent には0から1の間の小数を設定し、親Viewの水平ないし垂直の長さとの比率を表します。
表示結果
上の表示例は、3つのTextViewを1:2:3の長さの比率で横に並べています。percentはチェーンでも使うことができ、1–3., 2–3. はチェーンを使っています。percentの合計が1に満たないようにすると、LinearLayoutで android:weightSum を設定して余白部分を余らせるのと同様の表示ができます。2–3. はチェーンの効果で均等配列されます。

LinearLayoutの完全上位互換ではない?

今回、LinearLayoutで android:layout_weight を使って表示できるレイアウトのすべてをConstraintLayoutで実現するつもりで記事を書いたのですが、筆者がやってみた限りでは、表示例の3. のように「子Viewにゼロを超える長さ (ここでは100dp) を与えておいてウェイト (ここでは1:2:3) を設定する」というケースをConstraintLayoutで表現できませんでした。
LinearLayoutでこのように設定すると、子Viewで幅を100dp (ここでは262.5px) ずつ確保しておいて、さらにLinearLayoutが持っている余白を1:2:3の比率で子Viewに分配する (48.5px, 97.5px, 146.5px) という2段階の長さ割り当てが行われます。
しかしConstraintLayoutのpercentではこのような割り当てができません。percentを設定する子Viewは「長さゼロ」を指定しなければならないので子View固有の長さを設定できません。 layout_constraintWidth_min を使っても同じようにはなりませんでした。
ConstraintLayoutはFrameLayoutやLinearLayoutなど配置用のViewGroupの完全上位互換を目指しているのかと筆者は勝手に考えていたのですが、そうではないのかもしれません。本当に上位互換でないのかどうかは、筆者の当面の宿題とさせていただくことにします。

サンプルコード

今回のサンプルコードは以下のリポジトリにあります。
https://github.com/csayamada/ConstraintLayout3

ConstraintLayout入門その1ConstraintLayout入門その2と歩みの遅いシリーズですが、ConstraintLayoutの習得は遠回りのようでも少しずつ出来ることを増やしていくのが確実だと思います。

参考文献

Constraintlayout | Android デベロッパー | Android Developers
ConstraintLayout | Android Developers

余談

percentという名を使っていますが百分率ではありません (1分率) 。 'proportion' などの名前にしなくてよかったのでしょうか…?

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む