Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Http Network call is not working (Flutter Android) #171

Closed
VarmaTech opened this issue May 12, 2020 · 30 comments
Closed

Http Network call is not working (Flutter Android) #171

VarmaTech opened this issue May 12, 2020 · 30 comments
Labels
android Android specific answered Used to auto-close 'answered' issues after a certain time of inactivity help wanted Extra attention is needed

Comments

@VarmaTech
Copy link

Hi ,

I am using workmanager for syncing data from server using http plugin in flutter android . but nothing is happening when http is called . below i am attaching my sample for code for reference

Sample Code :

import 'dart:io';

import 'package:workmanager/workmanager.dart';
import 'package:http/http.dart' as http;

const httpSync = "httpSync";
demoBackgroundSync() {
  Workmanager.initialize(startJobs, isInDebugMode: false);
  Workmanager.registerOneOffTask("3", httpSync,
      initialDelay: Duration(seconds: 5),
      constraints: Constraints(
          networkType: NetworkType.connected,
          requiresBatteryNotLow: true,
          // requiresCharging: true,
          // requiresDeviceIdle: true,
          requiresStorageNotLow: true));
}

startJobs() {
  Workmanager.executeTask((task, inputData) {
    switch (task) {
      case httpSync:
        httpSyncApis();
        break;
    }
    print(
        "Native called background task: $task"); //simpleTask will be emitted here.
    return Future.value(true);
  });
}
Map<String, String> requestHeaders = {
        HttpHeaders.contentTypeHeader: 'application/json',
        HttpHeaders.acceptHeader: 'application/json',
        // "Access-Control-Allow-Origin": "*",
        // "Access-Control-Allow-Methods": "POST,GET,DELETE,PUT,OPTIONS"
        //  'Authorization': '<Your token>'
      };
void httpSyncApis() async{

    print('Api Request  : Started');
// till here code works but after this step nothing happening 
  var response = await http
          .get(
            'http://dummy.restapiexample.com/api/v1/employees',
            headers: requestHeaders,
          )
          .timeout(const Duration(seconds: 300));
    
    print('Response Code : ${response.statusCode}');
    print('Response Body : ${response.body}');
}

console logs :

D/HostConnection(24188): HostConnection::get() New Host Connection established 0xbaf2a4a0, tid 24365
D/HostConnection(24188): HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_YUV420_888_to_NV21 ANDROID_EMU_YUV_Cache ANDROID_EMU_async_unmap_buffer GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_gles_max_version_3_0
D/EGL_emulation(24188): eglMakeCurrent: 0xd5e1b4a0: ver 3 0 (tinfo 0xe9589cf0)
I/flutter (24188): Api Request  : Started
I/flutter (24188): Native called background task: httpSync
I/WM-WorkerWrapper(24188): Worker result SUCCESS for Work [ id=740eaba7-dc42-4a24-b6a4-906c1218d13c, tags={ be.tramckrijte.workmanager.BackgroundWorker } ]
@abuzar-rasool
Copy link

I am having the same issue.

@Lukitaduarte
Copy link

Me too, any ideia?

@gebsl
Copy link

gebsl commented Jun 8, 2020

Can you try changing function startJobs to this:

startJobs() {
  Workmanager.executeTask((task, inputData) async {
    switch (task) {
      case httpSync:
        await httpSyncApis();
        break;
    }
    print(
        "Native called background task: $task"); //simpleTask will be emitted here.
    return true;
  });
}

Please note the added async and await keywords, as well as the changed return value.

This way, a future (not completed) is returned which will only complete after awaiting httpSyncApis to finish.

My guess why yours is not working:

You are returning an already completed future. This might tell the system your task has finished successfully, therefore not executing further code. As your http call is async, it might be dropped by the system.

@Kymer Kymer added android Android specific answered Used to auto-close 'answered' issues after a certain time of inactivity help wanted Extra attention is needed labels Jul 3, 2020
@Kymer Kymer closed this as completed Jul 3, 2020
@trighomautumnatg
Copy link

I am having the same issue.

@trighomautumnatg
Copy link

trighomautumnatg commented Jul 28, 2020

Can you try changing function startJobs to this:

