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

Flutter2.0 インストール to mac

自己紹介

Flutterをほぼ触ったことがありません。またAndroidアプリ開発も4年前で知識が止まっています。Flutter2が出て、PCやwebにも対応したそうで、興味が出たので触ってみることにしました。

環境・やること

  • intel mac 11.2.1
  • Pixel 4a (Android 11)

まずAndroidアプリの開発から始める。他のプラットフォームで動くようにする方法は別途調べる。

VScodeを普段使っており、公式ドキュメントに説明もあるが、AndroidStudioのほうがなんとなく良さそうなので、そちらで始めてみる。

参考

macOS install

Flutter環境構築

zipファイルをダウンロード、適当な場所に解凍する。

PATHを通す。

# .zshrcとかに入れる
export PATH="$PATH:`適当な場所`/flutter/bin"
flutter doctor

をやってみると、

[✗] Android toolchain - develop for Android devices
    ✗ Unable to locate Android SDK.
      Install Android Studio from: https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK components.
      (or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).
      If the Android SDK has been installed to a custom location, please use
      `flutter config --android-sdk` to update to that location.

[✗] Xcode - develop for iOS and macOS
    ✗ Xcode installation is incomplete; a full installation is necessary for iOS development.
      Download at: https://developer.apple.com/xcode/download/
      Or install Xcode via the App Store.
      Once installed, run:
        sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
        sudo xcodebuild -runFirstLaunch
    ✗ CocoaPods not installed.
        CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage
        on the Dart side.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/platform-plugins
      To install see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.

と出たが、今回はAndroidの開発ができればいい(iPhone持ってない)のでAndroid開発環境を整える。

Android Setup

macOS install

android studioが必要らしいので、インストール。起動して、スタンダードに設定をしたら、「Downloading Compornents」となり、いろいろなコンポーネントがインストールされた。

macにUSBケーブルでPixel4aを接続。

Pixel側は開発者モードにして、USBデバッグを有効にする。

flutter devices

Pixel 4a (mobile)
Chrome (web)

と表示された。

Androidアプリ開発

Android Studioを開き、最初の画面の右下から「Plugin」を選び、「Flutter」で検索し、プラグインをインストール。

Android Studioを再起動すると、「Start a new Flutter project」というボタンが増えているので、それを選択>「Flutter Application」を選択>上でインストールしたSDKのパスがあっていることを確認しNext>プロジェクト名を適当に入れてFinish

プロジェクトができた。

すでにサンプルアプリが用意されているようなので、試しに手持ちのPixelで実行してみる。

上の方の再生マーク(Run)を押したら、なかなか始まらない。

* What went wrong:
Could not determine the dependencies of task ':app:compileDebugJavaWithJavac'.
> Failed to install the following Android SDK packages as some licences have not been accepted.
     build-tools;29.0.2 Android SDK Build-Tools 29.0.2
  To build this project, accept the SDK license agreements and install the missing components using the Android Studio SDK Manager.
  Alternatively, to transfer the license agreements from one workstation to another, see http://d.android.com/r/studio-ui/export-licenses.html

そしてこれが。

Tools>SDK managerからv29を入れてみた。

そしたらできた!

なんとなくコードいじって、変えてみました!(Hot reloadすごいですね)
Screenshot_20210304-220735.png

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

[Flutter]Android実機でOpenCV(C++,FFI)を搭載してデバッグビルドする方法

この記事では、備忘録も兼ねて、FlutterにおいてAndroid実機でOpenCV(C++,FFI)を搭載してデバッグビルドする方法と、それに付随して発生する問題やその解決法について記述する。

この方法でOpenCVを搭載するメリットについては、iOSに向けてビルドする場合とAndroidに向けてビルドする場合とで(KotlinやSwiftなどに)コードを分ける必要が無く、メソッドチャンネルなどの理解が難しい手法を取る必要もないとだけ簡潔に述べておく。

最初にビルドを行うまでの作業

Integrating C library in a Flutter app using Dart FFI | by Igor Kharakhordin | Flutter Community | Medium

