Help us understand the problem. What is going on with this article?

flutterで定期通知を行う

More than 1 year has passed since last update.

flutterで定期実行を行うのは易しくありません。
https://github.com/flutter/flutter/issues/24278

このissue(この記事の約1ヶ月前)にもある通り、flutterでは現在、両プラットフォームにおいてバックグランド実行できる機能が制限されています。この原因として、iOSの場合は特にアプリを放置しておくと勝手に終了されてしまうため、アプリの裏側でタイマーを起動しても時間が経つとなかったことにされてしまいます。androidの場合はandroid_alarm_managerというアプリが公式で出されているのでこれを使えばよいのですが、iOSは未だに公式サポートがありません。

アプリの定期実行を行うのは今の現状だとかなり厳しいと思われますが、実は定期的に通知を出すだけであればサードパーティ製ライブラリのflutter_local_notificationを使うことで解決します。このアプリはバックグラウンドに行っても通知を送ることができる通知用タイマーのようなライブラリです。

例えば毎朝8時に通知を送るサンプルです

import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;

  @override
  void initState() {
    super.initState();

    var initializationSettingsAndroid =
        new AndroidInitializationSettings('app_icon');
    var initializationSettingsIOS = new IOSInitializationSettings();
    var initializationSettings = new InitializationSettings(
        initializationSettingsAndroid, initializationSettingsIOS);
    flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin();
    flutterLocalNotificationsPlugin.initialize(initializationSettings);
  }

  // notification
  Future _showNotification() async {
    var time = new Time(8, 0, 0);
    var androidPlatformChannelSpecifics = new AndroidNotificationDetails(
        'your channel id', 'your channel name', 'your channel description',
        importance: Importance.Max, priority: Priority.High);
    var iOSPlatformChannelSpecifics = new IOSNotificationDetails();
    var platformChannelSpecifics = new NotificationDetails(
        androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
    await flutterLocalNotificationsPlugin.showDailyAtTime(
      0,
      'Timer',
      'You should check the app',
      time,
      platformChannelSpecifics,
      payload: 'Default_Sound',
    );
  }

  void _setSchedular() {
    _showNotification();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              'Hello World',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _setSchedular,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

これ、ほぼほぼデフォルトのアプリを継承したものなのですがこんな感じで簡単に利用できます。
ここで一回起動するだけで毎朝8時に通知が来ます。

このflutterLocalNotificationsPlugin.showDailyAtTimeの部分を変えれば色々な定期通知が可能で
・X分後に実行

var scheduledNotificationDateTime =
        new DateTime.now().add(new Duration(seconds: 5));
var androidPlatformChannelSpecifics =
    new AndroidNotificationDetails('your other channel id',
        'your other channel name', 'your other channel description');
var iOSPlatformChannelSpecifics =
    new IOSNotificationDetails();
NotificationDetails platformChannelSpecifics = new NotificationDetails(
    androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.schedule(
    0,
    'scheduled title',
    'scheduled body',
    scheduledNotificationDateTime,
    platformChannelSpecifics);

・毎分実行

await flutterLocalNotificationsPlugin.periodicallyShow(0, 'repeating title',
    'repeating body', RepeatInterval.EveryMinute, platformChannelSpecifics);

・毎週同じ時間に実行

await flutterLocalNotificationsPlugin.showWeeklyAtDayAndTime(
    0,
    'show weekly title',
    'Weekly notification shown on Monday at approximately ${_toTwoDigitString(time.hour)}:${_toTwoDigitString(time.minute)}:${_toTwoDigitString(time.second)}',
    Day.Monday,
    time,
    platformChannelSpecifics);

といったことができます。
キャンセルする場合は以下の関数を呼んでください。

・1個キャンセル

await flutterLocalNotificationsPlugin.cancel(0);

・全部キャンセル

await flutterLocalNotificationsPlugin.cancelAll();

こんな感じで簡単に通知の利用ができます。

とはいえ、早く公式サポートしてくれないかなぁ...と願ってます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away