我正在创建一个 Flutter 应用程序,需要在应用程序关闭时以大约 15-30 秒的频率获取用户的位置。目前,我使用“位置”flutter 包,它允许我在应用程序打开但不在屏幕上时获取位置。但是,我希望在关闭应用程序并打开手机时跟踪位置。
我尝试过使用地理定位器和工作管理器来检索位置,但它们的最小频率为 15 分钟,这太罕见了。我目前使用“位置”包,但是当应用程序关闭时它会停止运行并且不会在启动时运行。我找到了 flutter_background_geolocation,但它不是开源的。
这是我的实现:
myapp/android/app/main/java/com/flutter/myapp/LocationService.kt
package com.flutter.myapp
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Intent
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationResult
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.FusedLocationProviderClient
class LocationService : Service() {
private val CHANNEL_ID = "ForegroundServiceChannel"
private lateinit var fusedLocationClient: FusedLocationProviderClient
private lateinit var locationCallback: LocationCallback
override fun onCreate() {
super.onCreate()
createNotificationChannel()
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
super.onLocationResult(locationResult)
locationResult?.let {
// Handle location update here
val location = it.lastLocation
}
}
startLocationUpdates()
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val serviceChannel = NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
)
val manager = getSystemService(NotificationManager::class.java)
manager.createNotificationChannel(serviceChannel)
}
}
private fun startLocationUpdates() {
val locationRequest = LocationRequest.create().apply {
interval = 15000
fastestInterval = 5000
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val notification: Notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Location Service")
.setContentText("Tracking your location...")
.setContentIntent(getPendingIntent())
.build()
startForeground(1, notification)
return START_STICKY
}
private fun getPendingIntent(): PendingIntent {
val notificationIntent = Intent(this, MainActivity::class.java)
return PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE)
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onDestroy() {
super.onDestroy()
fusedLocationClient.removeLocationUpdates(locationCallback)
}
}
添加到 myapp/android/app/main/kotlin/com/flutter/myapp/MainActivity.kt:
<service
android:name=".LocationService"
android:enabled="true"
android:exported="false"/>
服务的使用:
class ForegroundService {
static const platform =
MethodChannel('com.flutter.myapp/locationService');
Future<void> startService() async {
try {
final intent = AndroidIntent(
action: 'com.flutter.myapp.START_LOCATION_SERVICE',
package: 'com.flutter.myapp',
componentName: 'com.flutter.myapp/.LocationService',
flags: <int>[Flag.FLAG_ACTIVITY_NEW_TASK],
);
intent.sendBroadcast();
await platform.invokeMethod('startService');
} on PlatformException catch (e) {
print("Failed to start service: '${e.message}'.");
}
}
Future<void> stopService() async {
try {
await platform.invokeMethod('stopService');
} on PlatformException catch (e) {
print("Failed to stop service: '${e.message}'.");
}
}
当我关闭应用程序(即在应用程序列表中向上滑动)时,这会打印在日志中:
D/FlutterGeolocator(27222): Detaching Geolocator from activity
D/FlutterGeolocator(27222): Flutter engine disconnected. Connected engine count 0
D/FlutterGeolocator(27222): Disposing Geolocator services
E/FlutterGeolocator(27222): Geolocator position updates stopped
D/FlutterGeolocator(27222): Stopping location service.
D/FlutterLocationService(27222): Unbinding from location service.
D/FlutterLocationService(27222): Destroying service.
D/FlutterGeolocator(27222): Unbinding from location service.
D/FlutterGeolocator(27222): Destroying location service.
D/FlutterGeolocator(27222): Stopping location service.
D/FlutterGeolocator(27222): Destroyed location service.
有一个包 background locator 可以解决这个问题。 请检查这个问题,希望有帮助。