startJobs() {
  Workmanager.executeTask((task, inputData) async {
    switch (task) {
      case httpSync:
        await httpSyncApis();
        break;
    }
    print(
        "Native called background task: $task"); //simpleTask will be emitted here.
    return true;
  });
}

Please note the added async and await keywords, as well as the changed return value.

This way, a future (not completed) is returned which will only complete after awaiting httpSyncApis to finish.

My guess why yours is not working:

You are returning an already completed future. This might tell the system your task has finished successfully, therefore not executing further code. As your http call is async, it might be dropped by the system.

It does not work

@gebsl
Copy link

gebsl commented Jul 28, 2020

@trighomautumnatg: Can you post parts of your code? Without it's difficult to tell what's wrong.

@yekkaplan
Copy link

this solution is not worked

Can you try changing function startJobs to this:

startJobs() {
  Workmanager.executeTask((task, inputData) async {
    switch (task) {
      case httpSync:
        await httpSyncApis();
        break;
    }
    print(
        "Native called background task: $task"); //simpleTask will be emitted here.
    return true;
  });
}

Please note the added async and await keywords, as well as the changed return value.

This way, a future (not completed) is returned which will only complete after awaiting httpSyncApis to finish.

My guess why yours is not working:

You are returning an already completed future. This might tell the system your task has finished successfully, therefore not executing further code. As your http call is async, it might be dropped by the system.

@gebsl
Copy link

gebsl commented Aug 28, 2020

@yekkaplan: Same here, can you post your code?

@mustafaynk
Copy link

mustafaynk commented Sep 18, 2020

I have some issue. This is my code;

void callbackDispatcher() { Workmanager.executeTask((taskName, inputData) async { switch (taskName) { case myTask: print('Alarm Control 1'); keysControls().then((value) async { print('Alarm Control 2'); if (value) { print('Alarm Control 3'); await getDataFromApi(); } }); break; } return Future.value(true); }); }

I can see in the console: "Alarm Control 1 - Alarm Control 2 - Alarm Control 3" but, getDataFromApi() doesn't fetch data. Actually, it doesn't request.

@gebsl
Copy link

gebsl commented Sep 18, 2020

@mustafaynk

First of all, please format you code. It's incredibly hard to read it like this.

Try this:

void callbackDispatcher() async {
  Workmanager.executeTask((taskName, inputData) async {
    switch (taskName) {
      case myTask:
        print('Alarm Control 1');

        await keysControls();
        print('Alarm Control 2');

        if (value) {
          print('Alarm Control 3');
          await getDataFromApi();
        }

        break;
    }
    return Future.value(true);
  });
}

Using async and await makes your code a lot more readable and should do what you want to achieve.

Why yours is not working? You are not awaiting the Future returned by method call keysControls, therefore the inner await getDataFromApi(); won't do anything, as the task is cancelled before the the data is fetched.

Hope this helps.

@mustafaynk
Copy link

@gebsl Sorry for bad code format because, I wrote first comment in GitHub. Actually, my problem is very obvious. My app request only one http request. I want to run http request method when app destroy. If you can help me, I will be very happy. Thanks for your reply. Have a good day.

@gebsl
Copy link

gebsl commented Sep 27, 2020

