0

我希望我的应用程序在后台获取用户位置并发送到服务器。但我的应用每 15 分钟运行两次任务。我不确定是不是因为与模拟器或其他东西建立了新的连接。我没有在物理设备上检查这个。

15分钟后我的日志。

D/EGL_emulation( 5517): eglCreateContext: 0xb76d0c40: maj 2 min 0 rcv 2
D/EGL_emulation( 5517): eglCreateContext: 0xb76d07e0: maj 2 min 0 rcv 2
D/HostConnection( 5517): HostConnection::get() New Host Connection established 0xb76cdec0, tid 8672
D/HostConnection( 5517): 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_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_has_shared_slots_host_memory_allocator ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit ANDROID_EMU_sync_buffer_data ANDROID_EMU_read_color_buffer_dma GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_2 
D/EGL_emulation( 5517): eglMakeCurrent: 0xb76d07e0: ver 2 0 (tinfo 0xc09b2d30) (first time)
D/PathProviderPlugin( 5517): Use TaskQueues.
D/EGL_emulation( 5517): eglCreateContext: 0xb76e06f0: maj 2 min 0 rcv 2
D/EGL_emulation( 5517): eglCreateContext: 0xb76c6e50: maj 2 min 0 rcv 2
D/HostConnection( 5517): HostConnection::get() New Host Connection established 0xb76df880, tid 8675
D/HostConnection( 5517): 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_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_has_shared_slots_host_memory_allocator ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit ANDROID_EMU_sync_buffer_data ANDROID_EMU_read_color_buffer_dma GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_2 
D/EGL_emulation( 5517): eglMakeCurrent: 0xb76c6e50: ver 2 0 (tinfo 0xb9f6cf90) (first time)
D/PathProviderPlugin( 5517): Use TaskQueues.
I/flutter ( 5517): LocationTask was executed. inputData = null
I/flutter ( 5517): LocationTask was executed. inputData = null
I/flutter ( 5517): Api.sendLastLocationToServer
I/flutter ( 5517): Api.sendLastLocationToServer
I/flutter ( 5517): Send location
I/flutter ( 5517): Send location
I/WM-WorkerWrapper( 5517): Worker result SUCCESS for Work [ id=1db5828f-d784-4350-84bc-39d4bdbafac1, tags={ be.tramckrijte.workmanager.BackgroundWorker } ]
I/WM-WorkerWrapper( 5517): Worker result SUCCESS for Work [ id=05da0028-6002-4855-aecb-1ff5cdad7b53, tags={ be.tramckrijte.workmanager.BackgroundWorker } ]

我的主要代码包含 Workmanager。

const locationTaskKey = 'LocationTask';
const failedTaskKey = "failedTask";

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  LocationPermission permission = await Geolocator.checkPermission();
  if (permission == LocationPermission.denied) {
    permission = await Geolocator.requestPermission();
  }

  // Set up the SettingsController, which will glue user settings to multiple
  // Flutter Widgets.
  final settingsController = SettingsController(SettingsService());

  // Load the user's preferred theme while the splash screen is displayed.
  // This prevents a sudden theme change when the app is first displayed.
  await settingsController.loadSettings();

  // Run the app and pass in the SettingsController. The app listens to the
  // SettingsController for changes, then passes it further down to the
  // SettingsView.

  runApp(MyApp(settingsController: settingsController));
}

class MyApp extends StatelessWidget {
  const MyApp({
    Key? key,
    required this.settingsController,
  }) : super(key: key);

  final SettingsController settingsController;

  @override
  Widget build(BuildContext context) {
    Workmanager().initialize(
      callbackDispatcher,
      isInDebugMode: true,
    );

    Workmanager().registerPeriodicTask(
      "5",
      locationTaskKey,
      frequency: const Duration(minutes: 15),
      constraints: Constraints(
        networkType: NetworkType.not_required,
        requiresBatteryNotLow: false,
        // requiresCharging: true,
        // requiresDeviceIdle: true,
        requiresStorageNotLow: false,
      ),
    );

    // Glue the SettingsController to the MaterialApp.
    //
    // The AnimatedBuilder Widget listens to the SettingsController for changes.
    // Whenever the user updates their settings, the MaterialApp is rebuilt.
    return AnimatedBuilder(
      animation: settingsController,
      builder: (BuildContext context, Widget? child) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          restorationScopeId: 'MyApp',
          theme: AppTheme.newLightTheme(),
          darkTheme: AppTheme.newDarkTheme(),
          themeMode: settingsController.themeMode,
          onGenerateRoute: (RouteSettings routeSettings) {
            return MaterialPageRoute<void>(
              settings: routeSettings,
              builder: (BuildContext context) {
                switch (routeSettings.name) {
                  case MainScreen.routeName:
                    return MainScreen(settingsController: settingsController);
                  default:
                    return const ChooseLogin();
                }
              },
            );
          },
        );
      },
    );
  }
}

