transistorsoft / flutter_background_geolocation

Sophisticated, battery-conscious background-geolocation & geofencing with motion-detection
https://www.transistorsoft.com/shop/products/flutter-background-geolocation
Other
640 stars 236 forks source link

headless with state management or providers #167

Closed niypoo closed 4 years ago

niypoo commented 4 years ago

Your Environment

in main.dart if(Platform.isAndroid){

      void headlessTask(bg.HeadlessEvent headlessEvent) async {
        print('[BackgroundGeolocation HeadlessTask]: $headlessEvent');
        ListsProvider  listsProvider = Provider.of<ListsProvider>(context, listen: false);
        // Implement a 'case' for only those events you're interested in.
        switch(headlessEvent.name) {
          case bg.Event.LOCATION:
            bg.Location location = headlessEvent.event;
            LocationListenerHelper.onLocation(location,listsProvider);
            print('- Location: $location');
            break;
        }
      }

      bg.BackgroundGeolocation.registerHeadlessTask(headlessTask);
    }


## Expected Behavior
I'm trying to use headless in android it's work great but I need use Providers or state management with it to check my location in database but I can't figure out what the way once give me 

> I/flutter ( 9015): [BackgroundGeolocation _headlessCallbackDispather] ‼️ Callback error: NoSuchMethodError: No top-level getter 'headlessTask' declared.
I/flutter ( 9015): Receiver: top-level
I/flutter ( 9015): Tried calling: headlessTask

and once give me 

> E/flutter ( 9015): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The method 'toRawHandle' was called on null.
E/flutter ( 9015): Receiver: null
E/flutter ( 9015): Tried calling: toRawHandle()

## Context
in main.dart 
main Function once
and I'm tried in myApp() function 
christocracy commented 4 years ago

Don't do this:

if(Platform.isAndroid){
   ...
}
christocracy commented 4 years ago

And also make sure your void headlessTask() is not defined in the function void main(). Do it exactly as documented

📂 main.dart

// Headless function defined "in top level"
void headlessTask(bg.HeadlessEvent event) async {
  print('headlessTask');
}

void main() {
  runApp(YourApp());
  // Headless function registered within main()
  bg.BackgroundGeolocation.registerHeadlessTask(headlessTask);
}
niypoo commented 4 years ago

@christocracy thanks for reply , and Happy new year, now I change all my way I depended on sqlite for handle my data and do what do you said and exactly what you wrote in documentation but I'm facing also issues , there is a wrong in my code but I don't know what is it !

main.dart

void headlessTask(bg.HeadlessEvent headlessEvent) async {
  print('[BackgroundGeolocation HeadlessTask]: $headlessEvent');
  // Implement a 'case' for only those events you're interested in.
  switch(headlessEvent.name) {
    case bg.Event.LOCATION:
      bg.Location location = headlessEvent.event;
      await LocationListenerHelper.onLocation(location);
      print('- Location: $location');
      break;
    case bg.Event.MOTIONCHANGE:
      bg.Location location = headlessEvent.event;
      await LocationListenerHelper.onLocation(location);
      print('- Location: $location');
      break;
  }
}

void main() async {
  runApp( MyApp());
  // Register your headlessTask:
  bg.BackgroundGeolocation.registerHeadlessTask(headlessTask); 
}

home.dart

void initState() {
    /* for run those helpers after draw done */
    Future.delayed(Duration.zero).then(
      (_) {
      // /*
      //   open and init Sqlite Database
      // */
      // SqLiteHelper().databaseInitAndOpen();

        /* 
      init Dynamic Link and listen if there any 
      dynamic link recived */
      DynamicLinkHelper(context).initListen();

        /*
      init Firebase Cloud Messaging 
      and create Listener for any callback if user click or 
      when app in background or terminated */
      FCMHelper(context).init();

        /* 
      Local Notification init & Configration Listener For 
      any notification click call back */
      LocalNotificationsHelper().init(context);

        /* 
      Geo Location Listener that will listen for location and 
      check lists and items locations and notification user if
      he's near from any of them */
      LocationListenerHelper(distanceListener: 20).init();

      },
    );
    super.initState();
  }

onLocation helper


  Future<void> init() async {
    // if battery_save_power_mode is on I stop listen
    bool batterSavePowerMode =
        await LocalStorageHelper.getByKey('battery_save_power_mode');

    if (batterSavePowerMode != true) {
      // Fired whenever a location is recorded
      bg.BackgroundGeolocation.onLocation(onLocation, _onLocationError);
      print('[Background location init]');
      //BackGround Geoloacation init
      bg.State state = await bg.BackgroundGeolocation.ready(bg.Config(
        desiredAccuracy: bg.Config.DESIRED_ACCURACY_HIGH,
        distanceFilter: distanceListener,
        stopOnTerminate: false,
        startOnBoot: true,
        enableHeadless: true,
        debug: true,
        logLevel: bg.Config.LOG_LEVEL_OFF,
      ));
      print('state.enabled ${state.enabled}');
      if (!state.enabled) bg.BackgroundGeolocation.start();
    }
  }

