はじめに
携帯端末のホームスクリーン(インストールしたアプリが並んでる画面)にウィジェットを表示させたいと思って home_widget
というパッケージを導入したのですが、うまくいかず、色々試行錯誤してようやくウィジェット操作をすることができました。FlutterのバージョンなのかDartのバージョンなのか、はたまた別の要因なのか、パッケージの公式ページのやり方でどうもうまくできなかったので本記事でまとめていきたいと思います。まずはAndroid版のまとめです。iOSは今後書いていこうと思います。
ウィジェットという表現を多々使いますが、本記事ではホームウィジェットのことを指します。Flutterのwidgetではないので注意
また、ウィジェットはネイティブの部分を触ることが多い箇所となります。なので、XMLファイルを作ったりkotlinを触ったりします。
目標
本記事ではFlutterのUIに設置したボタンを押下すると、Androidのホームウィジェットに現在の時間を表示する仕組みを作る
環境
- MacOS BigSur 11.4
- Flutter 2.5.3
- Dart 2.14.3
- home_widget 0.1.4
やることリスト
- パッケージインストール
- AndroidManifest編集
- ウィジェットのXMLファイルを作成
- ウィジェットレイアウトのXMLファイルを作成
- ウィジェット背景用XMLを作成
- ウィジェットを操作するプログラムをkotlinで作成
- アプリ内のボタン作成
パッケージインストール
以下のコマンドを使ってライブラリをインストールします。
flutter pub add home_widget
AndroidManifest編集
android/app/src/main/AndroidManifest.xml
に receiver
の設定を行います。
以下のここからここまでという部分をAndroidManifestに貼り付けてください。ファイル名は適宜変更してください。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test">
<application
android:label="test"
android:icon="@mipmap/ic_launcher">
<!-- ここから -->
<receiver android:name="TestHomeWidgetProvider" > <!-- ① -->
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/test_home_widget_example" /> <!-- ② -->
</receiver>
<!-- ここまで -->
① ウィジェットを操作するkotlinのファイル名
② ウィジェットの定義を記載するXMLファイル名
ウィジェットの定義を記載するXMLファイルを作成
↑の②で出てきたファイルを作っていきます。
android/app/src/main/res/xml/test_home_widget_example.xml
を作成してください。↑の②に記載したのと同じ文字列をファイル名にしてください。
ファイルの中身はこんな感じにしてください。
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="320dp"
android:minHeight="320dp"
android:updatePeriodMillis="900000"
android:initialLayout="@layout/test_layout"
android:widgetCategory="home_screen">
</appwidget-provider>
minWidth
やminHeight
はウィジェットのサイズを指します。こちらを参考にしてください。
updatePeriodMills
はウィジェットの自動更新間隔を示しています。例は900000となっているので900秒、つまり15分となっています。initialLayout
はウィジェットが作成されたときに自動で適用されるレイアウトファイル名を指定しています。ここではtest_layout
という名前のレイアウトファイルを使うよう定義されています。
ウィジェットレイアウトのXMLファイルを作成
ウィジェットの見た目を決めるレイアウトXMLを作ります。
android/app/src/main/res/layout/test_layout.xml
を作成してください。
中身はテキストを表示するだけのシンプルなものにします。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:orientation="vertical"
android:background="@drawable/widget_background"
android:padding="8dp"
android:id="@+id/widget_container">
<TextView
android:id="@+id/widget_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="36sp"
android:textStyle="bold"
tools:text="Text" />
</LinearLayout>
ウィジェット背景用XMLを作成
↑の android:background
で指定した背景用のXMLを作成します。ここに背景色などを書くことでウィジェットの背景のデザインが決まります。
android/app/src/main/res/drawable/widget_background.xml
を作成してください。中身は単純に背景色 白
の設定とウィジェットの周りをちょっと丸みを帯びた形にする設定をしていきます。
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF"/>
<corners android:radius="16dp"/>
</shape>
ウィジェットを操作するプログラムをkotlinで作成
kotlinである必要はないのですが、ここではkotlinでのやり方を書いていきます。
android/app/src/main/kotlin/com/example/test/TestHomeWidgetProvider.kt
を作成してください。
TestHomeWidgetProvider
を覚えていますでしょうか?最初に編集した AndroidManifest.xml
に記載したものと同じですね。ここが異なっているとうまく動かないのでファイル名(というかクラス名)には注意しましょう。
このkotlinファイルには以下を記載してください。
package com.example.test
import android.appwidget.AppWidgetManager
import android.content.Context
import android.content.SharedPreferences
import android.net.Uri
import android.widget.RemoteViews
import es.antonborri.home_widget.HomeWidgetBackgroundIntent
import es.antonborri.home_widget.HomeWidgetLaunchIntent
import es.antonborri.home_widget.HomeWidgetProvider
class TestHomeWidgetProvider : HomeWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray, widgetData: SharedPreferences) {
appWidgetIds.forEach { widgetId ->
val views = RemoteViews(context.packageName, R.layout.test_layout).apply {
setTextViewText(R.id.widget_text, widgetData.getString("text", null)
?: "No Text Set")
}
appWidgetManager.updateAppWidget(widgetId, views)
}
}
}
アプリ内のボタン作成
ここでようやくFlutterの登場です。Flutterで、押下するとその時の日時をウィジェットに表示するボタンを作っていきます。
以下を貼っていただき、皆さんが作成したボタンのonPressed
でこの_sendAndUpdate
メソッドを呼んでいただくだけで動きます。
Future<void> _sendData() async {
DateTime now = DateTime.now();
try {
await Future.wait([
HomeWidget.saveWidgetData<String>('text', now.toString()),
]);
} on PlatformException catch (exception) {
debugPrint('Error Sending Data. $exception');
}
}
Future<void> _updateWidget() async {
try {
await HomeWidget.updateWidget(
name: 'TestHomeWidgetProvider',
androidName: 'TestHomeWidgetProvider',
iOSName: 'TestHomeWidgetProvider');
} on PlatformException catch (exception) {
debugPrint('Error Updating Widget. $exception');
}
}
Future<void> _sendAndUpdate() async {
await _sendData();
await _updateWidget();
}
ボタンを押下するとこんな感じになります。
以上、長々となりましたが、Flutter x Android x home_widget
パッケージでホームウィジェットを操作する方法まとめでした。最後までお読みいただきありがとうございました。