まずはここを見るべし。
大前提として、OpenCVのライブラリをプロジェクトにブチ込んだり、ライブラリの依存関係をどう記述するかについての情報が載っている。なお、iOSの場合についても書いてある。

ただし、当ページの

In order to build and link the library and our code from native_opencv.cpp must be added to cmake (or ndk-build). Create CMakeLists.txt configuration file in android folder of the plugin:

の次に書いてある

cmake_minimum_required(VERSION 3.4.1)

include_directories(../include)
add_library(lib_opencv SHARED IMPORTED)
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libopencv_java4.so)

add_library(native_opencv SHARED ../ios/Classes/native_opencv.cpp)
target_link_libraries(native_opencv lib_opencv)

において、../include../ios/Classes/native_opencv.cppに関しては、もう一つ../を付けないとパスが合わないと思われるので注意。
ここがミスっていると、前者は「opencvが見つからないぜ!」と言われ、後者は「C++のソースコードが無いぜ!」と言われる。

ここまでで無事にビルドできれば万々歳だが、自分が作業を行った際は追加で

FAILURE: Build failed with an exception. 

* What went wrong:
Execution failed for task ':app:stripDebugDebugSymbols'.
> No toolchains found in the NDK toolchains folder for ABI with prefix: arm-linux-androideabi

という内容のエラーが発生した。以下に参考ページと、原因と思われるものを記述する。

NDK issue after flutter upgrade, No version of NDK matched the requested version 20.0.5594570. Versions available locally: 21.0.6113669 · Issue #53657 · flutter/flutter · GitHub

Gradle Pluginのバージョンが古い

今回の結論ではそうなった。プロジェクトを作ったのが半年以上前で、諸々の設定が古かったということも原因として考えられるため、最新の環境でプロジェクトを作り、上記の作業を行った場合は以下の作業が必要ない可能性もある。
あるいは、Gradle Pluginとその他の環境との食い合わせが悪かった可能性もある。

なんにせよ、今回採った対策としては、
(ProjectRoot)/android/build.gradleにおいて、

buildscript {
    dependencies {
        classpath 'com.android.tools.build:gradle:4.0.0'
    }
}

とし、Gradle Pluginのバージョンを4.0.0以上にする(変更箇所以外は省略してある)。

最終的には4.0.14.0.2でも通ったが、あまり重要ではないので割愛。

Gradleのバージョンも古い

しかし、これだけだと

> Failed to apply plugin [id 'com.android.internal.version-check'] > Minimum supported Gradle version is 6.1.1. Current version is *.*.*. If using the gradle wrapper, try editing the distributionUrl in (ProjectRoot)/android/gradle/wrapper/gradle-wrapper.properties to gradle-6.1.1-all.zip

とツッコまれる。

要約すると、「Gradleのバージョンが古いぜ!」ということ。

さっきGradle Pluginのバージョンを上げたのに、こっちではGradleのバージョンが古いとはどういうこっちゃ? となるが、Gradle と Gradle Plugin のバージョンについて - Qiitaによれば、Gradle Pluginとは

これはgradleって書いていますがAndroid plugin for Gradle(人によっては Gradle Plugin)と呼ばれているものでGradleそのものではありません。

簡単に言えばGraldeをAndroid Studioで使用するためのプラグインです。

とのこと。つまりは別物。

とりあえず、上記のエラーログにはどこをどう変更すれば良いのか親切に書いてあるので、指摘通りに(ProjectRoot)/android/gradle/wrapper/gradle-wrapper.propertiesを開き、

distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip

に変更。

NDKのバージョンも古い

しかしこれでもまだ、

> No version of NDK matched the requested version 21.0.6113669. Versions available locally: 23.0.7123448

とツッコまれる。少々疲れてくるが、次で最後。

これは、上記参考ページのdeakjahn氏がその答えを述べており、(ProjectRoot)/android/app/build.gradle(←先程のbuild.gradleとは別物なので注意)を

android {
    ndkVersion '23.0.7123448-rc1'
}

のように変更(該当箇所が無い場合は追記)することでビルドが通るようになる。