void callbackDispatcher() {
  Workmanager().executeTask((task, inputData) async {
    switch (task) {
      case locationTaskKey:
        debugPrint("$locationTaskKey was executed. inputData = $inputData");
        Position position = await determinePosition();
        Api api = Api();
        List<AppLocation> locations = [];
        locations.add(
          AppLocation(
            position.timestamp.toString(),
            position.longitude,
            position.latitude,
          ),
        );
        bool status = await api.sendLastLocationToServer(locations);
        if (status) {
          debugPrint('Send location');
        } else {
          debugPrint('can not Send location');
        }
        break;
      case failedTaskKey:
        debugPrint('failed task');
        return Future.error('failed');
    }

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

Future<Position> determinePosition() async {
  bool serviceEnabled;
  LocationPermission permission;

  // Test if location services are enabled.
  serviceEnabled = await Geolocator.isLocationServiceEnabled();
  if (!serviceEnabled) {
    // Location services are not enabled don't continue
    // accessing the position and request users of the
    // App to enable the location services.
    return Future.error('Location services are disabled.');
  }

  permission = await Geolocator.checkPermission();
  if (permission == LocationPermission.denied) {
    permission = await Geolocator.requestPermission();
    if (permission == LocationPermission.denied) {
      // Permissions are denied, next time you could try
      // requesting permissions again (this is also where
      // Android's shouldShowRequestPermissionRationale
      // returned true. According to Android guidelines
      // your App should show an explanatory UI now.
      return Future.error('Location permissions are denied');
    }
  }

  if (permission == LocationPermission.deniedForever) {
    // Permissions are denied forever, handle appropriately.
    return Future.error(
        'Location permissions are permanently denied, we cannot request permissions.');
  }

  // When we reach here, permissions are granted and we can
  // continue accessing the position of the device.
  return await Geolocator.getCurrentPosition(
      desiredAccuracy: LocationAccuracy.high);
}

扑医生 -v 信息。

[✓] Flutter (Channel stable, 2.8.1, on Ubuntu 20.04.3 LTS 5.11.0-46-generic, locale en_US.UTF-8)
    • Flutter version 2.8.1 at /home/mahmoudi/snap/flutter/common/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 77d935af4d (5 weeks ago), 2021-12-16 08:37:33 -0800
    • Engine revision 890a5fca2e
    • Dart version 2.15.1

[✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
    • Android SDK at /home/mahmoudi/Android/Sdk
    • Platform android-32, build-tools 32.0.0
    • Java binary at: /snap/android-studio/115/android-studio/jre/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7249189)
    • All Android licenses accepted.

[✓] Chrome - develop for the web
    • Chrome at google-chrome

[✓] Linux toolchain - develop for Linux desktop
    • clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
    • cmake version 3.10.2
    • ninja version 1.8.2
    • pkg-config version 0.29.1

[✓] Android Studio (version 2020.3)
    • Android Studio at /snap/android-studio/115/android-studio
    • Flutter plugin version 63.2.1
    • Dart plugin version 203.8452
    • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7249189)

[✓] VS Code (version 1.63.2)
    • VS Code at /usr/share/code
    • Flutter extension version 3.32.0

[✓] Connected device (3 available)
    • sdk gphone x86 (mobile) • emulator-5554 • android-x86    • Android 11 (API 30) (emulator)
    • Linux (desktop)         • linux         • linux-x64      • Ubuntu 20.04.3 LTS 5.11.0-46-generic
    • Chrome (web)            • chrome        • web-javascript • Google Chrome 97.0.4692.71

• No issues found!

4

0 回答 0