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

【Android】SplitInstallManagerのListenerで期待する動作がしなくて困った話(備忘録)

環境 PC M1 MacBook Air Android Studio Arctic Fox 2020.3.1 Beta 3 Google Play Core Library com.google.android.play:core-ktx:1.8.1 困ったこと DFMを実装する際、 SplitInstallStateUpdatedListener の REQUIRES_USER_CONFIRMATION を通らないことがある sample.kt private val listener = SplitInstallStateUpdatedListener { state -> when (state.status()) { SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION -> { splitInstallManager.startConfirmationDialogForResult(state, this, DFM_REQUEST_CODE) } SplitInstallSessionStatus.DOWNLOADING -> { // do something } else -> { // do something } } サンプルコード↓ https://github.com/sasakitomohiro/DFMSample 原因 REQUIRES_USER_CONFIRMATIONはモジュールサイズが150MBを超える場合でないと通らないらしい?ことが原因っぽい その他、wifi接続している状態かどうかや端末によって挙動が変わるらしい https://issuetracker.google.com/issues/171501820
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Kotlin研修4日目】コンテキストメニューの実装

コンテキストメニュー ListViewなどを長押しした際に表示される小さなポップアップメニュー。 コンテキストメニューの実装 参考: 研修4日目 コンテキストメニューを実装する手順は、以下の通り。 resフォルダ内に、Resource Type: menuのAndroid Resource Directoryを作成 1.で作成したフォルダ内に、Menu Resource File(.xmlファイル)を作成 アクティビティクラスに、コンテキストメニューを生成するためのonCreateContextMenu()メソッドを実装 アクティビティクラスのonCreate()メソッド内に、生成したコンテキストメニューを表示するためのregisterForContextMenu()メソッドを記述 コンテキストメニューのItem選択時に呼び出されるonContextItemSelected()メソッドに、選択されたコンテキストメニューItemに応じた分岐処理を記述 Menu Resource Fileの記述 コンテキストメニューのItem含むレイアウトを定義するXMLファイル。 Menu Resource File 参考: メニューリソース アプリ内に実装する各種メニューのレイアウトを定義するXMLファイル。 メニューには、コンテキストメニューのほか、オプションメニュー、サブメニューが含まれる。 定義 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/<ItemID>" android:title="@string/<strings.xmlで定義した文字列の変数名>" /> </menu> コンテキストメニューの生成 参考: ContextMenu コンテキストメニューの表示時に呼び出されるonCreateContextMenu()メソッドのブロック{...}内に、 コンテキストメニューのItemを定義したXMLを表示するMenuInflater.inflate()メソッドを記述する。 また、コンテキストメニューにヘッダタイトルを表示させる場合はContextMenu.setHeaderTitle()メソッドを記述する。 定義 MenuInflater.inflate(menuRes: Int, menu: Menu!): Unit // パラメータ // menuRes: メニューのレイアウトファイル名(R値) // menu: インフレートを行うメニュー ContextMenu?.setHeaderTitle(titleRes: Int) // パラメータ // titleRes: ヘッダタイトルの文字列ID(R値) サンプルコード MainActivity.kt class MainActivity: AppCompatActivity() { // コンテキストメニュー表示時に呼び出される処理 override fun onCreateContextMenu( menu: ContextMenu?, view: View?, menuInfo: ContextMenu.ContextMenuInfo? ) { super.onCreateContextMenu(menu, view, menuInfo) // コンテキストメニューのレイアウト(XML)のインフレート menuInflater.inflate(menuRes: Int, menu: Menu!): Unit // ヘッダタイトルの定義 menu?.setHeaderTitle(titleRes: Int) } } ListViewへのコンテキストメニューの登録 定義 Activity.registerForContextMenu(view: View!): Unit // パラメータ // view: コンテキストメニューを表示するビュー サンプルコード MainActivity.kt class MainActivity: AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { val lvMenu = findViewById<ListView>(R.id.lvMenu) ... // 生成したコンテキストメニューを指定したビュー(ListView)に登録 registerForContextMenu(lvMenu) } } コンテキストメニューのItem選択時の処理 参考: 研修2日目 コンテキストメニューもオプションメニューと同様、アイテムが既定でリスナとして定義されているため、アイテム選択時に呼び出されるonContextItemSelected()メソッドを用いて、選択されたアイテムに応じた分岐処理(イベントハンドラ)を実装する。 ※アイテムが選択されない場合は、super.onContextItemSelected()の返り値(=false)を返却する必要がある。 サンプルコード MainActivity.kt class MainActivity : AppCompatActivity() { // コンテキストメニューItemの"タップ"イベント検知時の処理(イベントハンドラ) // onContextItemSelected(item:): オプションメニューのItemがタップされた場合に呼び出されるメソッド // item: タップされたItem override fun onContextItemSelected(item: MenuItem): Boolean { // 最終的に返却するBool値(初期値: true) var returnVal = true // AdapterContextMenuInfoオブジェクトの定義 // -> コンテキストメニューを呼び出したItemの情報を格納 val info = item.menuInfo as AdapterView.AdapterContextMenuInfo // コンテキストメニューを呼び出したItemのIndex番号 val listPosition = info.position // コンテキストメニューを呼び出したItemのキーと値を格納するMutableList val menu = _menuList[listPosition] // タップされたItemに応じた分岐処理 // MenuItem.itemId: ItemのID(R値) when(item.itemId) { R.id.menuListContextDesc -> { // トースト表示する文字列 val desc = menu["desc"] as String // 表示するトーストの定義 val toast = Toast.makeText(this@MainActivity, desc, Toast.LENGTH_LONG) // トーストの表示 toast.show() } R.id.menuListContextOrder -> ... else -> // オプションメニューのItem以外が選択された場合は、 // 親クラス(super)のonContextItemSelected(item:)メソッドの // 返り値(デフォルトではfalse)を返却 returnVal = super.onContextItemSelected(item) } return returnVal } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ブラウジングを高速化する、最強のChrome flags 15選

本記事は、Diwakar Kumar氏による「Top Chrome Flags You Should Enable to Boost Your Browsing」(2021年4月16日公開)の和訳を、著者の許可を得て掲載しているものです。 ブラウジングを高速化する、最強のChrome flags 15選 はじめに ほとんどの人はChromeの動作を重く感じるでしょう。これは、RAM、プロセッサ、ストレージオプションなどのPCの仕様が低いことが原因です。しかし、その解決のためにできることは何もありません。代わりにChromeで今できることを最大限に利用したらどうでしょう。Chromeには実験的なオプションがいくつかあり、Chromeの動作を変更できます。一般的には「Chrome flags」と呼ばれています。Chrome flagsのオプションは、オン/オフを切り替えられます。 これはAndroid端末の開発者向けオプションに似ています。多くの人がAndroidの開発者向けオプションを使って、Android携帯のユーザーエクスペリエンスを向上させています。 Chrome flagsとは? Google Chrome flagsは、さまざまな実験的オプションです。実験的とは、試せるオプションのことで、ほとんどのオプションは不安定か、今後のアップデートで正式導入される予定です。Mac、Windows、Android、iOSのすべてのプラットフォームで楽しむことができます。chrome://flagsをペーストするだけで、実験的な機能を網羅したページが表示されます。 有効にすべきChrome flags 以下のChrome flagsで、Google Chromeをより快適に使えます。 1. Parallel Downloading その名の通り、このChrome flagは並行ダウンロードに役立ちます。複数のダウンロードプロセスを同時に実行でき、とても便利です。1つのダウンロードプロセスから複数のプロセスが作成されることで、ダウンロードプロセスが高速化します。IDM(Internet Download Manager)と同じ方法で、ダウンロードを断片(接続)に分割します。 有効にするには、URLに#enable-parallel-downloadingと入力します。 2. Smooth Scrolling Chrome flagの中でも、これは特に有効にする価値があります。このflagは、その名の通り機能します。スムーズなスクロールアニメーションで、スクロール中のコンテンツの揺れが軽減します。私たちも使ってみましたが、本当に素晴らしいflagです。コンテンツを見ている時に揺れを感じたら、ぜひ試してみてください。 有効にするには、URLに#smooth-scrollingと入力します。 3. Horizontal Tab Switcher (Android) このChrome flagを使えば、古くて退屈なChromeタブの縦スクロールを横スクロールに切り替えられます。Chromeで複数のタブを開いたままにする習慣のある人には便利です。タブにすぐアクセスして、コンテンツを見ることができます。 有効にするには、URLに#enable-horizontal-tab-switcherと入力します。 4. Password Generation このflagは、サービスにサインアップする時に、強力なパスワードを生成するのに役立ちます。推測するのに何世紀もかかるような、本当に難しいパスワードが必要な時に便利です。 有効にするには、URLに#automatic-password-generationと入力します。 5. Block Downloads Chrome flagsの中でも、これは、ファイルダウンロード時のセキュリティ維持に役立ちます。このflagは、ファイルが何らかのコードを実行する可能性がある場合、疑わしいファイルのダウンロードをブロックします。この機能を試してみてください。 有効にするには、URLに#disallow-unsafe-http-downloadsと入力します。 6. Scroll Anchor Serialization これはChrome公式バージョンにあったものですが、なぜGoogleが削除してChrome flagsに移動させたのかは分かりません。Androidで、ウェブページで最後にスクロールした位置を保持できます。そのページに戻ると、最後のスクロール位置から始まります。これは、Microsoft Officeにあるような機能です。オンラインで小説を読むのが好きな人にとっては、本当に便利です。使ってみれば便利なツールだと分かるでしょう。主に携帯用ですが、デスクトップでも使えます。 有効にするには、URLに#enable-scroll-anchor-serializationと入力します。 7. Graphics enhancements これらのflagsは、S/Wエンコーディングの代わりにH/Wエンコーディングを使えるようです。レンダリングでGPUを優先します。自分で試してみて、違いがあるか確認してみてください。私たちは違いをほとんど感じませんでした。 2Dキャンバスの高速化:#disable-accelerated-2d-canvas S/Wレンダリングリストのオーバーライド:#ignore-gpu-blacklist 8. Tab Grouping このChrome flagを使うと、タブの管理がうまくできます。多くのタブを同時に開いている人には便利です。似たようなタブを簡単にグループ化して、作業を楽にできます。また、小さな画面、つまりAndroidやiOSなどの携帯で役に立つと思います。 有効にするには、URLに#tab-groupsと入力します。 9. Tab Hover Card (Chromeのダウンロード用に)Microsoft Edgeを使ったことがあるかもしれませんね。もししばらく使っていたなら、タブをマウスオーバーすると、タブのプレビューが表示されることを知っているはずです。同じような機能が、このChrome flagにもあります。これは、タブを開かずに、タブに関する情報を知るのに役立ちます。しかし、この分野ではMicrosoft Edgeの方が優れています。 有効にするには、URLに#tab-hover-cardsと入力します。 10. QUIC Experimental Protocol 接続をより高速で安定したものにしたい時は、このChrome flagが最適です。Googleは新しいプロトコル、QUICプロトコルを開発中です。これは、TCPとUDPを併せ持つもので、速度や安定性など、接続が改善します。また、セキュリティ面でも優れています。TCPとUDPは、安定した安全な接続のために、何度も通信を行います。これに対してQUICは、1回の接続要求ですべての処理を完了します。そのため、システムはより速く、安定して安全になります。 有効にするには、URLに#enable-quicと入力します。 11. Enable Dark Mode ダークモードは、多くの人を魅了してやみません。人は、集中できる環境と薄暗い光の中で働くのが大好きです。ダークモードがそれをかなえてくれます。この最強Chrome flagは、Chromeのダークモードをオンにできます。 有効にするには、URLに#enable-force-darkと入力します。 12. Chrome Reader Mode 他のブラウザを使ったことがあれば、そのブラウザが提供する読書モードに精通しているはずです。読書モードは、メインコンテンツを表示し、ウェブサイト上の気が散る要素はすべて排除します。このChromeの機能で、コンテンツに集中できるようになります。 有効にするには、URLに#enable-reader-modeと入力します。 13. Play/Pause button for Media ブラウジング中、いくつかのウェブサイトから音楽を聴いているでしょう。このChrome flagを使えば、メディアの再生を一ヶ所から一時停止できます。これにより、オンラインでメディアを再生/一時停止したりする時の混乱を防ぐことができます。このflagで、タブを開かずにメディアをコントロールできます。 有効にするには、URLに#global-media-controlsと入力します。 14. Zero-Copy Rasterization ブラウザは画面上にすべてのウェブコンテンツをレンダリングします。Chromeで(特に)で使われているプロセスは「ラスタライズ」です。flagの説明によると、このオプションは、すべての「タイル」をGPUメモリに転送します。これにより、Chromeのパフォーマンスは確実に向上します。試してみてください。 有効にするには、URLに#enable-zero-copyと入力します。 15. Pull to Refresh on PC スマートフォンで下にスワイプするとコンテンツが読み込まれるのを見たことがあるはずです。このChrome flagを使えば、PCでも同じことができ、PCやノートパソコンでPull-to-Refreshジェスチャーが使えます。 有効にするには、URLに#pull-to-refreshと入力します。 おわりに ここでご紹介したChrome flagsを試して、より良いChrome体験をしてください。もしこのリストに掲載されていないChrome flagsがあれば、使っているflagsをぜひ教えてください。 おすすめChrome flagsリスト どのChrome flagsを試すべきか悩んでいるなら、こちらを最初に試すと良いでしょう。 Smooth Scroll Tab Grouping Parallel Downloading QUIC Protocol Dark Mode もっと技術コンテンツを読みたい方は、私達のFacebookに「いいね」したり、Twitter、Instagram、Pinterestをフォローしたり、YouTubeチャンネルを登録したりしてください。 翻訳協力 この記事は以下の方々のご協力により公開する事ができました。改めて感謝致します。 Original Author: Diwakar Kumar (@kumardiwakar98) Original Article: Top Chrome Flags You Should Enable to Boost Your Browsing Thank you for letting us share your knowledge! 選定担当: @gracen 翻訳担当: @gracen 監査担当: - 公開担当: @gracen ご意見・ご感想をお待ちしております 今回の記事はいかがでしたか? ・こういう記事が読みたい ・こういうところが良かった ・こうした方が良いのではないか などなど、率直なご意見を募集しております。 頂いたお声は、今後の記事の質向上に役立たせて頂きますので、お気軽に コメント欄にてご投稿ください。Twitterでもご意見を受け付けております。 皆様のメッセージをお待ちしております。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

(Unity)SimpleSQL使用時の「DllNotFoundException: sqlite3」エラー対応

UnityでSQLiteを使うに当たって、評価の高い「SimpleSQL」を使ってます。 これまでiOS向けにしかビルドを試していなかったので、Android向けにビルドしたところ以下のエラーが。。。 E/Unity: DllNotFoundException: sqlite3 ググったところ、Plubinsフォルダの配下に以下のフォルダを用意し、 libsqlite3.soを三つのフォルダそれぞれにいれる arm64-v8a armeabi-v7a x86 との先人の記事が出てきたため、試行しましたが上手くいかず。。。 そこでSimpleSQLのドキュメントをよく読むことに(当然ですね) 解決方法 メニューから、Tool > SimpleSQL > Option を選択 ここで、Optimize PlatformからAndroidを選択するとAssets直下に以下のフォルダが自動で作成され、 sqlite-android-328000が配置されます。 Plugin/Android/sqlite-android-3280000 これで解決します... 結論、ドキュメントをよく読めってことです。。。 ではでは。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Kotlin研修4日目】独自レイアウトのListView、アクションバーへのオプションメニューの実装

独自レイアウトのListView ListViewのItemを独自レイアウトで定義する手順は以下の通り。 res/layoutフォルダに独自定義するレイアウトファイルを用意 Adapterオブジェクトの生成時、SimpleAdapter(context:data:resource:from:to:)のresourceおよびtoに、独自定義したレイアウトファイルのR値を指定(後述) SimpleAdapterオブジェクト生成時のR値 MainActivity.kt SimpleAdapter( context: Context!, data: MutableList<out MutableMap<String!, *>!>!, resource: Int from: Array<String>! to: IntArray! ) // パラメータ // context: Adapterを生成するアクティビティオブジェクト(=コンテキスト) // data: Adapterに紐づけるリストデータ // resource: リスト形式ビュー(ListView)のItemのレイアウトを表現するR値 // from: リストデータ(MutableMap)のキー // to: リストデータ(MutableMap)の値を埋め込むTextViewのR値(ID) Android SDKで用意されたレイアウトを用いる場合のR値はandroid.R.、 独自定義したレイアウトファイルを用いる場合のR値はR.から始める。 パラメータ Android SDK 独自定義 resource android.R.layout.simple_list_item_2 R.layout.<レイアウトファイル名> to intArrayOf(android.R.id.text1,android.R.id.text2) intArrayOf(R.id.<TextViewのid>,R.id.<TextViewのid>) アクションバー アプリ上部に表示されるバー。 オプションメニュー アクションバー内に表示される、アイコン形式のメニュー。 オーバーフローメニュー アクションバー内に十分な余白がなく表示できないオプションメニューが格納される、文字列形式のメニュー。 オプションメニューの実装 参考: メニュー オプションメニューを実装する手順は、以下の通り。 resフォルダ内に、Resource Type: menuのAndroid Resource Directoryを作成 1.で作成したフォルダ内に、Menu Resource File(.xmlファイル)を作成 アクティビティクラスに、オプションメニューを表示するためのonCreateOptionsMenu()メソッドを実装 アクティビティクラスに、オプションメニューのアイテムが選択された場合の処理を記述するonOptionsItemSelected()メソッドを実装 Menu Resource Fileの記述 オプションメニューのItem含むレイアウトを定義するXMLファイル。 Menu Resource File 参考: メニューリソース アプリ内に実装する各種メニューのレイアウトを定義するXMLファイル。 メニューには、オプションメニューのほか、コンテキストメニュー、サブメニューが含まれる。 定義 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/<ItemID>" app:showAsAction="<アクションバーへの表示設定>" android:title="@string/<strings.xmlで定義した文字列の変数名>" android:icon="@drawable/<アイコンID> /> </menu> showAsAction Activityクラスの継承元 属性 通常のActivity android:showAsAction AppCompatActivity app:showAsAction showAsActionの属性値 属性値 内容 never オーバーフローメニューに格納 always 常にアクションバーに表示(非推奨) ifRoom スペースに余裕があればアクションバーに表示余裕がない場合はオーバーフローメニューに格納 icon アクションバーに表示する場合(=オプションメニュー)は指定したアイコンのみ表示され、 オーバーフローメニューに格納する場合はtitleの文字列のみ表示される。 サンプルコード res/menu/menu_options_menu_list.xml <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menuListOptionSetMeal" app:showAsAction="never" android:title="@string/menu_list_options_setMeal" /> <item android:id="@+id/menuListOptionCurry" app:showAsAction="never" android:title="@string/menu_list_options_curry" /> </menu> オプションメニューの表示 アクティビティ開始時に呼び出されるonCreateOptionsMenu()メソッドのブロック{...}内に、 オプションメニューのItemを定義したXMLを表示するMenuInflater.inflate()メソッドを記述する。 定義 MenuInflater.inflate(menuRes: Int, menu: Menu!): Unit // パラメータ // menuRes: メニューのレイアウトファイル名(R値) // menu: インフレートを行うメニュー サンプルコード MainActivity.kt class MainActivity: AppCompatActivity() { // 定義したオプションメニューの表示 // onCreateOptionsMenu(menu:): アクティビティ開始時に呼び出されるメソッド // menu: Itemを保持するオプションメニュー override fun onCreateOptionsMenu(menu: Menu?): Boolean { // レイアウトファイルのインフレート menuInflater.inflate(R.menu.<XMLファイル名>, menu) // onCreateOptionsMenu()のオーバーライド時は、常にtrueを返却 return true } } インフレート(inflate) .xmlファイルに記述したビューをJavaオブジェクトとして実体化すること。 オプションメニューのアイテム選択時の処理 オプションメニューのアイテムは、既定でリスナとして定義されているため、 アイテム選択時に呼び出されるonOptionsItemSelected()メソッドを用いて、 選択されたアイテムに応じた分岐処理(イベントハンドラ)を実装する。 ※アイテムが選択されない場合は、super.onOptionsItemSelected()の返り値(=false)を返却する必要がある。 サンプルコード MainActivity.kt class MainActivity: AppCompatActivity() { // オプションメニューItemの"タップ"イベント検知時の処理 // onOptionsItemSelected(item:): オプションメニューのItemがタップされた場合に呼び出されるメソッド // item: タップされたItem override fun onOptionsItemSelected(item: MenuItem): Boolean { // 最終的に返却するBool値(初期値: true) var returnVal: Boolean = true // タップされたItemに応じた分岐処理 // MenuItem.itemId: ItemのID(R値) when(item.itemId) { R.id.<レイアウトファイルで定義したID> -> // Itemタップ時の処理 ... R.id.<レイアウトファイルで定義したID> -> // Itemタップ時の処理 ... else -> // オプションメニューのItem以外が選択された場合は、 // 親クラス(super)のonOptionsItemSelected(item:)メソッドの // 返り値(デフォルトではfalse)を返却 returnVal = super.onOptionsItemSelected(item) } ... // 最終的にBool値を返却 // -> アイテムが選択され、正常に処理を行った場合はtrueを返却 return returnVal } } アクションバーへの「戻る」ボタン(←)の実装 参考: ActionBar アクションバーを表すNullable型のsupportActionBarプロパティの、setDisplayHomeAsUpEnabled()メソッドを、引数をtrueにして呼び出す。 なお、「戻る」ボタンのR値は、android.R.id.homeで表される。 定義 ActionBar.setDisplayHomeAsUpEnabled(showHomeAsUp: Boolean): Unit // パラメータ // showHomeAsUp: 1つ階層が上のアクティビティに戻る「←」ボタンの表示有無 // true: 表示 // false: 非表示 サンプルコード MenuThanksActivity.kt class MenuThanksActivity: AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { ... // アクションバー内に「戻る」ボタン(←)を表示 supportActionBar?.setDisplayHomeAsUpEnabled(true) } override fun onOptionsItemSelected(item: MenuItem): Boolean { var returnVal: Boolean = true if (item.itemId == android.R.id.home) { finish() } else { returnVal = super.onOptionsItemSelected(item) } return returnVal }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AndroidアプリにFlutterをadd-to-appして複数の画面を扱う

はじめに この記事はFlutter公式( https://flutter.dev/docs/development/add-to-app/multiple-flutters )に載っているMultiple Flutter screens or viewsを試してみた記事になります。 今までadd-to-appは 最初の画面を起動するのに時間がかかる(のでFlutterEngineのキャッシュが必要だった) 1画面だけ扱うことを想定している(複数の画面を扱うのは無理では無いがトリッキーな方法が必要だった) メモリを食う などの課題がありました。 特に1画面しか扱うことを想定していないという制限は大きく、プロダクションでは実質使えない状態でした。 Flutter2.0のリリースに伴い実装されたFlutterEngineGroupを使うことでこれらを解決できます! 前提・環境 Android Studio 4.2.1 (Android Studio CanaryはFlutterをサポートしていないので注意!) Flutter 2.2.1 Flutter doctorを通していること 公式( https://flutter.dev/docs/development/add-to-app/android/project-setup )に従い、add-to-appを済ませていること 実装 FlutterEngineGroupの宣言 Applicationクラスを拡張してFlutterEngineGroupを宣言します App.kt class App : Application() { lateinit var engines: FlutterEngineGroup override fun onCreate() { super.onCreate() engines = FlutterEngineGroup(this) } } 遷移処理の準備 EngineBindingsクラスを用意します EngineBindings.kt package com.example.addtoapptest import android.app.Activity import io.flutter.FlutterInjector import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.dart.DartExecutor import io.flutter.plugin.common.MethodChannel interface EngineBindingsDelegate { fun onNext() } class EngineBindings(activity: Activity, delegate: EngineBindingsDelegate, entrypoint: String) { val channel: MethodChannel val engine: FlutterEngine val delegate: EngineBindingsDelegate init { val app = activity.applicationContext as App // This has to be lazy to avoid creation before the FlutterEngineGroup. val dartEntrypoint = DartExecutor.DartEntrypoint( FlutterInjector.instance().flutterLoader().findAppBundlePath(), entrypoint ) engine = app.engines.createAndRunEngine(activity, dartEntrypoint) this.delegate = delegate channel = MethodChannel(engine.dartExecutor.binaryMessenger, "multiple-flutters") } fun attach() { channel.setMethodCallHandler { call, result -> } } fun detach() { // TODO: Uncomment after https://github.com/flutter/engine/pull/24644 is on stable. // engine.destroy(); channel.setMethodCallHandler(null) } } Flutter用のActivityの用意 FlutterActivityと上記で宣言したEngineBindingsを継承したActivityを作成します。 entrypoint = ""が呼び出す画面の関数名になりますので、ここはdart側に合わせて適宜変更してください。 SingleFlutterActivity.kt package com.example.addtoapptest import android.content.Context import android.content.Intent import android.os.Bundle import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine class SingleFlutterActivity : FlutterActivity(), EngineBindingsDelegate { private val engineBindings: EngineBindings by lazy { EngineBindings(activity = this, delegate = this, entrypoint = "firstScreen") } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) engineBindings.attach() } override fun onDestroy() { super.onDestroy() engineBindings.detach() } override fun provideFlutterEngine(context: Context): FlutterEngine? { return engineBindings.engine } override fun onNext() { val flutterIntent = Intent(this, MainActivity::class.java) startActivity(flutterIntent) } } dart側の準備 main.dartに@pragma('vm:entry-point')で新しいエントリポイントを記述します。 ここで宣言した関数名とkotlin側で呼び出すエントリポイントを一致させましょう。 main.dart import 'package:flutter/material.dart'; // MyAppの内容は省略しています @pragma('vm:entry-point') void firstScreen() => runApp(MyApp()); void main() => runApp(MyApp()); 以上です。AndroidManifestにActivityに登録するのを忘れずに! 補足 FlutterEngineGroupはまだまだ実験的な機能とアナウンスされているので、実装はすぐ変わるかもしれません。 実験的な機能であるためか、FlutterEngineGroupクラスではプロダクションで使わないでくださいというコメントがあります。導入の際は自己責任で!( https://api.flutter.dev/javadoc/io/flutter/embedding/engine/FlutterEngineGroup.html ) @pragma('vm:entry_point')でも特にエラーが出ない上、なぜかデバッグビルドだと動いてリリースビルドだと動かないという不思議な動作をしました。アンダーバーではなくハイフンなのでご注意を!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む