ただし、上記参考ページでdeakjahn氏が述べているように、GradleやGladle Plugin、NDKのバージョンを変更するたびにこの部分で引っかかる可能性がある。とはいってもビルドが通らないのはもっと困るので、今後注意を払うしかない。

ここで指定されるバージョンのNDKがインストールされているかどうかは、AndroidStudioを起動し、(Macでは)出てきたウインドウの右下からConfigure > SDK Manager > Android SDKSDK Toolsタブにおいて、右下のShow Package Detailsにチェックを入れ、NDKのツリーを見ればわかる。
該当するバージョンにチェックが入っていない場合はインストールされていないので、チェックを入れてApplyを押せばインストールウィザードが開始する。

なお、Version欄に記載されているバージョン名に、rc1など純粋な番号以外の記号が付属している場合、上記のようにハイフンでつないで記述する。一応忘れてもエラーログで記法を教えてくれる。

ここまでの作業を終えてなおビルドが通らない場合は、なにか別の原因が存在する可能性があるため、エラーログをよく確認することを推奨する。

蛇足

Gradleのバージョンも古い では、

distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip

としたが、書かれているURLにアクセスすれば、より新しいバージョンのGradleが配布されていることがわかる。今後の面倒を減らすためにも、6.1.1より新しいバージョンを入れておいてもいいかもしれない。

2021-03-04現在、6.8.3での動作を確認済み。

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

【Android】ボタンの色や形を動的に変更する

xml上での設定ではなく、ボタンの角丸・輪郭・押下時のレイアウト変更を動的に設定する方法のメモ。

手順

xmlでボタン作成

activity_main.xml
    <androidx.appcompat.widget.AppCompatButton
        android:id="@+id/button"/>

kotlin内でレイアウト定義

MainActivity.kt
        val drawable = GradientDrawable()
        //角丸
        drawable.cornerRadius = 200f
        //輪郭
        drawable.setStroke(6, Color.parseColor("#77ccff"))
        //ボタン押下時・通常時の色指定
        drawable.color = ColorStateList(
            arrayOf(intArrayOf(android.R.attr.state_pressed), intArrayOf()),
            intArrayOf(Color.parseColor("#88ddff"), Color.parseColor("#99eeff"))
        )
        //上記で設定したdrawableをボタン背景に設定
        binding.button.background = drawable
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Flutter bundle IDはどこで確認できる?

Flutterアプリ、bundle IDはどこで確認する?

アプリ初心者にとっては「bundle ID」がそもそも何なのかわからなかったりする。。
※AndroidではPackage nameと呼ばれてたりもします!

Flutterはプロジェクトを作成した時点で、「デフォルトのbundle ID」が作成されているので、それを確認してみましょう!!

また、bundle IDを変更する場合も同様の場所からできます。

Android

android/app/build.gradleで確認できます。

※build.gradleはandroid/build.gradleにも存在するので注意!
スクリーンショット 2021-03-04 15.29.35.jpg

// 省略
 defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "com.example.myApp" // これがAndroidのbundle ID
        minSdkVersion 16
        targetSdkVersion 28
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }
// 省略

iOS

Xcodeでios/Runner.xcodeprojを開いて確認します。
スクリーンショット 2021-03-04 15.39.44.jpg

RunnerをクリックしてGeneralの項目で確認できます。

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

コンフリクトしてるファイルをAndroid Studioで一気に開く方法

ちょっとしたチップスみたいなものです

Android Studioでファイルを開くコマンドを生成する

  1. Tools->Create Command-Line Launcher...
    image.png

  2. 適当な場所に保存
    image.png

  3. studioでファイルを展開できるようになる

コンフリクトしてるファイルの一覧を取得してstudioの引数に渡す

このコマンドを叩けばOK

git ls-files -u | cut -f 2 | sort -u | xargs studio

あとは、、、

お好みに合わせてaliasつけたりすれば完璧

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

Navigation Componentの使い方(概要〜画面遷移〜データの受け渡し編)

はじめに

