Closed anandStratBeans closed 3 months ago
I got this error when trying both version 6.3.0 and 6.4.0. Is it related to this package's error?
FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to create service com.pravera.flutter_foreground_task.service.ForegroundService: java.lang.SecurityException: Starting FGS with type microphone callerApp=ProcessRecord{64b48c9 18748:/u0a185} targetSDK=34 requires permissions: all of the permissions allOf=true [android.permission.FOREGROUND_SERVICE_MICROPHONE] any of the permissions allOf=false [android.permission.CAPTURE_AUDIO_HOTWORD, android.permission.CAPTURE_AUDIO_OUTPUT, android.permission.CAPTURE_MEDIA_OUTPUT, android.permission.CAPTURE_TUNER_AUDIO_INPUT, android.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT, android.permission.RECORD_AUDIO] and the app must be in the eligible state/exemptions to access the foreground only permission
at android.app.ActivityThread.handleCreateService(ActivityThread.java:4663)
at android.app.ActivityThread.-$$Nest$mhandleCreateService(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2264)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8176)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Caused by: java.lang.SecurityException: Starting FGS with type microphone callerApp=ProcessRecord{64b48c9 18748:/u0a185} targetSDK=34 requires permissions: all of the permissions allOf=true [android.permission.FOREGROUND_SERVICE_MICROPHONE] any of the permissions allOf=false [android.permission.CAPTURE_AUDIO_HOTWORD, android.permission.CAPTURE_AUDIO_OUTPUT, android.permission.CAPTURE_MEDIA_OUTPUT, android.permission.CAPTURE_TUNER_AUDIO_INPUT, android.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT, android.permission.RECORD_AUDIO] and the app must be in the eligible state/exemptions to access the foreground only permission
at android.os.Parcel.createExceptionOrNull(Parcel.java:3057)
at android.os.Parcel.createException(Parcel.java:3041)
at android.os.Parcel.readException(Parcel.java:3024)
at android.os.Parcel.readException(Parcel.java:2966)
at android.app.IActivityManager$Stub$Proxy.setServiceForeground(IActivityManager.java:6745)
at android.app.Service.startForeground(Service.java:862)
at com.pravera.flutter_foreground_task.service.ForegroundService.startForegroundService(ForegroundService.kt:252)
at com.pravera.flutter_foreground_task.service.ForegroundService.onCreate(ForegroundService.kt:85)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:4650)
at android.app.ActivityThread.-$$Nest$mhandleCreateService(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2264)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8176)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Caused by: android.os.RemoteException: Remote stack trace:
at com.android.server.am.ActiveServices.validateForegroundServiceType(ActiveServices.java:2718)
at com.android.server.am.ActiveServices.setServiceForegroundInnerLocked(ActiveServices.java:2418)
at com.android.server.am.ActiveServices.setServiceForegroundLocked(ActiveServices.java:1666)
at com.android.server.am.ActivityManagerService.setServiceForeground(ActivityManagerService.java:13253)
at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:3378)
In AndroidManifest.xml
:
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
<service
android:name="com.pravera.flutter_foreground_task.service.ForegroundService"
android:stopWithTask="true"
android:foregroundServiceType="microphone"
android:exported="false" />
Check runtime prerequisites. https://developer.android.com/about/versions/14/changes/fgs-types-required#microphone
You must grant RECORD_AUDIO permission before starting the service.
@Dev-hwang My issue is with the MEDIA_PROJECTION service. How exactly do I grant it before the service starts? It's already specified in the manifest.
Plugin version - 6.4.0
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
<service
android:name="com.pravera.flutter_foreground_task.service.ForegroundService"
android:foregroundServiceType="mediaPlayback|camera|microphone|mediaProjection"
android:stopWithTask="true"/>
Error -
java.lang.RuntimeException: Unable to create service com.pravera.flutter_foreground_task.service.ForegroundService: java.lang.SecurityException: Starting FGS with type mediaProjection callerApp=ProcessRecord{91d52c4 15903:com.example.test/u0a206} targetSDK=34 requires permissions: all of the permissions allOf=true [android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION] any of the permissions allOf=false [android.permission.CAPTURE_VIDEO_OUTPUT, android:project_media]
I am also experience issues on Android regarding the FOREGROUND_SERVICE_MICROPHONE, I downgraded to 6.3 to specify the foregroundServiceTypes. The ForgroundService starts as expected but when I try to start my audio recording with the record dependency I get an error from the record that I lack the permission. As @bhavinb98 and @tatuan19 are using the FOREGROUND_SERVICE_MICROPHONE I wonder how you manage to record audio in the FS.
@knma1992 Hmm not sure. My app asks for the access microphone permission during startup, after that there's no other configuration. My foreground service code is pretty much similar to the one in the readme.
@bhavinb98 Mine as well, recording works but not in the FS for some reason, is your app on github?
@knma1992 Yes, but can't share it since it's a company's app.
Let me just post my code here, maybe I am doing something obviously wrong.
`
void initForegroundTask() {
FlutterForegroundTask.init(
androidNotificationOptions: AndroidNotificationOptions(
foregroundServiceTypes: [AndroidForegroundServiceType.MICROPHONE],
channelId: 'foreground_service',
channelName: 'Foreground Service Notification',
channelDescription: 'This notification appears when the foreground service is running.',
channelImportance: NotificationChannelImportance.LOW,
priority: NotificationPriority.LOW,
iconData: const NotificationIconData(
resType: ResourceType.mipmap,
resPrefix: ResourcePrefix.ic,
name: 'launcher',
),
buttons: [
const NotificationButton(id: 'sendButton', text: 'Send'),
const NotificationButton(id: 'testButton', text: 'Test'),
],
),
iosNotificationOptions: const IOSNotificationOptions(
showNotification: true,
playSound: false,
),
foregroundTaskOptions: const ForegroundTaskOptions(
interval: 1000,
isOnceEvent: false,
autoRunOnBoot: true,
allowWakeLock: true,
allowWifiLock: true,
),
);
}
@override
void initState() {
initForegroundTask();
}
// The callback function should always be a top-level function.
@pragma('vm:entry-point')
void startCallback() {
// The setTaskHandler function must be called to handle the task in the background.
FlutterForegroundTask.setTaskHandler(FirstTaskHandler());
}
enum TaskState { none, running, paused }
class FirstTaskHandler extends TaskHandler {
SendPort? _sendPort;
TaskState _taskState = TaskState.none;
void _startController() async {
final record = AudioRecorder();
final inputDevices = await record.listInputDevices();
final inputDevice = inputDevices[1];
logger.i(inputDevice);
if (await record.hasPermission()) {
logger.i("Permission granted");
} else {
logger.e("Permission denied"); //<-This is where it throws permission denied even though it works perfectly fine outside the FS
return;
}
final recordConfig = RecordConfig(
encoder: AudioEncoder.pcm16bits,
sampleRate: 16000,
numChannels: 1,
device: inputDevice); //bitRate: 128000
final stream = await record.startStream(recordConfig);
stream.listen(
(data) async {
print(data);
},
onError: (error) {
logger.e("onError error = ${error.toString()}");
},
onDone: () {
logger.i("onDone");
},
);
}
@override
void onStart(DateTime timestamp, SendPort? sendPort) async {
print("onStart");
_taskState = TaskState.running;
_sendPort = sendPort;
final customData = await FlutterForegroundTask.getData<String>(key: 'customData');
print('customData: $customData');
_startController();
}
@override
void onRepeatEvent(DateTime timestamp, SendPort? sendPort) async {
print("onRepeatEvent");
// Send data to the main isolate.
sendPort?.send("timestamp: ${timestamp.toString()}");
}
@override
void onDestroy(DateTime timestamp, SendPort? sendPort) async {
print("onDestroy");
}
@override
void onNotificationButtonPressed(String id) {
print('onNotificationButtonPressed >> $id');
}
@override
void onNotificationPressed() {
FlutterForegroundTask.launchApp("/resume-route");
_sendPort?.send('onNotificationPressed');
}
}
`
@knma1992 Have you tried asking for the record permission outside of the task handler function? or is it the first time it asks for it?
Currently, I grant permission on a separate screen using the permission handler and I only access the screen from which I start my FS when I have granted all my permissions. What is weird is the fact that if I check permission in my task handler with the permission handler it is granted.
final microphonePermission = await Permission.microphone.isGranted;
But record for some reason does not.
Hmm that is weird. I don't know any more :(
Looking into the ForegroundService was a mistake, I should have debugged the record plugin way earlier. When the record plugin checks for permission and when it sinks the audio buffer into the EventChannel it does so via an activity variable that won't be set when the record plugin is started from the second dart entry point. I forked the record plugin and changed it accordingly.
This is the old implementation.
fun sendRecordChunkEvent(buffer: ByteArray) { activity?.runOnUiThread { eventSink?.success(buffer) } }
My implementation:
fun sendRecordChunkEvent(buffer: ByteArray) { uiThreadHandler.post(Runnable { eventSink?.success(buffer) }) }
Currently, I don't change the permission check implementation inside record as I can check for permissions using the permission_handler plugin and I have no idea how to supply the context to the record plugin. Thanks @bhavinb98 for the help.
The foreground service type is missing in the new version 6.4.0. Due to this the Android app crashes continuously. FATAL EXCEPTION: main Process: com.stratbeans.bytecastingevolve, PID: 13153 java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=333, result=-1, data=Intent { (has extras) }} to activity {com.stratbeans.bytecastingevolve/com.stratbeans.bytecastingevolve.MainActivity}: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION at android.app.ActivityThread.deliverResults(ActivityThread.java:5527) at android.app.ActivityThread.handleSendResult(ActivityThread.java:5566) at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:67) at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:205) at android.os.Looper.loop(Looper.java:294) at android.app.ActivityThread.main(ActivityThread.java:8177) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971) Caused by: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION at android.os.Parcel.createExceptionOrNull(Parcel.java:3057) at android.os.Parcel.createException(Parcel.java:3041) at android.os.Parcel.readException(Parcel.java:3024) at android.os.Parcel.readException(Parcel.java:2966) at android.media.projection.IMediaProjection$Stub$Proxy.start(IMediaProjection.java:313) at android.media.projection.MediaProjection.(MediaProjection.java:84)
at android.media.projection.MediaProjection.(MediaProjection.java:75)
at android.media.projection.MediaProjectionManager.getMediaProjection(MediaProjectionManager.java:236)
at com.isvisoft.flutter_screen_recording.FlutterScreenRecordingPlugin.onActivityResult(FlutterScreenRecordingPlugin.kt:53)
at io.flutter.embedding.engine.FlutterEngineConnectionRegistry$FlutterEngineActivityPluginBinding.onActivityResult(FlutterEngineConnectionRegistry.java:774)
at io.flutter.embedding.engine.FlutterEngineConnectionRegistry.onActivityResult(FlutterEngineConnectionRegistry.java:422)
at io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.onActivityResult(FlutterActivityAndFragmentDelegate.java:857)
at io.flutter.embedding.android.FlutterActivity.onActivityResult(FlutterActivity.java:884)
at android.app.Activity.dispatchActivityResult(Activity.java:8943)
at android.app.ActivityThread.deliverResults(ActivityThread.java:5520)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:5566)
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:67)
at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8177)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Caused by: android.os.RemoteException: Remote stack trace:
at com.android.server.media.projection.MediaProjectionManagerService$MediaProjection.start(MediaProjectionManagerService.java:940)
at android.media.projection.IMediaProjection$Stub.onTransact(IMediaProjection.java:192)
at android.os.Binder.execTransactInternal(Binder.java:1339)
at android.os.Binder.execTransact(Binder.java:1275)