title: How to implement "flutter_local_notifications" plugin inside" flutter_background_fetch" to push notification online WITHOUT FIREBASE in Flutter
body: <p>I want launch the notification when the background process is triggered,
  I tried call the notification class inside BackgroundFetch method but didn't work ,However when i print a debug message it works.</p>
  
  <p>and i want to make this functionality isolated from the business logic of the app
  this is my attempt </p>
  
  <p>1-the notification class:</p>
  
  <pre><code>class LocalNotificationWidget extends StatefulWidget {
  
    @override
    _LocalNotificationWidgetState createState() =&gt;
        _LocalNotificationWidgetState();
  }
  
  class _LocalNotificationWidgetState extends State&lt;LocalNotificationWidget&gt; {
    final notifications = FlutterLocalNotificationsPlugin();
  
    @override
    void initState() {
      super.initState();
  
      final settingsAndroid = AndroidInitializationSettings('app_icon');
  
      final settingsIOS = IOSInitializationSettings(
          onDidReceiveLocalNotification: (id, title, body, payload) =&gt;
              onSelectNotification(payload));
  
      notifications.initialize(
          InitializationSettings(settingsAndroid, settingsIOS),
          onSelectNotification: onSelectNotification);
  
      showOngoingNotification(notifications,
          title: 'Tite', body: 'hello');
    }
  
    Future onSelectNotification(String payload) async =&gt; await Navigator.push(
          context,
          MaterialPageRoute(builder: (context) =&gt; SecondScreen( payload)),
        );
  
    @override
    Widget build(BuildContext context) =&gt; Container();
  
    Widget title(String text) =&gt; Container(
          margin: EdgeInsets.symmetric(vertical: 4),
          child: Text(
            text,
            style: Theme.of(context).textTheme.title,
            textAlign: TextAlign.center,
          ),
        );
  }
  </code></pre>
  
  <p>2-the background service class:</p>
  
  <pre><code>const EVENTS_KEY = "fetch_events";
  
  /// This "Headless Task" is run when app is terminated.
  void backgroundFetchHeadlessTask() async {
    print('[BackgroundFetch] Headless event received.');
  
    SharedPreferences prefs = await SharedPreferences.getInstance();
  
    // Read fetch_events from SharedPreferences
    List&lt;String&gt; events = [];
    String json = prefs.getString(EVENTS_KEY);
    if (json != null) {
      events = jsonDecode(json).cast&lt;String&gt;();
    }
    // Add new event.
    events.insert(0, new DateTime.now().toString() + ' [Headless]');
    // Persist fetch events in SharedPreferences
    prefs.setString(EVENTS_KEY, jsonEncode(events));
  
    BackgroundFetch.finish();
  }
  
  void main() {
    // Enable integration testing with the Flutter Driver extension.
    // See https://flutter.io/testing/ for more info.
    runApp(new MyApp());
  
    // Register to receive BackgroundFetch events after app is terminated.
    // Requires {stopOnTerminate: false, enableHeadless: true}
    BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
  }
  
  class MyApp extends StatefulWidget {
    @override
    _MyAppState createState() =&gt; new _MyAppState();
  }
  
  class _MyAppState extends State&lt;MyApp&gt; {
    bool _enabled = true;
    int _status = 0;
    List&lt;String&gt; _events = [];
  
    @override
    void initState() {
      super.initState();
      initPlatformState();
  
  
    }
  
    // Platform messages are asynchronous, so we initialize in an async method.
    Future&lt;void&gt; initPlatformState() async {
      // Load persisted fetch events from SharedPreferences
      SharedPreferences prefs = await SharedPreferences.getInstance();
      String json = prefs.getString(EVENTS_KEY);
      if (json != null) {
        setState(() {
          _events = jsonDecode(json).cast&lt;String&gt;();
        });
      }
  
      // Configure BackgroundFetch.
      BackgroundFetch.configure(BackgroundFetchConfig(
          minimumFetchInterval: 15,
          stopOnTerminate: false,
          enableHeadless: true,
          forceReload: false
      ), _onBackgroundFetch).then((int status) {
        LocalNotificationWidget();
        print('[BackgroundFetch] SUCCESS: $status');
        setState(() {
          _status = status;
        });
      }).catchError((e) {
        print('[BackgroundFetch] ERROR: $e');
        setState(() {
          _status = e;
        });
      });
  
      // Optionally query the current BackgroundFetch status.
      int status = await BackgroundFetch.status;
      setState(() {
        _status = status;
      });
  
      // If the widget was removed from the tree while the asynchronous platform
      // message was in flight, we want to discard the reply rather than calling
      // setState to update our non-existent appearance.
      if (!mounted) return;
    }
  
    void _onBackgroundFetch() async {
      SharedPreferences prefs = await SharedPreferences.getInstance();
  
      // This is the fetch-event callback.
      print('[BackgroundFetch] Event received');
      setState(() {
        _events.insert(0, new DateTime.now().toString());
      });
      // Persist fetch events in SharedPreferences
      prefs.setString(EVENTS_KEY, jsonEncode(_events));
  
      // IMPORTANT:  You must signal completion of your fetch task or the OS can punish your app
      // for taking too long in the background.
      BackgroundFetch.finish();
    }
  
    void _onClickEnable(enabled) {
      setState(() {
        _enabled = enabled;
      });
      if (enabled) {
        BackgroundFetch.start().then((int status) {
          print('[BackgroundFetch] start success: $status');
        }).catchError((e) {
          print('[BackgroundFetch] start FAILURE: $e');
        });
      } else {
        BackgroundFetch.stop().then((int status) {
          print('[BackgroundFetch] stop success: $status');
        });
      }
    }
  
    void _onClickStatus() async {
      int status = await BackgroundFetch.status;
      print('[BackgroundFetch] status: $status');
      setState(() {
        _status = status;
      });
    }
  
    void _onClickClear() async {
      SharedPreferences prefs = await SharedPreferences.getInstance();
      prefs.remove(EVENTS_KEY);
      setState(() {
        _events = [];
      });
    }
    @override
    Widget build(BuildContext context) {
      const EMPTY_TEXT = Center(child: Text('Waiting for fetch events.  Simulate one.\n [Android] \$ ./scripts/simulate-fetch\n [iOS] XCode-&gt;Debug-&gt;Simulate Background Fetch'));
  
      return new MaterialApp(
        home: new Scaffold(
          appBar: new AppBar(
              title: const Text('BackgroundFetch Example', style: TextStyle(color: Colors.black)),
              backgroundColor: Colors.amberAccent,
              brightness: Brightness.light,
              actions: &lt;Widget&gt;[
                Switch(value: _enabled, onChanged: _onClickEnable),
              ]
          ),
          body: (_events.isEmpty) ? EMPTY_TEXT : Container(
            child: new ListView.builder(
                itemCount: _events.length,
                itemBuilder: (BuildContext context, int index) {
                  String timestamp = _events[index];
                  return InputDecorator(
                      decoration: InputDecoration(
                          contentPadding: EdgeInsets.only(left: 5.0, top: 5.0, bottom: 5.0),
                          labelStyle: TextStyle(color: Colors.blue, fontSize: 20.0),
                          labelText: "[background fetch event]"
                      ),
                      child: new Text(timestamp, style: TextStyle(color: Colors.black, fontSize: 16.0))
                  );
                }
            ),
          ),
          bottomNavigationBar: BottomAppBar(
              child: Container(
                  padding: EdgeInsets.only(left: 5.0, right:5.0),
                  child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: &lt;Widget&gt;[
                        RaisedButton(onPressed: _onClickStatus, child: Text('Status: $_status')),
                        RaisedButton(onPressed: _onClickClear, child: Text('Clear'))
  
                      ]
                  )
              )
          ),
        ),
      );
    }
  }
  </code></pre>