Android应用程序关闭后后台服务不停止



在我的flutter应用程序中,我编写了一个后台服务来获取用户位置。当应用程序在后台时,这个位置服务仍然获取用户的位置,应用程序仍然运行。

我不希望后台位置服务在用户终止应用程序后继续运行。

但是当我在Android上终止应用程序时,位置服务似乎还在运行。

当我第二次启动应用程序时,它不能正常工作。我想这是因为后台服务还在运行。

  • 如果我通过"强制停止"停止应用程序;第二次一切正常。

  • 如果我手动停止后台服务从应用程序(说从一个按钮点击,调用停止函数),然后关闭应用程序,再次一切工作正常。

有人能提供一些建议,如何停止后台服务,当我关闭应用程序?

MainActivity。kt;

class MainActivity: FlutterActivity() {

override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, LOCATION_CHANNEL).setMethodCallHandler {
call, result ->
if (call.method == "startLocationUpdate") {
var status = startUpdateLocation()
result.success(status.toString())
} else if (call.method == "stopLocationUpdate")
{
var status = stopUpdateLocation()
result.success(status.toString())
} else if (call.method == "isLocationPermissionEnabled")
{
var status = checkPermission()
result.success(status.toString())
}
else {
result.notImplemented()
}
}
EventChannel(flutterEngine.dartExecutor, LOCATION_EVENT_CHANNEL).setStreamHandler(
object : EventChannel.StreamHandler {
override fun onListen(arguments: Any?, events: EventChannel.EventSink) {
locationUpdateReceiver = receiveLocationUpdate(events)
}
override fun onCancel(arguments: Any?) {
unregisterReceiver(locationUpdateReceiver)
locationUpdateReceiver = null
isServiceStarted = false
}
}
)

}
override fun onDestroy() {
try {
if (locationUpdateReceiver != null )
{
unregisterReceiver(locationUpdateReceiver)
}
} catch (e: Exception) {
}
super.onDestroy()
}
private fun stopUpdateLocation() : Int {
if (isServiceStarted) {
unregisterReceiver(locationUpdateReceiver)
stopService(this)
isServiceStarted = false
return SUCCESS
}
else {
return SERVICE_NOT_RUNNING
}
}
private fun startUpdateLocation() : Int {
if (isServiceStarted) {
return SERVICE_ALREADY_STARTED
}
else if (!checkPermission()) {
//requestPermission()
return REQUESTING_PERMISSION
}
else {
registerReceiver(locationUpdateReceiver, locationIntentFilter);
isServiceStarted = true
startService(this)
return SUCCESS
}
}
private fun receiveLocationUpdate(events: EventChannel.EventSink): BroadcastReceiver {
return object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val key = LocationManager.KEY_LOCATION_CHANGED
val location: Location? = intent.extras!![key] as Location?
if (location != null) {
val runningAppProcessInfo = ActivityManager.RunningAppProcessInfo()
ActivityManager.getMyMemoryState(runningAppProcessInfo)
var appRunningBackground: Boolean = runningAppProcessInfo.importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
if (appRunningBackground) {
events.success("0," + location.latitude.toString() + "," + location.longitude.toString())
}
else {
events.success("1," + location.latitude.toString() + "," + location.longitude.toString())
}
}
}
}
}
private fun checkPermission(): Boolean {
val result = ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.ACCESS_FINE_LOCATION)
val result1 = ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.ACCESS_COARSE_LOCATION)
return result == PackageManager.PERMISSION_GRANTED && result1 == PackageManager.PERMISSION_GRANTED
}