Hi @mustafaynk: You could try to combine this (https://flutter.dev/docs/get-started/flutter-for/android-devs#how-do-i-listen-to-android-activity-lifecycle-events) with flutter_workmanager.

Just run Workmanager.executeTask when the app is suspending and this should enable you to run your http call in the background.

@mustafaynk
Copy link

Hi again @gebsl ; I solved my problem. Thanks a lot.

@gebsl
Copy link

gebsl commented Sep 28, 2020

Hi @mustafaynk, can you state how you were able to solve the problem? Might also be interesting for other devs. Thanks!

@mustafaynk
Copy link

@gebsl Sure.
I called WorkManager initialize methods in initState(). WorkManager didn't work. After that, I called these methods in the 'main' method, work manager worked. Of course, I also used your advices.

@DeepaPradeepa
Copy link

Calldispatcher function does not called . Can you help me out

@DeepaPradeepa
Copy link

void callbackDispatcher() async {
Workmanager.executeTask((taskName, inputData) async {
switch (taskName) {
case fetchBackground:
print("backgroundfetchcalled in Android");
getcurrentlocation();
break;
case Workmanager.iOSBackgroundTask:
print("backgroundfetchcalled in ios");
break;
}
return true;
});

@gebsl
Copy link

gebsl commented Nov 3, 2020

Sorry, more code needed. And please format your code, it's hard to read like this.

@DeepaPradeepa
Copy link

@gebsl Please let me know how to format my code like yours

@DeepaPradeepa
Copy link

@gebsl Sure.
I called WorkManager initialize methods in initState(). WorkManager didn't work. After that, I called these methods in the 'main' method, work manager worked. Of course, I also used your advices.

Hi @mustafaynk . Can you share your worked code.

@gebsl
Copy link

gebsl commented Nov 3, 2020

@DeepaPradeepa please markup your code like this:

```dart
var x = 'yourcodegoeshere'
```

will then look like

var x = 'yourcodegoeshere'

@DeepaPradeepa
Copy link

void callbackDispatcher() async {
Workmanager.executeTask((taskName, inputData) async {
switch (taskName) {
case fetchBackground:
print("backgroundfetchcalled in Android");
getcurrentlocation();
break;
case Workmanager.iOSBackgroundTask:
print("backgroundfetchcalled in ios");
break;
}
return true;
});
}
void getcurrentlocation() async {
print("userLocationlatcalled");

try {

 // Position userLocation =  await Geolocator().getCurrentPosition(
 //     locationPermissionLevel: GeolocationPermission.location,desiredAccuracy:LocationAccuracy.high);
  print("userLocationcalled}");
 AppPreferences _appPreference;
 _appPreference = App().getAppPreferences();
 final prefs = await _appPreference.getAuthToken();
 // String tokenVal;
 LatLng userLocation = LatLng(9.98,78.11);
 //);
 await updateCurrentLoc1(userLocation,prefs);
} catch (e) {
print('Location not shared');
}
//Position userLocation = await Geolocator().getCurrentPosition(desiredAccuracy:LocationAccuracy.high);

}
Future updateCurrentLoc1(LatLng position,String token) async {
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
new FlutterLocalNotificationsPlugin();
var android = new AndroidNotificationDetails(
'1', 'location-bg', 'fetch location in background',
playSound: false, importance: Importance.Max, priority: Priority.High);
var iOS = new IOSNotificationDetails();
var platform = new NotificationDetails(android, iOS);

await flutterLocalNotificationsPlugin.show(
0, "locationtop", "${position.longitude}", platform);

GraphQLClient graphQLClientWithHeader;
HttpLink httpLink =
HttpLink(uri:"GraphQLEndPoint",
headers: <String, String>{
'auth':token,
},);
graphQLClientWithHeader = GraphQLClient(
cache: new InMemoryCache(),
link: httpLink ,
);
//print("authtoken: ${globals.authToken}");

var variables = <String, dynamic>{
"lat": position.latitude,
"lng": position.longitude
};

Map<String, dynamic> _login_result = await getMutationValues(
graphQLClientWithHeader,
"updateDriverLocation_mutation",
variables);

if (_login_result["updateDriverLocation"]["status"] == 200) {
print("location updated");

await flutterLocalNotificationsPlugin.show(
    0, "locationbottom", "${position.latitude}", platform);
//sendDriverLocation1();
return "";
} else if (_login_result["updateDriverLocation"]["status"] == 500) {
print("location notupdated");
await flutterLocalNotificationsPlugin.show(
0, "locationerror", "${_login_result["updateDriverLocation"]["errorMessage"]}", platform);
// sendDriverLocation1();
return "timeout";
} else {
print("location notupdated reason ${_login_result["updateDriverLocation"]["errorMessage"]}");
await flutterLocalNotificationsPlugin.show(
0, "locationerror", "${_login_result["updateDriverLocation"]["errorMessage"]}", platform);
return _login_result["updateDriverLocation"]["errorMessage"];
}
}

          void initState() {
// getcurrentlocation();

Workmanager.initialize(
    callbackDispatcher,
    isInDebugMode:true
);

Workmanager.registerPeriodicTask(
  "1",
  fetchBackground,
  frequency: Duration(seconds:30),
);
           }

@gebsl
Copy link

gebsl commented Nov 4, 2020

First of all, a frequency of 30 seconds is not supported. The minimum time between two background calls is always 15 minutes (on Android). On iOS, you can not control the frequency at all (due to platform restrictions).

Secondly, put an await before your function call to getcurrentlocation, as otherwise callbackDispatcher will exit before running the asynchronous call.

@DeepaPradeepa
Copy link

@gebsl Yes I know that time interval which is defaultly taken as 15 mins. I tried with await callbackDispatcher as well. But I am getting failure status background fetch Pushnotification

@gebsl
Copy link

gebsl commented Nov 4, 2020

@DeepaPradeepa, have you already tried the example project to verify whether this one works or not?

@DeepaPradeepa
Copy link

@gebsl Yes. I tried with local push notification which is worked fine. But Now API Call functionality does not work

@gebsl
Copy link

gebsl commented Nov 5, 2020

I just realize we are probably not talking about the same thing.

@gebsl Yes I know that time interval which is defaultly taken as 15 mins. I tried with await callbackDispatcher as well. But I am getting failure status background fetch Pushnotification

I proposed awaiting getcurrentlocation, but you wrote you awaited callbackDispatcher. That could be the problem.

@DeepaPradeepa
Copy link

DeepaPradeepa commented Nov 5, 2020

I just realize we are probably not talking about the same thing.

@gebsl Yes I know that time interval which is defaultly taken as 15 mins. I tried with await callbackDispatcher as well. But I am getting failure status background fetch Pushnotification

I proposed awaiting getcurrentlocation, but you wrote you awaited callbackDispatcher. That could be the problem.

Sorry @gebsl I wrongly told await callbackDispatcher . I have tried with await getcurrentlocation() . Same thing happened. Now I tried with native iOS Callback with Flutter. Thank you very much for helping.

@gebsl
Copy link

gebsl commented Nov 5, 2020

Oh, your issue is on iOS? I didn't know this. This whole thread is about workmanager on Android.

@Gerhardt0011
Copy link

Gerhardt0011 commented Feb 5, 2022

Had the same issue, managed to resolved the issue with the following code.

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await UserSharedPrefs.init();
  Location location = new Location();
  location.enableBackgroundMode();

  Workmanager().initialize(
    callbackDispatcher,
    isInDebugMode: true,
  );

  Workmanager().registerPeriodicTask(
      "update_location_worker", "update_location_worker",
      frequency: Duration(minutes: 15),
      inputData: {
        "lat": UserSharedPrefs.getLat(),
        "long": UserSharedPrefs.getLong()
      },
      initialDelay: Duration(minutes: 1),
      constraints: Constraints(
        networkType: NetworkType.connected,
      ));
  runApp(
    OnePush(),
  );
}

Before the main() method i have this function

void callbackDispatcher() {
  Workmanager().executeTask((taskName, inputData) async {
    await UserSharedPrefs.init();
    Position position = await Geolocator.getCurrentPosition();
    UserSharedPrefs.setLat(position.latitude);
    UserSharedPrefs.setLong(position.longitude);

    final String url = 'https://72b7-154-70-228-141.ngrok.io';
    final String path = 'api/lat_long_store';

    var bearerToken = UserSharedPrefs.getBearerToken();

    var headers = {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Authorization': 'Bearer $bearerToken'
    };

    final body = {'lat': position.latitude, 'long': position.longitude};

    await http.post(
      Uri.parse(url + '/' + path),
      headers: headers,
      body: jsonEncode(body),
    );

    LocalNotification.Initializer();
    LocalNotification.ShowOneTimeNotification(DateTime.now());
    return Future.value(true);
  });
}

see screenshot attached, this is making a http post request :)
image

I know it returns a 500 server error, but just wanted to show that it is working :)

@fluttercommunity fluttercommunity locked and limited conversation to collaborators Feb 5, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
android Android specific answered Used to auto-close 'answered' issues after a certain time of inactivity help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

10 participants