Jetpackで追加された、 Navigation Component を調べたいな〜とずっと考えていましたが、ようやく使い方が理解できたので使い方をこの記事では説明します。

動作環境

この記事の動作環境は以下のとおりです。

Android Studio:4.1.1
Kotln:1.4.21
Open JDK:1.8
compileSdkVersion:30
targetSdkVersion:30
minSdkVersion:23
Navigation Component:2.3.2

目標

以下を目標とします。

  • 基本的な利用方法を理解する
  • 画面遷移方法を理解する
  • 画面間でデータの受け渡しを行う方法を理解する

動作イメージ

この記事の最終動作イメージは下図です。

サンプルコード

早くサンプルコード見せろって方は下記からダウンロードしてください。

github

Navigation Componentの概要

まずはNavigation Componentって何???って話をしていきます。
Androidアプリ開発において、画面遷移は全体像を理解するために、各画面を作成してからOfficeなどを使い、画面遷移図を作成しているかと思います。
iOSアプリ開発ではStoryboardが存在し、IDE上で視覚的に画面遷移が理解出来ます。
Androidアプリ開発でも、Storyboardのように視覚的に直感で画面遷移が理解出来ます。
それだけではなく、メリットがあります。公式サイトではその他にも以下のメリットを上げていますね。

  • フラグメント トランザクションを処理する。
  • デフォルトで「上」アクションと「戻る」アクションを正しく処理する。
  • アニメーションと遷移用の標準化されたリソースを提供する。
  • ディープリンクを実装して処理する。
  • 最小限の追加作業で、ナビゲーション ドロワーやボトム ナビゲーションなどのナビゲーション UI パターンを組み込める。
  • Safe Args - 宛先間で移動とデータの受け渡しを行う際に型の安全性を提供する Gradle プラグイン。
  • ViewModel のサポート - ViewModel のスコープをナビゲーション グラフに設定して、グラフの宛先間で UI 関連のデータを共有できます。

なかなか、いろんな事が簡単に実現できそうな感じです。
フラグメントのトランザクション管理をやってくれるのは本当にありがたいです。
ということは、Navigation Componentってのは、どうやらFragmentを使って実現しているようです。
フラグメントで最低限の知識がないかも不安って方はFragmentの基本を参照してください。

実装方法

必要なファイル郡

それでは、実装方法について説明します。
実装するにも、何から手をつけてよいやらと思います。
Navigation Componentで必要となるActivityやFragmentを図にしてみました。

01_navigation_componentの概要.png

以下のファイル群が登場します。

  • navigationの設定ファイル(XML)
  • Activity
  • Fragment

それぞれの役割をまとめるとこの様な感じです。

ファイル 役割
Activity Fragmentのコンテナが基本的な役割だが、アクションバーやツールバー、ナビゲーションドロワーの制御を行います。
Fragment 実際に表示する画面や機能を持つ
navigationの設定ファイル(XML) 画面遷移や画面間のデータの受け渡しの設定、画面遷移のアニメーションの設定などを管理する

navigationの設定ファイルで画面遷移を表現すると言ったところです。
内部的にはActivityのコンテナ部分でFragmentを操作しているようです。

Fragmentを準備する

必要なファイル群を理解すると、navigationの設定ファイルを作る前にFragmentなどを事前に準備しておく必要があることが分かります。

まずはBlankでもいいので、Fragmentを3ほど用意してみます。

02_Fragmentの準備.png

今回は以下の3つのFragmentを用意しました。そのぞれの画面の役割も説明します。

Fragment名 役割
StartFragment 名前が入力でき、FirstFragmentやSecondFragmentに遷移するボタンを保持する。入力した名前をFirstFragmentやSecondFragmentに受け渡す
FirstFragment StartFragmentから画面遷移してきて、入力した名前を受け取る。受け取った名前を表示する
SecondFragment FirstFragmentと同じくStartFragmentから画面遷移してきて、入力した名前を受け取る。受け取った名前の文字数を表示する

これで必要なFragmentが準備できました。

navigationの設定ファイル作成