companion object {
private const val LOCATION_CHANNEL = "flutter.io/location"
private const val LOCATION_EVENT_CHANNEL = "flutter.io/locationEvent"
private const val LOCATION_UPDATE_INTENT = "FLUTTER_LOCATION"
private const val PERMISSION_REQUEST_CODE = 1
private final const val SERVICE_NOT_RUNNING = 0;
private final const val SUCCESS = 1;
private final const val REQUESTING_PERMISSION = 100;
private final const val SERVICE_ALREADY_STARTED = 2;
var isServiceStarted = false
var duration = "1" ;
var distance = "20";
var locationIntentFilter = IntentFilter(LOCATION_UPDATE_INTENT)
var locationUpdateReceiver: BroadcastReceiver? = null
fun startService(context: Context) {
val startIntent = Intent(context, LocationService::class.java)
ContextCompat.startForegroundService(context, startIntent)
}
fun stopService(context: Context) {
val stopIntent = Intent(context, LocationService::class.java)
context.stopService(stopIntent)
}
}
}

在LocationSerivice.kt

class LocationService : Service() {
private val NOTIFICATION_CHANNEL_ID = "notification_location"
private val duration = 5 // In Seconds
private val distance = 0  // In Meters
override fun onCreate() {
super.onCreate()
isServiceStarted = true
val builder: NotificationCompat.Builder =
NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setOngoing(false)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager: NotificationManager =
getSystemService(NOTIFICATION_SERVICE) as NotificationManager
val notificationChannel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW
)
notificationChannel.description = NOTIFICATION_CHANNEL_ID
notificationChannel.setSound(null, null)
notificationManager.createNotificationChannel(notificationChannel)
startForeground(1, builder.build())
}
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
LocationHelper().startListeningLocation(this, duration, distance);
return START_STICKY
}
override fun onBind(intent: Intent): IBinder? {
return null
}
override fun onDestroy() {
super.onDestroy()
isServiceStarted = false
}
override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent)
stopSelf()
}
companion object {
var isServiceStarted = false
}
}

在我的AndroidManifest.xml中我有

android:name=".LocationService"
android:enabled="true"
android:exported="true"
android:stopWithTask="true"

在我的flutter应用程序中,我调用了

中的stop服务
@override
void dispose() async {
if (_locationUpdateEventStarted) {
await methodChannel.invokeMethod('stopLocationUpdate');
}
super.dispose();
}

我也试着遵循,但它也没有工作

@override
void didChangeAppLifecycleState(AppLifecycleState state) async {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.detached) {

if (_locationUpdateEventStarted) {
await methodChannel.invokeMethod('stopLocationUpdate');
}
}
}

我使用flutter_background_service有类似或相同的问题. 我正在修改onTaskRemoved.

flutter_background_service通过invoemethod ("stopService")停止。所以,我发现stopService方法代码。

if (method.equalsIgnoreCase("stopService")) {
isManuallyStopped = true;
WatchdogReceiver.remove(this);
try {
synchronized (listeners) {
for (Integer key : listeners.keySet()) {
IBackgroundService listener = listeners.get(key);
if (listener != null) {
listener.stop();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
stopSelf();
result.success(true);
return;
}

,我可以通过应用stopService方法代码来解决它。

@Override
public void onTaskRemoved(Intent rootIntent) {
isManuallyStopped = true;
WatchdogReceiver.remove(this);
try {
synchronized (listeners) {
for (Integer key : listeners.keySet()) {
IBackgroundService listener = listeners.get(key);
if (listener != null) {
listener.stop();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
stopSelf();
}

我不确定这是正确的解决方案。但我希望这个解决方案能帮助你解决问题。

我提交了一个问题,所以记住这一点。https://github.com/ekasetiawans/flutter_background_service/issues/300

实际服务是前台服务,即使应用程序关闭也会运行。

前台服务显示状态栏通知,以便用户主动意识到您的应用程序正在前台执行任务并且正在消耗系统资源。该通知不能被驳回,除非服务被停止或从前台移除。

这我已经和它的工作原理

await service.configure(
androidConfiguration: AndroidConfiguration(

onStart: onStart,
autoStart: true,
isForegroundMode: false,
notificationChannelId: 'my_foreground',
initialNotificationTitle: 'my service',
initialNotificationContent: 'the service is started',
foregroundServiceNotificationId: 888,
autoStartOnBoot: true
),
iosConfiguration: IosConfiguration(
autoStart: true,
onForeground: onStart,
onBackground: onIosBackground,
),
);

最新更新