Skip to content

🐞[Workmanager periodic task does not execute in background/killed state] #634

@umair-ilyas

Description

@umair-ilyas
  • I have ran the sample app and it does not work there
  • I have read the README
  • I have done the setup for Android
  • I have done the setup for iOS

Version

| Technology | Version |
| Flutter | 3.24.0 |
| Workmanager version | 0.7.0 |
| Xcode version | |
| Swift version | |
| iOS deployment target| |

Describe the error
I’m using the workmanager plugin in a Flutter app to log the country name every 45 minutes. The task is working fine in foreground and while the app is open. However, the periodic task is not running when the app is killed or in background, even after waiting more than 1 hour.
Note: I also tried to run the sample app. Still the periodic function also not work. I run the app, try to Start the Flutter background service. Nothing happens. After that run failed or register off task. They run perfectly. But periodic task didnot run.

Can you guide me what is going wrong even i am running the example app. Still periodic task didnot run in killed state. I tested right now in android only.

I am sharing the setup of android and ios along with main.dart

Android Manifest

 ```
    
    
    
    
    

    
        
            
            
            
                
                
            
        
        
        

        
    
    
    
        
            
            
        
    

 ``` 

app/Build.gradle

 ```
plugins {
    id("com.android.application")
    id("kotlin-android")
    // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
    id("dev.flutter.flutter-gradle-plugin")
}

android {
    namespace = "com.example.workmanagertesting"
    compileSdk = flutter.compileSdkVersion
    ndkVersion = flutter.ndkVersion

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }

    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_11.toString()
    }

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId = "com.example.workmanagertesting"
        // You can update the following values to match your application needs.
        // For more information, see: https://flutter.dev/to/review-gradle-config.
        minSdk = 21
        targetSdk = flutter.targetSdkVersion
        versionCode = flutter.versionCode
        versionName = flutter.versionName
    }

    buildTypes {
        release {
            // TODO: Add your own signing config for the release build.
            // Signing with the debug keys for now, so `flutter run --release` works.
            signingConfig = signingConfigs.getByName("debug")
        }
    }
}

flutter {
    source = "../.."
}

  ``` 

Main.dart

 ```import 'package:flutter/material.dart';
import 'package:workmanager/workmanager.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:path_provider/path_provider.dart';
import 'package:geolocator/geolocator.dart';
import 'package:geocoding/geocoding.dart';
import 'dart:io';
import 'package:permission_handler/permission_handler.dart';

@pragma('vm:entry-point')
void callbackDispatcher() {
  Workmanager().executeTask((task, inputData) async {
    WidgetsFlutterBinding.ensureInitialized();

    final directory = await getApplicationDocumentsDirectory();
    Hive.init(directory.path);
    final box = await Hive.openBox('locationLogs');

    final permission = await Geolocator.checkPermission();
    if (permission == LocationPermission.denied ||
        permission == LocationPermission.deniedForever) {
      return Future.value(false);
    }

    Position position = await Geolocator.getCurrentPosition();
    List placemarks =
    await placemarkFromCoordinates(position.latitude, position.longitude);
    String country = placemarks.first.country ?? 'Unknown';

    await box.add({
      'country': country,
      'timestamp': DateTime.now().toIso8601String(),
    });

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


void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final directory = await getApplicationDocumentsDirectory();
  await Hive.initFlutter(directory.path);
  await Hive.openBox('locationLogs');

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

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(home: LogListScreen());
  }
}

class LogListScreen extends StatefulWidget {
  const LogListScreen({super.key});

  @override
  State createState() => _LogListScreenState();
}
Future getCountryFromCoordinates(double latitude, double longitude) async {
  final placemarks = await placemarkFromCoordinates(latitude, longitude);
  return placemarks.isNotEmpty ? placemarks.first.country ?? 'Unknown' : 'Unknown';
}

class _LogListScreenState extends State {
  bool loggingStarted = false;

  Future startLogging() async {
    var status = await Permission.location.request();

    if (status.isDenied || status.isPermanentlyDenied) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text("Location permission denied")),
      );
      return;
    }

    if (await Permission.locationAlways.isDenied) {
      var backgroundStatus = await Permission.locationAlways.request();
      if (!backgroundStatus.isGranted) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text("Background location permission denied")),
        );
        return;
      }
    }

    // Get location + country once
    Position position = await Geolocator.getCurrentPosition();
    String country = await getCountryFromCoordinates(position.latitude, position.longitude);
    final box = Hive.box('locationLogs');
    await box.add({'country': country, 'timestamp': DateTime.now().toIso8601String()});

    // Schedule every 45 mins
 // Optional
    await Workmanager().registerPeriodicTask(
      "log_country_task",
      "logCountryWorker",
      frequency: const Duration(minutes: 45),
      initialDelay: const Duration(seconds: 5),
      existingWorkPolicy: ExistingWorkPolicy.keep,
      constraints: Constraints(networkType: NetworkType.connected,
        requiresBatteryNotLow: true,
        requiresCharging: false,
        requiresDeviceIdle: false,
        requiresStorageNotLow: true,),
    );

    setState(() {
      loggingStarted = true;
    });
  }

  @override
  Widget build(BuildContext context) {
    final box = Hive.box('locationLogs');

    return Scaffold(
      appBar: AppBar(title: const Text('Country Visit Logs'),actions: [
        TextButton(onPressed: () async{
          await Workmanager().cancelAll();
    }, child: Text("Cancel"))

      ],),
      floatingActionButton: FloatingActionButton.extended(
        label: const Text("Start Logging"),
        onPressed: loggingStarted ? null : startLogging,
        icon: const Icon(Icons.location_on),
      ),
      body: ValueListenableBuilder(
        valueListenable: box.listenable(),
        builder: (context, box, _) {
          final logs = box.values.toList();
          return RefreshIndicator(
            onRefresh: () async {
              await Future.delayed(const Duration(milliseconds: 500));
              setState(() {});
            },
            child: logs.isEmpty
                ? ListView(
              children: const [
                Center(
                    child: Padding(
                      padding: EdgeInsets.all(16),
                      child: Text("No logs yet."),
                    ))
              ],
            )
                : ListView.builder(
              itemCount: logs.length,
              itemBuilder: (context, index) {
                final entry = logs[index] as Map;
                return ListTile(
                  title: Text(entry['country'] ?? 'Unknown'),
                  subtitle: Text(entry['timestamp'] ?? ''),
                );
              },
            ),
          );
        },
      ),
    );
  }
}





``` 

