Open dharambudh1 opened 4 months ago
You are missing this permission uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION"
Thank you for the reply! I am currently utilizing <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
, while <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
is not documented anywhere. Let's test it out.
android.permission.FOREGROUND_SERVICE_LOCATION
Since Android 14, the permission is required https://developer.android.com/develop/background-work/services/foreground-services?hl=es-419#fgs-prerequisites
Currently there is a different in requesting permissions for android 11
and above there are certain times , the option for the background location settings doesnt get invoked as expected. For example, when I test on my android 14 , it immediately shows but for my andoid 12 it doesnt.
The background location permission is a bit different for android 11 and above , reference , here
So the solution that may guarantee to work is using native platform channel where you would invoke requestPermission
, reference for this , here
I currently inovke the platform channel methods on initstate of the widget screen that expected to use it
Here is the native side of code, ofc will have to be added at MainActivity.kt
package com.cloone.edo
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import android.widget.Toast
class MainActivity : FlutterActivity() {
private val CHANNEL = "android.flutter.dev/permission"
private val REQUEST_CODE_BACKGROUND_LOCATION = 1001
private var permissionResult: MethodChannel.Result? = null
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "requestBackgroundLocationPermission") {
permissionResult = result
requestBackgroundLocationPermission()
} else {
result.notImplemented()
}
}
}
private fun requestBackgroundLocationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// Check if permission is already granted
if (checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED) {
permissionResult?.success("already_granted")
} else {
// Request background location permission
requestPermissions(arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), REQUEST_CODE_BACKGROUND_LOCATION)
}
} else {
// For android 10 and below , not required
permissionResult?.success("not_required")
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
REQUEST_CODE_BACKGROUND_LOCATION -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Background Location Permission Granted", Toast.LENGTH_SHORT).show()
permissionResult?.success("granted")
} else {
Toast.makeText(this, "Background Location Permission Denied", Toast.LENGTH_SHORT).show()
permissionResult?.success("denied")
}
}
}
}
}
and on the dart side
Future<void> _getBackgroundLocationPermission() async {
String locationPermission = '';
try {
final result = await platform
.invokeMethod<String>('requestBackgroundLocationPermission');
locationPermission = 'Permission : $result % .';
} on PlatformException catch (e) {
locationPermission = "Failed to get permission: '${e.message}'.";
}
setState(() {
_locationPermission = locationPermission;
});
}
this would be the method you would invoke on the initstate
I am quite new to native, so the code quality may not be the best but it currently request permission as expected and would show a native toast . Hope this helps.
And referring to what you issued originally, it is most likely you did not handle what happens when user denies. Usually on testing u should do for denied and then check if app attempts to loop back or redirect user back, and forcing user to allow permission regardless in order to use that particular service.
MethodChannelLocation.enableBackgroundMode
Stack trace: PlatformException(error, Service.startForeground() not allowed due to mAllowStartForeground false: service com.ahinsaaggregator.vendor/com.lyokone.location.FlutterLocationService, null, android.app.ForegroundServiceStartNotAllowedException: Service.startForeground() not allowed due to mAllowStartForeground false: service com.ahinsaaggregator.vendor/com.lyokone.location.FlutterLocationService at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:54) at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:50) at android.os.Parcel.readParcelableInternal(Parcel.java:4882) at android.os.Parcel.readParcelable(Parcel.java:4864) at android.os.Parcel.createExceptionOrNull(Parcel.java:3064) at android.os.Parcel.createException(Parcel.java:3053) at android.os.Parcel.readException(Parcel.java:3036) at android.os.Parcel.readException(Parcel.java:2978) at android.app.IActivityManager$Stub$Proxy.setServiceForeground(IActivityManager.java:7234) at android.app.Service.startForeground(Service.java:775) at com.lyokone.location.FlutterLocationService.d(SourceFile:1) at bb.h.a(SourceFile:1) at bb.h.onMethodCall(SourceFile:1) at xb.j$a.a(SourceFile:1) at ob.c.l(SourceFile:1) at ob.c.m(SourceFile:1) at ob.c.i(SourceFile:1) at ob.b.run(SourceFile:1) at android.os.Handler.handleCallback(Handler.java:958) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:230) at android.os.Looper.loop(Looper.java:319) at android.app.ActivityThread.main(ActivityThread.java:8934) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:578) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103) )
Flutter version: Flutter (Channel stable, 3.19.3, on Ubuntu 24.04 LTS 6.8.0-35-generic, locale en_US.UTF-8) Plugin version: location: ^6.0.2 Device information: Samsung Galaxy A23 running Android 14