Fragmentが準備できたらnavigationの設定ファイルを作成します。
これはAndroid StudioのGUI操作でサクサク作れます。
手順は以下のとおりです。

  1. resを右クリック
  2. Resource TypeNavigation を選択。
  3. name にファイル名を入力、今回は my_navi を入力
  4. 必要なライブラリーがbuild.gradleのdependenciesに存在しない場合、ダイアログが表示されるため、OKを押下
  5. res フォルダに navigation フォルダが作成され、my_navi.xmlファイルが出来ている事を確認する

実際の操作画面は下図です。

03_navigationの設定ファイル(XML)の作成.png

家マークが付いているFragmentは、初期画面を意味します。初期画面の設定は画面上部の家マークで変更可能です。

Fragmentをnavigation設定でFragmentの追加と接続

navigationの設定ファイルが作成したら、いよいよ、Fragmetの画面遷移をGUIで表していきます。

画面(Destination:デスティネーション)の追加

まずは、navigationの設定ファイルにFragmentを追加しましょう。
手順は以下のとおりです。

  1. new destinationボタンをクリック
  2. 対象のFragmentをクリック

Navigation Componentでは、Fragmentの事をDestination(デスティネーション)と呼ぶようです。

今回は以下の3つを追加します。

  • StartFragment
  • FirstFragment
  • SecondFragment

実際の操作イメージは以下のとおりです。

04_destienationの追加.png

追加が完了すると左下のComponent Treeに追加したデスティネーション(画面)が表示されます。

画面遷移の線(Action:アクション)を接続

デスティネーション(画面)が追加できたら、画面遷移の線で表します。
線のことを アクション と呼びます。
アクションの接続手順は以下のとおりです。

  1. 遷移元のデスティネーション(画面)の右端に表示する○から遷移先にドラッグアンドドロップします。

実際の操作イメージは下図の通りです。

05_destinationをつなげる.png

接続が完了するとComponetTreeにもアクションが表示されます。

Activityの設定

navigationの設定ファイルがある程度完成したら、Activityのコンテナを設定して作成したNavigation Componentを設定していきます。

手順は以下のとおりです。
1. Activityのレイアウトファイルを開く
2. プロジェクト作成時に生成されたTextViewなどは削除しておく
3. デザインタブが選択された状態にする
4. Palette の検索で fragment と入力
5. NavHostFragment を画面にドラッグアンドドロップする
6. NavHostFragment の選択ダイアログが表示したら、作成したnavigation設定ファイルのmy_naviを選択する

実際の操作イメージは下図の通りです。

06_activityへの適応.png

NavHostFragment を追加した後にCodeタブで確認をするとFragmentに警告が出ています。どうやら、 FragmentContainerView に変更すべし!!と出ているので修正します。
FragmentContainerViewについてはご自身で調べてください。

以下のように修正されていれば問題ありません。

07_Fragmentタグの修正.png

ここまで設定が出来たら、動作確認を行ってみました。

StartFragment の画面が下図のように表示されれば問題ありません。
この時点で、画面遷移は起きません。
なぜなら、画面遷移の処理を記述する必要があるからです。

08_動作確認.png

画面遷移

画面遷移するためには処理の記述が必要です。どの様な処理を記述するのかを公式サイトで調べてみると、以下の手順になるようです。

  1. NavHostを取得
  2. NavHostから以下のいずれかでNavControllerを取得
    1. Fragment.findNavController()
    2. View.findNavController()
    3. Activity.findNavController(viewId: Int)
  3. アクションを取得
  4. navigateでアクションを指定し画面遷移

ここでは、以下の2つが重要な役割を果たしているようです。

  • NavHost
  • NavController

それぞれの役割の概要は以下のとおりです。

クラス名 役割
NavHost Navigation用の単一コンテナ。直接操作せずに、NavControllerを通じて操作する。NavControllerを渡すメソッドを保持している。
NavController NavHostを保持し、アプリケーションのNavigationを管理する。NavControllerが保持しているデスティネーションはナビゲーショングラフ(navigation設定ファイル)によって異なる

どうやら、画面遷移にはNavControllerで行う事がわかります。

