Android ・iOS端末にHome Widgetを導入する方法

Home Widgetは、ホーム画面を便利にカスタマイズできる「ウィジェット」のことです。
この記事を読むことで、**簡単なHome Widgetの導入をAndroid / iOS端末で行うことができます**。

Androidでは、初期バージョンが2008年にリリースされた時から、iPhoneでは、iOS 14（2020年リリース）から、ホーム画面に直接ウィジェットを配置できる機能が導入されています。
Android / iPhoneともに、Home Widget機能が導入されているアプリは、全体の割合としては非常に少ないというのが現状です。

今回は、**Flutter**を用いて、Android / iOSにHome Widgetを導入する方法について解説します。この記事では**Flutter 3.16.1**と**Dart 3.2.1**をベースに解説を行っています。

## Home Widget導入までの流れ
以下の流れでHomeWidgetの導入を行います。

- Step1. パッケージの追加
- Step2. Dartコードの追加
- Step3. Androidの設定
- Step4. iOSの設定

以下のようなHome Widgetを追加することが目標です。
今回は、ウィジェットに表示するデータは固有値（Widget）とし、任意のデータを表示する機能は含んでいません。

![Green Minimalist Financial Services Table Graph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615439/142578e8-0143-13b7-db30-1dd816d0a902.png)

## 具体的な導入方法
### Step1. パッケージの追加
pubspec.yaml ファイルに home_widget: ^0.3.0 を追加して、依存関係を更新します。

home_widgetの最新版については[こちら](https://pub.dev/packages/home_widget)を参照ください。

### Step2. Dartコードの追加
Flutter側でウィジェットを更新するためのDartコードを書きます。

```main.dart
import 'package:flutter/material.dart';
import 'package:home_widget/home_widget.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Home Widget Example'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            HomeWidget.updateWidget(name: 'MyAppWidgetProvider', androidName: 'MyAppWidgetProvider');
          },
          child: Text('Update Widget'),
        ),
      ),
    );
  }
}
```

### Step3. Androidの設定
#### ①AndroidManifest.xmlファイルの追加

android/app/src/main/AndroidManifest.xml の<application> タグ内に以下のコードを追加します。

```AndroidManifest.xml
<application>
    # -------------------- 追加 --------------------
    <service
        android:name="es.antonborri.home_widget.HomeWidgetBackgroundService"
        android:permission="android.permission.BIND_JOB_SERVICE"
        android:exported="true"/>
    <receiver android:name="MyAppWidgetProvider"
        android:exported="false">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>
        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/app_widget_provider" />
    </receiver>
    # -------------------- 追加 --------------------
</application>
```

#### ②app_widget_provider.xmlファイルの追加

android/app/src/main/res/xml/app_widget_provider.xml ファイルを作成し、ウィジェットの設定を以下のように記述します。

```app_widget_provider.xml
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/widget_layout"
    android:minHeight="40dp"
    android:minWidth="40dp"
    android:updatePeriodMillis="86400000"
    android:previewImage="@drawable/example_appwidget_preview"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen">
</appwidget-provider>
```

#### ③widget_layout.xmlファイルの追加

android/app/src/main/res/layout ディレクトリに widget_layout.xml ファイルを作成し、ウィジェットのUIレイアウトの設定を以下のように記述します。

```widget_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#0067C0">

    <TextView
        android:id="@+id/appwidget_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="@string/appwidget_text"
        android:textColor="#FFFFFF"
        android:textSize="24sp"/>
</RelativeLayout>
```

#### ④プレビュー画像を追加

android/app/src/main/res/drawable ディレクトリに、ウィジェットのプレビュー画像を追加します。この画像は、ユーザーがウィジェットを追加する際に表示されます。
ファイル名は example_appwidget_preview.png などにして、app_widget_provider.xml で参照されている名前と一致させる必要があります。

#### ⑤strings.xmlファイルの追加

android/app/src/main/res/values/strings.xml ファイルを開きます。このファイルはアプリ内で使用する全ての文字列リソースを含みます。このファイルに以下を記述します。

```strings.xml
<string name="appwidget_text">Widget</string>
```

#### ⑥ビルドの実行

これらの変更を行った後、プロジェクトのビルドを行うと、AndroidにてWidgetを追加することができます。

### Step4. iOSの設定
#### ①Widget Extensionの追加

Xcodeを開いてFlutterプロジェクトのiOS部分をロードします。
Terminalで $open ios/Runner.xcworkspaceを実行すると、Xcodeを開くことができます。
File -> New -> Target を選択し、Widget Extension を選びます。
ウィジェットの名前を入力し、必要な設定を行います。
今回は、「HomeWidgetSample」という名前にしました。

#### ②HomeWidgetSample.swiftファイルの追加

このファイルの該当する部分に以下のコードを追加します。それによって、ウィジェットビューを定義することができます。

```HomeWidgetSample.swift
struct HomeWidgetSampleEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        ZStack {
            // 青色の背景
            Color.blue

            VStack {
                // ウィジェットのタイトル
                Text("Widget")
                    .font(.headline)
                    .foregroundColor(.white)
            }
        }
        .edgesIgnoringSafeArea(.all)
    }
}
```

#### ③ビルドの実行

これらの変更を行った後、Xcodeでプロジェクトをビルドすると、iOSでもWidgetを追加することができます。

## まとめ
本記事では、Home Widgetの導入方法について解説していきました。
今回は、簡単なWidgetを作成しましたが、ご自身のお好みでカスタマイズすることもできるので、もしよければ色々とお試しください。

## 最後に
弊社では、Flutterを利用したモバイルアプリの開発相談を多数頂いております。
それに対して、エンジニアの数がまだまだ不足している状況です。
弊社にてFlutter開発をしたい方や、インターンシップをしたい学生さんを随時募集しております。
ご興味のある方は、弊社採用アドレス(rec@stv-tech.co.jp )またはhttps://www.wantedly.com/companies/stv-tech/projects へお気軽にお問い合わせください。

## 参考
 - [home_widget package](https://pub.dev/packages/home_widget)
 - [Adding a Home Screen widget to your Flutter App](https://codelabs.developers.google.com/flutter-home-screen-widgets#0)