Comments (24)
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.
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.
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.
container.registerSingleton((c) => BackgroundService(container<CollectionDeliveryRepository>(),container<SaveOrdersDetailsDAO>(),container<OrdersMasterDAO>()));
from kiwi.
any solutions about this issue?
from kiwi.
Oh I'm sorry I completely forgot. Today I have time to investigate.
from kiwi.
@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.
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.
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.
@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.
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.
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.
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.
diConfig is not yet available
from kiwi.
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.
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.
Alright @vanlooverenkoen fine. Let me know your solutions.
from kiwi.
@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.
@vanlooverenkoen Am faced this issue from both plarforms.
from kiwi.
And the app is completely terminated? Removed from recents. Or is the app just in the background?
from kiwi.
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.
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.
Thanks for the solution @vanlooverenkoen.It's save my day.
from kiwi.
@saravananmnm no problem. Sorry it took so long.
from kiwi.
Related Issues (20)
- Kiwi generator crash boolean expression must not be null HOT 2
- Migrate example project to v2 android
- Add support for nullability HOT 8
- between kiwi and flutter_test version solving failed. issue HOT 2
- Add no response bot
- Null Safety HOT 1
- How can I create scoped container? HOT 2
- Generate custom Stateless widget and State HOT 1
- The type `Object` was not registered HOT 1
- Can I create `kiwi_generator` record for a string? HOT 7
- Use cascade operator in generated code HOT 3
- Doesn't work with build_runner 2.0.4 HOT 6
- Update analyzer ^1.7.1 to analyzer ^2.0.0 HOT 3
- Can't use try/catch with kiwi
- Class could not be registered correctly even when defaults are specified
- Code generator does not play nice with mockito HOT 1
- Kiwi injection not working in background/app killed state. HOT 4
- Allow analyzer version 4.x. HOT 1
- migrate to github actions HOT 1
- It is not generating anything HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from kiwi.