/*
    Check current Location and lists and items's location and if user
    near by any one of them I push notification
   */
  static Future<void> onLocation(bg.Location location) async {

    List<Map<String, dynamic>> objects = await 
    SqLiteHelper.query(table:'itemslocations');

    if (objects == null || objects.length == 0) {return;}

    print('[new Location listen] ....');
    //? latLng of current location
    LatLng currentLatlng =
        LatLng(location.coords.latitude, location.coords.longitude);

     ///// handle the locations data here

}

the error is

E/flutter (16295): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: MissingPluginException(No implementation found for method getDatabasesPath on channel com.tekartik.sqflite)

[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: MissingPluginException(No implementation found for method getDatabasesPath on channel com.tekartik.sqflite)

I recored my test maybe there is something weird I'm wrong with. https://youtu.be/zuA4BmTjt8w

niypoo commented 4 years ago

I'm trying also remove my own headless task handle and depended on your package handle it's work also when app is opening but after terminated it i hear the debug sound but my app doesn't live don't give me any notification like when he open

christocracy commented 4 years ago

It makes me angry when people flood the thread with logs. I’m not looking at any of that or anything else in this thread until you clean that up.

niypoo commented 4 years ago

any handle code by me inside Future<void> headlessTask(bg.HeadlessEvent headlessEvent) async { doesn't work any code even SharedPreferences SharedPreferences localStorage = await SharedPreferences.getInstance(); return localStorage.get(key);

it's give me

[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences)

christocracy commented 4 years ago

Have you Upgraded your Flutter Android Project?

niypoo commented 4 years ago

no , i didn't upgrade yet !

christocracy commented 4 years ago

I strongly suggest you do so. Flutter has completely refactored their "headless" mechanism. You no longer need to do any extra steps in a custom Application java class any more. It's all automatic, but you must upgrade to new api. Follow the directions in the link above.

niypoo commented 4 years ago

I did it but now all issues that occurred when background_featch happened when app lunch I check every dependences now and after make app work as expected I will test your package point , sorry for any abuse

niypoo commented 4 years ago

I'm facing a same issue background don't hear after terminated app my AndroidMinfest.xml

I have used android:name=".MainActivity" instead android:name="io.flutter.embedding.android.FlutterActivity" to avoid google_maps unregister issue .

<application
        tools:replace="android:label"
        android:label="myapp" ...... > ....
      <activity
            android:name=".MainActivity"
            android:theme="@style/LaunchTheme" .....

MainActivity.kt is package codes.nudge.pow

import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant

class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine);
    }
}

my main.dart


Future<void> headlessTask(bg.HeadlessEvent headlessEvent) async {
  print('--==-=----=-=-=-=-=-=--[BackgroundGeolocation HeadlessTask]: $headlessEvent');
  switch(headlessEvent.name) {
    case bg.Event.LOCATION:
      bg.Location location = headlessEvent.event;  
      print('- Location: $location');
      await LocationListenerHelper.onLocation(location);
      break;
    case bg.Event.MOTIONCHANGE:
      bg.Location location = headlessEvent.event;
      print('- Location: $location');
      await LocationListenerHelper.onLocation(location);
      break;
  }
}

void main() async {
  runApp(LocalizedApp(delegate, MyApp()));

  // Register your headlessTask:
  bg.BackgroundGeolocation.registerHeadlessTask(headlessTask);

}

my flutter --version

Flutter 1.12.13+hotfix.5 • channel stable • https://github.com/flutter/flutter.git Framework • revision 27321ebbad (3 weeks ago) • 2019-12-10 18:15:01 -0800 Engine • revision 2994f7e1e6 Tools • Dart 2.7.0

when app is opened it's receives and handle very well but after app terminated not receives any background calls

niypoo commented 4 years ago

final I have received background call after create new project only with java and move my code to new project but I can't access on any package like sqflite or SharedPreferences

sqflite gives me

[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The method 'query' was called on null.

and when try open database before query to ensure the database is not null gives

Unhandled Exception: MissingPluginException(No implementation found for method getDatabasesPath on channel com.tekartik.sqflite)

SharedPreferences gives me

Unhandled Exception: MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences)

christocracy commented 4 years ago

Could you please generate a simple hello-world project and share the github repo with me.

niypoo commented 4 years ago

I create new app just with your package and it's working as good , so I think this issue is conflict with other package so i have added one by one and I think I have figure out what package is make this issue that called "google_places_picker: ^2.0.2+2"

this is a project link in github please check it due to I can't test backend fetch as good as I think https://github.com/niypoo/headless_test.git

niypoo commented 4 years ago

is there any way to handle data from sqflite not SharedPreferences, sqflite not work in backend fetch.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. You may also mark this issue as a "discussion" and I will leave this open.

stale[bot] commented 4 years ago

Closing this issue after a prolonged period of inactivity. Fell free to reopen this issue, if this still affecting you.

aweiand commented 4 years ago

Hi people! You'l find an answer for the problem? I'm have the same problem. Don't save to sqflite in background...

Vish88781 commented 2 years ago

https://github.com/transistorsoft/flutter_background_fetch/issues/283
Hope this will solve your Unhandled Exception: MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences) @niypoo