では、NavHostを取得しようと考えたら、Navigation Componentを利用するのであれば、 Safe Args を利用して、タイプセーフに移動することを推奨しているようです。
Safe Args を利用するとAndroid Studioの入力補完も効くので、オススメです。

Safe Args を利用するにはbuild.garadleに以下の修正を加える必要があります。

build.gradle(project)
dependencies {
    def nav_version = "2.3.2"
    classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
}
build.gradle(app)
apply plugin: "androidx.navigation.safeargs.kotlin"

appのbuild.gradleですが、プロジェクトによっては以下のように修正する必要があります。

build.gradle(app)
plugins {
    id 'androidx.navigation.safeargs.kotlin'
}

ここまで出来たら、ビルドしておきます。
公式サイトには、pluginを追加すると遷移元のデスティネーションからクラスが自動生成されるとのことですが、実際はされないのでビルドし直してAndroid Studioに生成してもらいます。

リビルドは下図の手順で行ってください。

09_リビルド.png

準備が整ったので、画面遷移を実装していきます。
今一度、手順を振り返っておきます。

  1. NavHostを取得
  2. NavHostから以下のいずれかでNavControllerを取得
    1. Fragment.findNavController()
    2. View.findNavController()
    3. Activity.findNavController(viewId: Int)
  3. アクションを取得
  4. navigateでアクションを指定し画面遷移

NavHost を取得するとあります。しかし、ここまで、 NavHost なんてものを定義した記憶はありません。
実は、Activityのコンテナに設定しています。
Activityのレイアウトリソースファイルを見てみます。

actitivy_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/my_navi"
        />
</androidx.constraintlayout.widget.ConstraintLayout>

FragmentContainerViewの android:name 属性を確認してみると、しっかり ** NavHostFragment** って記述がありますね。
どうやら、Activityにコンテナを設定したときにAndroid Studioが自動で設定してくれたみたいです。 app:navGraph 属性には、navigationの設定ファイルが指定されていますね。
ここで紐付いているようです。
なるほど、しかも公式サイトにはこんな記述があります。

FragmentContainerView を使用して NavHostFragment を作成する場合、または FragmentTransaction からアクティビティに NavHostFragment を手動で追加する場合、Navigation.findNavController(Activity, @IdRes int) からアクティビティの onCreate() で NavController を取得しようとするとエラーになります。NavHostFragment から直接 NavController を取得してください。

フラグメントを取得してそのままキャストすればいいとのことです。
なるほど、われわれはこうなるわけですね。

StartFragment.kt
// NavHostの取得
val navHostFragment =
    requireActivity().supportFragmentManager.findFragmentById(R.id.host_fragment) as NavHostFragment

次にNavControllerを取得します。NavControllerはNavHostから取得するので下記の記述になります。

StartFragment.kt
// NavController取得
val navController = navHostFragment.navController

続いてActionを取得しましょう。

公式サイトに下記の記述があります。

Safe Args を有効にすると、このプラグインによって、定義した各アクションのクラスとメソッドを格納するコードが生成されます。

そうでしたね。自動でクラスを生成してくれるのでした。
アクションはその線の元に内部クラスとして生成されます。
今回は、StartFragmentから線を延ばしました。そのため、自動生成されたStartFragmentのクラスから取得します。
自動生成されるクラス名は以下のとおりです。

まずはFragmentのクラス名は以下のとおりです。

Fragmentのクラス名 + Directions

なので、StartFragmentは StartFragmentDirections という名前のクラスが生成されます。そしてそのクラスの内部クラスとしてActionのクラスが生成されます。

Actionのクラス名はnavigationの設定ファイルで指定したActionのid属性から生成されます。
変換ルールは「スネークケース→ローワーキャメルケース」
navigationの設定ファイルをcodeタブで確認すると下記のようになっています。