[✓] Flutter (Channel stable, 3.24.0, on macOS 15.3.1 24D70 darwin-arm64, locale en-PK)
• Flutter version 3.24.0 on channel stable at /Users/umair/Downloads/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision 80c2e84975 (1 year ago), 2024-07-30 23:06:49 +0700
• Engine revision b8800d88be
• Dart version 3.5.0
• DevTools version 2.37.2

[!] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
• Android SDK at /Users/umair/Library/Android/sdk
• Platform android-35, build-tools 35.0.0
• Java binary at: /Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment Microsoft-40648 (build 11.0.16.1+1-LTS)
✗ Android license status unknown.
Run flutter doctor --android-licenses to accept the SDK licenses.
See https://flutter.dev/to/macos-android-setup for more details.

[✓] Xcode - develop for iOS and macOS (Xcode 16.2)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 16C5032a
• CocoaPods version 1.16.2

[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2022.3)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b829.9-10027231)

[✓] Android Studio (version 2023.3)
• Android Studio at /Applications/Android Studio 2.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11572160)

[✓] Android Studio (version 2024.3)
• Android Studio at /Applications/Android Studio 3.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 21.0.6+-13368085-b895.109)

[✓] VS Code (version 1.82.2)
• VS Code at /Users/umair/Downloads/Visual Studio Code.app/Contents
• Flutter extension can be installed from:
🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] VS Code (version 1.82.2)
• VS Code at /Users/umair/Downloads/Visual Studio Code 2.app/Contents
• Flutter extension can be installed from:
🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] Connected device (5 available)
• sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64 • Android 14 (API 34) (emulator)
• iPhone 15 Pro (mobile) • 2762DEB4-EAEF-4788-9111-7CAFFF476E0C • ios • com.apple.CoreSimulator.SimRuntime.iOS-17-0 (simulator)
• macOS (desktop) • macos • darwin-arm64 • macOS 15.3.1 24D70 darwin-arm64
• Mac Designed for iPad (desktop) • mac-designed-for-ipad • darwin • macOS 15.3.1 24D70 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 138.0.7204.184

[✓] Network resources
• All expected network resources are available.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions