Giter Club home page Giter Club logo

Comments (24)

saravananmnm avatar saravananmnm commented on August 29, 2024 1

And the app is completely terminated? Removed from recents. Or is the app just in the background?

Yes @vanlooverenkoen. App is terminated from recent activities.

from kiwi.

vanlooverenkoen avatar vanlooverenkoen commented on August 29, 2024

Can you provide me a reproducible example? You are calling a method getAllOrders on a null object? Where is this object coming from? Why is it null?

Did you init the container in the background as well?

from kiwi.

saravananmnm avatar saravananmnm commented on August 29, 2024
class BackgroundService {
  CollectionDeliveryRepository repository;
  SaveOrdersDetailsDAO saveOrdersDetailsDAO;
  OrdersMasterDAO ordersMasterDAO;

  BackgroundService(
      this.repository, this.saveOrdersDetailsDAO, this.ordersMasterDAO) {
    configure();
  }

i have injected from class constructor through kiwi .

void backgroundFetchHeadlessTask(String taskId) async {
  CollectionDeliveryRepository repository;
  SaveOrdersDetailsDAO saveOrdersDetailsDAO;
  OrdersMasterDAO ordersMasterDAO;
  print("[BackgroundFetch onTerminate] Headless event received: $taskId");
  DateTime timestamp = DateTime.now();
  // Read fetch_events from SharedPreferences
  // Add new event.
  if (await Utils.onCheckNetworkConnection()) {
    var orders = await ordersMasterDAO.getAllOrders(StringConstant.POD);
    var syncData = await saveOrdersDetailsDAO.getAllOrderDetails(orders);
    var savedOrders = await getSavedOrderDetails(repository, syncData, orders);
    pushAllSavedOrders(
        savedOrders, repository, ordersMasterDAO, saveOrdersDetailsDAO);
  }
  BackgroundFetch.finish(taskId);
}

but inside top-level function is not getting those objects.

from kiwi.

saravananmnm avatar saravananmnm commented on August 29, 2024

container.registerSingleton((c) => BackgroundService(container<CollectionDeliveryRepository>(),container<SaveOrdersDetailsDAO>(),container<OrdersMasterDAO>()));

from kiwi.

saravananmnm avatar saravananmnm commented on August 29, 2024

any solutions about this issue?

from kiwi.

vanlooverenkoen avatar vanlooverenkoen commented on August 29, 2024

Oh I'm sorry I completely forgot. Today I have time to investigate.

from kiwi.

vanlooverenkoen avatar vanlooverenkoen commented on August 29, 2024

@saravananmnm can you provide me with a small working example? That I can run that has this specific issue? Meanwhile I am looking at https://pub.dev/packages/background_fetch how it works and trying to create a working example for myself

from kiwi.

saravananmnm avatar saravananmnm commented on August 29, 2024
2020-10-24 14:06:53.466 29236-29266/com.fluttersamples E/flutter: [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: KiwiError:
    
    
    Failed to resolve `BGReposotory`:
    
    The type `BGReposotory` was not registered
    
    Make sure `BGReposotory` is added to your KiwiContainer and rerun build_runner build
    (If you are using the kiwi_generator)
    
    When using Flutter, most of the time a hot restart is required to setup the KiwiContainer again.
    
    
    
    #     KiwiContainer.resolve (package:kiwi/src/kiwi_container.dart:94:7)
    #     KiwiContainer.call (package:kiwi/src/kiwi_container.dart:126:31)
    #     backgroundHeadlessTask (package:fluttersamples/backgroundservices.dart:14:25)
    #     _headlessCallbackDispatcher.<anonymous closure> (package:background_fetch/background_fetch.dart:619:15)
    #     MethodChannel._handleAsMethodCall (package:flutter/src/services/platform_channel.dart:432:55)
    #     MethodChannel.setMethodCallHandler.<anonymous closure> (package:flutter/src/services/platform_channel.dart:385:33)
    #     _DefaultBinaryMessenger.handlePlatformMessage (package:flutter/src/services/binding.dart:267:33)
    #     _invoke3.<anonymous closure> (dart:ui/hooks.dart:282:15)
    #     _rootRun (dart:async/zone.dart:1190:13)
    #     _CustomZone.run (dart:async/zone.dart:1093:19)
    #     _CustomZone.runGuarded (dart:async/zone.dart:997:7)
    #     _invoke3 (dart:ui/hooks.dart:281:10)
    #    _dispatchPlatformMessage (dart:ui/hooks.dart:156:5)
2020-10-24 14:07:27.986 29236-29236/com.fluttersamples D/TSBackgroundFetch: - Background Fetch event received
2020-10-24 14:07:27.986 29236-29236/com.fluttersamples D/TSBackgroundFetch: 💀 [HeadlessTask flutter_background_fetch]
2020-10-24 14:07:27.991 29236-29266/com.fluttersamples E/flutter: [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: KiwiError:

from kiwi.

saravananmnm avatar saravananmnm commented on August 29, 2024
import 'dart:async';

import 'package:background_fetch/background_fetch.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttersamples/repository/backgroundrepository.dart';
import 'package:geolocator/geolocator.dart';
import 'package:kiwi/kiwi.dart';

/// This "Headless Task" is run when app is terminated.
Future<void> backgroundHeadlessTask(String taskId) async {
  BGReposotory reposotory;
  var container = new KiwiContainer();
  reposotory = container<BGReposotory>();
  DateTime timestamp = DateTime.now();
  print("[BackgroundFetch onTerminate] Headless event received: $timestamp");
  var position = await Geolocator.getCurrentPosition(
      forceAndroidLocationManager: true,
      desiredAccuracy: LocationAccuracy.high);
  print(position.toString());
  int res= await reposotory.updateDriverStatus(position);
  if (res != null && res == 1)
    print('success');
  else
    print('failure');
  BackgroundFetch.finish(taskId);
}

class MyBGApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyBGApp> {
  bool _enabled = true;
  int _status = 0;
  List<String> _events = [];
  BGReposotory reposotory;

  _MyAppState() {
    var container = new KiwiContainer();
    reposotory = container<BGReposotory>();
  }

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

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    // Configure BackgroundFetch.
    BackgroundFetch.configure(
            BackgroundFetchConfig(
              minimumFetchInterval: 1,
              forceAlarmManager: true,
              stopOnTerminate: false,
              startOnBoot: true,
              enableHeadless: true,
              requiresBatteryNotLow: false,
              requiresCharging: false,
              requiresStorageNotLow: false,
              requiresDeviceIdle: false,
              requiredNetworkType: NetworkType.ANY,
            ),
            _onBackgroundFetch)
        .then((int status) {
      print('[BackgroundFetch] configure success: $status');
      setState(() {
        _status = status;
      });
    }).catchError((e) {
      print('[BackgroundFetch] configure ERROR: $e');
      setState(() {
        _status = e;
      });
    });

    // Schedule a "one-shot" custom-task in 10000ms.
    // These are fairly reliable on Android (particularly with forceAlarmManager) but not iOS,
    // where device must be powered (and delay will be throttled by the OS).
    BackgroundFetch.scheduleTask(TaskConfig(
        taskId: "Saro.Background",
        delay: 1000,
        periodic: true,
        forceAlarmManager: false,
        stopOnTerminate: false,
        enableHeadless: true));

    // 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(String taskId) async {
    DateTime timestamp = new DateTime.now();
    // This is the fetch-event callback.
    print("[BackgroundFetch onForeground] Event received: $taskId $timestamp");
    var position = await Geolocator.getCurrentPosition(
        forceAndroidLocationManager: true,
        desiredAccuracy: LocationAccuracy.high);
   int res= await reposotory.updateDriverStatus(position);
    if (res != null && res == 1)
      print('success');
    else
      print('failure');
    // 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(taskId);
  }

  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 {
    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->Debug->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: <Widget>[
              Switch(value: _enabled, onChanged: _onClickEnable),
            ]),
        body: (_events.isEmpty)
            ? EMPTY_TEXT
            : Container(
                child: new ListView.builder(
                    itemCount: _events.length,
                    itemBuilder: (BuildContext context, int index) {
                      List<String> event = _events[index].split("@");
                      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: "[${event[0].toString()}]"),
                          child: new Text(event[1],
                              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: <Widget>[
                      RaisedButton(
                          onPressed: _onClickStatus,
                          child: Text('Status: $_status')),
                      RaisedButton(
                          onPressed: _onClickClear, child: Text('Clear'))
                    ]))),
      ),
    );
  }
}
```

from kiwi.

vanlooverenkoen avatar vanlooverenkoen commented on August 29, 2024

@saravananmnm I tried the following and everything was working for me.

I assume this problem is only present on Andriod? Because on iOS it is not possible to fetch when the app is terminated

EXAMPLE
import 'dart:math';

import 'package:background_fetch/background_fetch.dart';
import 'package:flutter/material.dart';
import 'package:kiwi/kiwi.dart';
import 'package:pp_local_notifications/local_notifications.dart';

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//// MAIN DART FILE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await setupDependencyTree();
  BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
  runApp(MyApp());
  Future.delayed(Duration(seconds: 10)).then((value) {
    delayedPrint();
  });
}

backgroundFetchHeadlessTask(String taskId) {
  sendNotification(
    title: "backgroundFetchHeadlessTask",
    content: "${KiwiContainer().resolve<RepoA>().id}\n"
        "${KiwiContainer().resolve<RepoB>().id}\n"
        "${KiwiContainer().resolve<RepoC>().id}\n"
        "${KiwiContainer().resolve<RepoD>().id}\n"
        "${KiwiContainer().resolve<RepoABC>().id}\n",
  );
  print(KiwiContainer().resolve<RepoA>().id);
  print(KiwiContainer().resolve<RepoB>().id);
  print(KiwiContainer().resolve<RepoC>().id);
  print(KiwiContainer().resolve<RepoD>().id);
  print(KiwiContainer().resolve<RepoABC>().id);

  BackgroundFetch.finish(taskId);
}

delayedPrint() {
  sendNotification(
    title: "delayedPrint",
    content: "${KiwiContainer().resolve<RepoA>().id}\n"
        "${KiwiContainer().resolve<RepoB>().id}\n"
        "${KiwiContainer().resolve<RepoC>().id}\n"
        "${KiwiContainer().resolve<RepoD>().id}\n"
        "${KiwiContainer().resolve<RepoABC>().id}\n",
  );
  print(KiwiContainer().resolve<RepoA>().id);
  print(KiwiContainer().resolve<RepoB>().id);
  print(KiwiContainer().resolve<RepoC>().id);
  print(KiwiContainer().resolve<RepoD>().id);
  print(KiwiContainer().resolve<RepoABC>().id);
}

Future<void> sendNotification({@required String title, @required String content}) async {
  const AndroidNotificationChannel channel = const AndroidNotificationChannel(
    id: 'default_notification',
    name: 'Default',
    description: 'Grant this app the ability to show notifications',
    importance: AndroidNotificationChannelImportance.HIGH,
  );

  await LocalNotifications.createAndroidNotificationChannel(channel: channel);

  LocalNotifications.createNotification(
    title: title,
    ticker: content,
    content: content,
    id: Random().nextInt(54468),
    androidSettings: AndroidSettings(channel: channel),
  );
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//// INJECTOR
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
abstract class Injector {
  @Register.singleton(RepoA)
  @Register.singleton(RepoB)
  @Register.singleton(RepoC)
  @Register.singleton(RepoD)
  @Register.singleton(RepoABC)
  void register();
}

Future<void> setupDependencyTree() async => _$Injector().register();

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//// REPOSITORIES
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class RepoA {
  String id;

  RepoA() {
    id = Random().nextInt(545654465).toString();
  }

  String getStringFromA() => 'A';
}

class RepoB {
  String id;

  RepoB() {
    id = Random().nextInt(545654465).toString();
  }

  String getStringFromB() => 'B';
}

class RepoC {
  String id;

  RepoC() {
    id = Random().nextInt(545654465).toString();
  }

  String getStringFromC() => 'A';
}

class RepoD {
  String id;

  RepoD() {
    id = Random().nextInt(545654465).toString();
  }

  String getStringFromD() => 'A';
}

class RepoABC {
  final RepoA _repoA;
  final RepoB _repoB;
  final RepoC _repoC;
  String id;

  RepoABC(this._repoA, this._repoB, this._repoC){
    id = Random().nextInt(545654465).toString();
  }

  String getString() => '${_repoA.getStringFromA()}${_repoB.getStringFromB()}${_repoC.getStringFromC()}';
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//// MY APP
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: HomeScreen(),
    );
  }
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//// Home Screen
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  int _status = 0;
  List<DateTime> _events = [];

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home'),
      ),
      body: Column(
        children: [
          Text(KiwiContainer().resolve<RepoA>().id),
          Text(KiwiContainer().resolve<RepoB>().id),
          Text(KiwiContainer().resolve<RepoC>().id),
          Text(KiwiContainer().resolve<RepoD>().id),
          Text(KiwiContainer().resolve<RepoABC>().id),
          Expanded(
            child: Container(
              color: Colors.grey.shade300,
              child: ListView.builder(
                itemCount: _events.length,
                itemBuilder: (BuildContext context, int index) {
                  DateTime timestamp = _events[index];
                  return InputDecorator(
                    decoration: InputDecoration(
                        contentPadding: EdgeInsets.only(left: 10.0, top: 10.0, bottom: 0.0),
                        labelStyle: TextStyle(color: Colors.amberAccent, fontSize: 20.0),
                        labelText: "[background fetch event]"),
                    child: Text(
                      timestamp.toString(),
                      style: TextStyle(color: Colors.white, fontSize: 16.0),
                    ),
                  );
                },
              ),
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: onAddTask,
      ),
    );
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    // Configure BackgroundFetch.
    BackgroundFetch.configure(
        BackgroundFetchConfig(
          stopOnTerminate: false,
          enableHeadless: true,
          minimumFetchInterval: 1,
        ), (String taskId) async {
      // This is the fetch-event callback.
      print("[BackgroundFetch] Event received $taskId");
      setState(() {
        _events.insert(0, new DateTime.now());
      });
      // IMPORTANT:  You must signal completion of your task or the OS can punish your app
      // for taking too long in the background.
      BackgroundFetch.finish(taskId);
    }).then((int status) {
      print('[BackgroundFetch] configure success: $status');
      setState(() {
        _status = status;
      });
    }).catchError((e) {
      print('[BackgroundFetch] configure 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;
  }

  Future<void> onAddTask() async {
    sendNotification(
      title: "onAddTask",
      content: "${KiwiContainer().resolve<RepoA>().id}\n"
          "${KiwiContainer().resolve<RepoB>().id}\n"
          "${KiwiContainer().resolve<RepoC>().id}\n"
          "${KiwiContainer().resolve<RepoD>().id}\n"
          "${KiwiContainer().resolve<RepoABC>().id}\n",
    );
    BackgroundFetch.scheduleTask(TaskConfig(
      taskId: 'com.example.customtask',
      delay: 60 * 1000,
      enableHeadless: true,
      stopOnTerminate: false,
      periodic: true,
    ));
  }
}

from kiwi.

saravananmnm avatar saravananmnm commented on August 29, 2024
C:\Saravanan\Flutter_Sdk\flutter\bin\flutter.bat doctor --verbose
[√] Flutter (Channel stable, 1.20.4, on Microsoft Windows [Version 10.0.18362.1082], locale en-IN)
    • Flutter version 1.20.4 at C:\Saravanan\Flutter_Sdk\flutter
    • Framework revision fba99f6cf9 (6 weeks ago), 2020-09-14 15:32:52 -0700
    • Engine revision d1bc06f032
    • Dart version 2.9.2

[√] Android toolchain - develop for Android devices (Android SDK version 30.0.0)
    • Android SDK at C:\Users\Admin\AppData\Local\Android\sdk
    • Platform android-30, build-tools 30.0.0
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
    • All Android licenses accepted.

[√] Android Studio (version 4.0)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 50.0.1
    • Dart plugin version 193.7547
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)

[√] Connected device (1 available)
    • Android SDK built for x86 (mobile) • emulator-5554 • android-x86 • Android 10 (API 29) (emulator)

• No issues found!
Process finished with exit code 0

from kiwi.

vanlooverenkoen avatar vanlooverenkoen commented on August 29, 2024
import 'dart:async';

import 'package:background_fetch/background_fetch.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttersamples/repository/backgroundrepository.dart';
import 'package:geolocator/geolocator.dart';
import 'package:kiwi/kiwi.dart';

/// This "Headless Task" is run when app is terminated.
Future<void> backgroundHeadlessTask(String taskId) async {
  BGReposotory reposotory;
  var container = new KiwiContainer();
  reposotory = container<BGReposotory>();
  DateTime timestamp = DateTime.now();
  print("[BackgroundFetch onTerminate] Headless event received: $timestamp");
  var position = await Geolocator.getCurrentPosition(
      forceAndroidLocationManager: true,
      desiredAccuracy: LocationAccuracy.high);
  print(position.toString());
  int res= await reposotory.updateDriverStatus(position);
  if (res != null && res == 1)
    print('success');
  else
    print('failure');
  BackgroundFetch.finish(taskId);
}

class MyBGApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyBGApp> {
  bool _enabled = true;
  int _status = 0;
  List<String> _events = [];
  BGReposotory reposotory;

  _MyAppState() {
    var container = new KiwiContainer();
    reposotory = container<BGReposotory>();
  }

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

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    // Configure BackgroundFetch.
    BackgroundFetch.configure(
            BackgroundFetchConfig(
              minimumFetchInterval: 1,
              forceAlarmManager: true,
              stopOnTerminate: false,
              startOnBoot: true,
              enableHeadless: true,
              requiresBatteryNotLow: false,
              requiresCharging: false,
              requiresStorageNotLow: false,
              requiresDeviceIdle: false,
              requiredNetworkType: NetworkType.ANY,
            ),
            _onBackgroundFetch)
        .then((int status) {
      print('[BackgroundFetch] configure success: $status');
      setState(() {
        _status = status;
      });
    }).catchError((e) {
      print('[BackgroundFetch] configure ERROR: $e');
      setState(() {
        _status = e;
      });
    });

    // Schedule a "one-shot" custom-task in 10000ms.
    // These are fairly reliable on Android (particularly with forceAlarmManager) but not iOS,
    // where device must be powered (and delay will be throttled by the OS).
    BackgroundFetch.scheduleTask(TaskConfig(
        taskId: "Saro.Background",
        delay: 1000,
        periodic: true,
        forceAlarmManager: false,
        stopOnTerminate: false,
        enableHeadless: true));

    // 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(String taskId) async {
    DateTime timestamp = new DateTime.now();
    // This is the fetch-event callback.
    print("[BackgroundFetch onForeground] Event received: $taskId $timestamp");
    var position = await Geolocator.getCurrentPosition(
        forceAndroidLocationManager: true,
        desiredAccuracy: LocationAccuracy.high);
   int res= await reposotory.updateDriverStatus(position);
    if (res != null && res == 1)
      print('success');
    else
      print('failure');
    // 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(taskId);
  }

  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 {
    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->Debug->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: <Widget>[
              Switch(value: _enabled, onChanged: _onClickEnable),
            ]),
        body: (_events.isEmpty)
            ? EMPTY_TEXT
            : Container(
                child: new ListView.builder(
                    itemCount: _events.length,
                    itemBuilder: (BuildContext context, int index) {
                      List<String> event = _events[index].split("@");
                      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: "[${event[0].toString()}]"),
                          child: new Text(event[1],
                              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: <Widget>[
                      RaisedButton(
                          onPressed: _onClickStatus,
                          child: Text('Status: $_status')),
                      RaisedButton(
                          onPressed: _onClickClear, child: Text('Clear'))
                    ]))),
      ),
    );
  }
}

@saravananmnm Your example does not include the main function. And I don't see a KiwiContainer().register(BGRepository)

I need an example that I can copy and past in my editor run it and it should work just like that. So remove the geolocation as well that is not related to this problem. So create a minimal example

from kiwi.

saravananmnm avatar saravananmnm commented on August 29, 2024
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  diConfig();
  BackgroundFetch.registerHeadlessTask(backgroundHeadlessTask);
  runApp(MyMainApp());
}

class MyMainApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primaryColor: Colors.blue,
      ),
      home: MyBGApp(),
    );
  }
}

from kiwi.

vanlooverenkoen avatar vanlooverenkoen commented on August 29, 2024

diConfig is not yet available

from kiwi.

saravananmnm avatar saravananmnm commented on August 29, 2024
import 'dart:io';

import 'package:fluttersamples/apiinterface/apiinterface.dart';
import 'package:fluttersamples/constants/constants.dart';
import 'package:fluttersamples/dto/driverstatusdto.dart';
import 'package:fluttersamples/dto/logindto.dart';
import 'package:fluttersamples/repository/backgroundrepository.dart';
import 'package:http/http.dart';
import 'package:http/io_client.dart';
import 'package:jaguar_retrofit/jaguar_retrofit.dart';
import 'package:jaguar_serializer/jaguar_serializer.dart';
import 'package:kiwi/kiwi.dart';

final KiwiContainer container = new KiwiContainer();

diConfig() {
  jaguarRetrofit();
}

jaguarRetrofit() {
  container.registerSingleton((c) => globalClient = IOClient());
  container.registerSingleton((c) => JsonRepo()
    ..add(new LoginModelSerializer())
    ..add(new DriverStatusModelSerializer()));

  container.registerSingleton((c) => ApiInterface(
          Route(Constants.DEV_URL).withClient(
        RestyIOClient(
          HttpClient()
            ..connectionTimeout = const Duration(minutes: 5)
            ..idleTimeout = const Duration(seconds: 60)
            ..userAgent = 'CA Driver',
        )..timeout = Duration(minutes: 5),
      )
            ..before((req) async {
              req.header('timezone', "Asia/Kolkata");
              print(req.getUrl);
              print(req.getHeaders);
              if (req is RouteWithBody) {
                print(req.getBody());
              }
            })
            ..after((res) {
              print(res.request.url);
              print(res.statusCode);
              print(res.body);
            }))
        ..jsonConverter = c<JsonRepo>());

  container.registerSingleton((c) => BGReposotory(container<ApiInterface>()));
}


class RestyIOClient extends IOClient {
  Duration timeout;

  RestyIOClient([inner]) : super(inner);

  @override
  Future<IOStreamedResponse> send(BaseRequest request) async {
    return await timeout != null
        ? super.send(request).timeout(timeout)
        : super.send(request);
  }
}

from kiwi.

vanlooverenkoen avatar vanlooverenkoen commented on August 29, 2024

Alright thanks. I just got the same error in my example as well after taking a look at your full example. I am first taking a deeper look into headless dart code. How it exactly works.

from kiwi.

saravananmnm avatar saravananmnm commented on August 29, 2024

Alright @vanlooverenkoen fine. Let me know your solutions.

from kiwi.

vanlooverenkoen avatar vanlooverenkoen commented on August 29, 2024

@saravananmnm 1 more question are you having this problem only on Android? Because iOS won't run when the app is terminated? Or on both platforms?

from kiwi.

saravananmnm avatar saravananmnm commented on August 29, 2024

@vanlooverenkoen Am faced this issue from both plarforms.

from kiwi.

vanlooverenkoen avatar vanlooverenkoen commented on August 29, 2024

And the app is completely terminated? Removed from recents. Or is the app just in the background?

from kiwi.

vanlooverenkoen avatar vanlooverenkoen commented on August 29, 2024

transistorsoft/flutter_background_fetch#32 (comment)

How is it possible that you can run a headless implemation on iOS? That is not supported by iOS itself.

from kiwi.

vanlooverenkoen avatar vanlooverenkoen commented on August 29, 2024

Regarding the Android problem this is because android will release these objects. Only the callback can bu used to trigger dart code. The sollution that works is to call your diConfig() in you too level function.

This wil offcourse result in new objects but. But the kiwi container wil have all the objects you registered. As far as I can see there is no way to keep these the objects in the KiwiContainer. So calling diConfig() again is the way to go.

from kiwi.

saravananmnm avatar saravananmnm commented on August 29, 2024

Thanks for the solution @vanlooverenkoen.It's save my day.

from kiwi.

vanlooverenkoen avatar vanlooverenkoen commented on August 29, 2024

@saravananmnm no problem. Sorry it took so long.

from kiwi.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.