my_navi.xml
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/my_navi"
    app:startDestination="@id/startFragment">

    <fragment
        android:id="@+id/startFragment"
        android:name="jp.co.casareal.navigationcomponent_sample.StartFragment"
        android:label="fragment_start"
        tools:layout="@layout/fragment_start" >
        <action
            android:id="@+id/action_startFragment_to_firstFragment"
            app:destination="@id/firstFragment" />
        <action
            android:id="@+id/action_startFragment_to_secondFragment"
            app:destination="@id/secondFragment" />
    </fragment>
</navigation>

今回の場合は以下のように変換されます。

action_startFragment_to_firstFragmentActionStartFragmentToFirstFragment

変換ルールを理解したところで、実際にActionを取得するコードを確認します。
Actionを取得するには、idをローワーキャメルケースのメソッドを呼び出します。

StartFragment.kt
val action =
    StartFragmentDirections.actionStartFragmentToFirstFragment()

Actionが取得できたら、いよいよ、最後の画面遷移です。
NavControllerのnavigateメソッドの引数にActionのオブジェクトを渡して呼び出すだけです。

StartFragment.kt
navController.navigate(action)

この時点で動作確認をすると、入力したデータを遷移先の画面に受け渡しができてないですが、しっかり画面遷移できます。

10_画面遷移.png

画面間のデータの受け渡し

Navigation Componentで画面間のデータの受け渡しはいくつかやり方があります。
事前に Safe Args を有効 しているため、navigationの設定ファイルにデータを受け渡す設定をします。

データの受け渡しのイメージとしては、遷移先のFragmentに変数を設定し、Actionを取得する際にその変数に値を格納するイメージです。

11_データの受け口.png

設定ファイルはXMLなので、コードで編集も可能ですが、GUIでも設定が可能です。
手順は以下のとおりです。

  1. GUIでせっていする場合は、navigationの設定ファイルを開く
  2. デザインタブを選択する
  3. データを受け取る (遷移先の)Fragment を選択する
  4. Arguments の「+」ボタンをクリック
  5. 表示されたダイアログの nameを入力する
  6. type を選択する

実際の画面間イメージは下図の通りです。

12_データの受け口の設定方法.png

Codeタブを開くと下図のように遷移先のFragmentに argument タグが定義されます。

my_navi.xml
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/my_navi"
    app:startDestination="@id/startFragment">
    <fragment
        android:id="@+id/firstFragment"
        android:name="jp.co.casareal.navigationcomponent_sample.FirstFragment"
        android:label="fragment_first"
        tools:layout="@layout/fragment_first" >
        <argument
            android:name="nameForConfirm"
            app:argType="string"/>
    </fragment>
</navigation>

受け渡しできるデータの方は下記の通りです。
詳細は公式サイトを確認してください。

記述例
Integer app:argType="integer"
Float app:argType="float"
Long app:argType="long"
Boolean app:argType="boolean"
String app:argType="string"
参照 app:argType="reference"
Parcelable app:argType=""
Serializable app:argType=""
Enum app:argType=""

大体の型には対応しています。

遷移先にデータを受け渡すコードを記述していきます。
Actionを取得する際に、呼び出すメソッドに受け渡すデータを設定します。

StartFragment.kt
val action =
    StartFragmentDirections.actionStartFragmentToFirstFragment(nameForConfirm = strName)

最後にデータを受け取る処理です。
navigationの設定ファイルにargmentタグを追加すると、設定したFragmentのクラスから以下のルールでクラスが自動生成されます。

フラグメントのクラス名 + Args

FirstFragment であれば FirstFragmentArgs となります。

実際に取得するには navArgs 関数を呼び出します。

FirstFragment.kt
class FirstFragment : Fragment() {

    // データが格納されているargsを取得
    private val args:FirstFragmentArgs by navArgs()

}

args:FirstFragmentArgs が取得できればあとは簡単です。
FirstFragamentArgsのプロパティにnavigationの設定ファイルのargmentのname属性で指定した名前で追加されています。

実際のコードは下記のとおりです。

FirstFragment.kt
args.nameForConfirm

以上でデータの受け渡しが完了です。

まとめ

Navigation Componentの基本的な利用方法は多くあるため、覚えるのだけでも一苦労です。
しかし、他にも機能があるのでしっかり覚えておくことをおすすめします。

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