MissingPluginException при использовании flutter_sound в flutter_foreground_taskAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 MissingPluginException при использовании flutter_sound в flutter_foreground_task

Сообщение Anonymous »

Мне нужно реализовать функцию, при которой микрофон пользователя записывается с помощью FlutterSoundRecorder пакета flutter_sound и немедленно воспроизводится через динамик с помощью FlutterSoundPlayer для Android и iOS. Я уже выполнил эту часть задачи.
Запись и немедленное воспроизведение должны происходить отдельно и должны продолжаться, даже когда приложение свернуто/не в фокусе, а также когда смартфон переходит в спящий режим.
Пакет flutter_foreground_task показался очень многообещающим. Я попробовал запустить его примеры, и они сработали безупречно.
Проблемы начинаются, как только я пытаюсь переместить код flutter_sound в изолят, созданный пакетом flutter_foreground_task и запустите приложение:
MissingPluginException (MissingPluginException(No implementation found for method resetPlugin on channel xyz.canardoux.flutter_sound_player))

Я попробовал очистить флаттер, а также очистить кэш флаттера паба в сочетании с перестройкой проекта после добавления всех зависимостей. Я пробовал WidgetsFlutterBinding.ensureInitialized() и DartPluginRegistrant.ensureInitialized(), но безрезультатно.
Я знаю, что запуск кода в другом изоляте и код, который только не игнорируется в процессе сборки через @pragma('vm:entry-point'), может вызвать проблемы при выполнении собственного кода или плагинов внутри него.
Как я могу устранить это исключение ? В настоящее время я тестирую его только для Android, проблема с iOS возникнет позже.
Чтобы воспроизвести его, создайте новый пустой проект flutter и замените содержимое main.dart на следующий код, основанный на официальном примере flutter_foreground_task (по запросу я могу его сократить). Соответствующий файл AndroidManifest.xml находится под кодом. Также добавьте в pubspec.yaml проекта следующие три пакета: flutter_foreground_task, flutter_sound и Permission_handler.
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:permission_handler/permission_handler.dart';

void main() {
FlutterForegroundTask.initCommunicationPort();
runApp(const ExampleApp());
}

@pragma('vm:entry-point')
void startCallback() {
FlutterForegroundTask.setTaskHandler(MyTaskHandler());
}

class MyTaskHandler extends TaskHandler {
static const String incrementCountCommand = 'incrementCount';

int _count = 0;

FlutterSoundRecorder _recorder = FlutterSoundRecorder();
FlutterSoundPlayer _player = FlutterSoundPlayer();

final StreamController _streamController =
StreamController.broadcast();

void _incrementCount() {
_count++;

FlutterForegroundTask.updateService(
notificationTitle: 'Hello MyTaskHandler :)',
notificationText: 'count: $_count',
);

FlutterForegroundTask.sendDataToMain(_count);
}

@override
void onStart(DateTime timestamp) async {
print('onStart');
_incrementCount();
await _player.openPlayer();
await _player.setVolume(1.0);
await _recorder.openRecorder();
_streamController.stream.listen((Uint8List food) {
if (_player.isPlaying) {
_player.foodSink!.add(FoodData(food));
}
});
await _player.startPlayerFromStream(
sampleRate: 44100,
whenFinished: _streamController.close,
);
await _recorder.startRecorder(
toStream: _streamController.sink,
codec: Codec.pcm16,
sampleRate: 44100,
);
}

@override
void onRepeatEvent(DateTime timestamp) {
_incrementCount();
}

@override
void onDestroy(DateTime timestamp) async {
print('onDestroy');
await _player.stopPlayer();
await _player.closePlayer();

await _recorder.stopRecorder();
await _recorder.closeRecorder();

await _streamController.close();
}

@override
void onReceiveData(Object data) {
print('onReceiveData: $data');
if (data == incrementCountCommand) {
_incrementCount();
}
}

@override
void onNotificationButtonPressed(String id) {
print('onNotificationButtonPressed: $id');
}

@override
void onNotificationPressed() {
FlutterForegroundTask.launchApp('/');
print('onNotificationPressed');
}

@override
void onNotificationDismissed() {
print('onNotificationDismissed');
}
}

class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
'/': (context) => const ExamplePage(),
},
initialRoute: '/',
);
}
}

class ExamplePage extends StatefulWidget {
const ExamplePage({super.key});

@override
State createState() => _ExamplePageState();
}

class _ExamplePageState extends State {
final ValueNotifier _receivedTaskData = ValueNotifier(null);

Future _requestPermissions() async {
final NotificationPermission notificationPermission =
await FlutterForegroundTask.checkNotificationPermission();
if (notificationPermission != NotificationPermission.granted) {
await FlutterForegroundTask.requestNotificationPermission();
}
//microphone permission
final PermissionStatus microphonePermission =
await Permission.microphone.status;

if (Platform.isAndroid) {
if (!await FlutterForegroundTask.canDrawOverlays) {
await FlutterForegroundTask.openSystemAlertWindowSettings();
}

if (!await FlutterForegroundTask.isIgnoringBatteryOptimizations) {
await FlutterForegroundTask.requestIgnoreBatteryOptimization();
}

if (!await FlutterForegroundTask.canScheduleExactAlarms) {
await FlutterForegroundTask.openAlarmsAndRemindersSettings();
}
}
}

void _initService() {
FlutterForegroundTask.init(
androidNotificationOptions: AndroidNotificationOptions(
channelId: 'foreground_service',
channelName: 'Foreground Service Notification',
channelDescription:
'This notification appears when the foreground service is running.',
channelImportance: NotificationChannelImportance.LOW,
priority: NotificationPriority.LOW,
),
iosNotificationOptions: const IOSNotificationOptions(
showNotification: false,
playSound: false,
),
foregroundTaskOptions: ForegroundTaskOptions(
eventAction: ForegroundTaskEventAction.repeat(5000),
autoRunOnBoot: true,
autoRunOnMyPackageReplaced: true,
allowWakeLock: true,
allowWifiLock: true,
),
);
}

Future _startService() async {
if (await FlutterForegroundTask.isRunningService) {
return FlutterForegroundTask.restartService();
} else {
return FlutterForegroundTask.startService(
serviceId: 256,
notificationTitle: 'Foreground Service is running',
notificationText: 'Tap to return to the app',
notificationIcon: null,
notificationButtons: [
const NotificationButton(id: 'btn_hello', text: 'hello'),
],
callback: startCallback,
);
}
}

Future _stopService() async {
return FlutterForegroundTask.stopService();
}

void _onReceiveTaskData(Object data) {
print('onReceiveTaskData: $data');
_receivedTaskData.value = data;
}

void _incrementCount() {
FlutterForegroundTask.sendDataToTask(MyTaskHandler.incrementCountCommand);
}

@override
void initState() {
super.initState();
FlutterForegroundTask.addTaskDataCallback(_onReceiveTaskData);

WidgetsBinding.instance.addPostFrameCallback((_) {
_requestPermissions();
_initService();
});
}

@override
void dispose() {
FlutterForegroundTask.removeTaskDataCallback(_onReceiveTaskData);
_receivedTaskData.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return WithForegroundTask(
child: Scaffold(
appBar: AppBar(
title: const Text('Flutter Foreground Task'),
centerTitle: true,
),
body: _buildContentView(),
),
);
}

Widget _buildContentView() {
return Column(
children: [
Expanded(child: _buildCommunicationText()),
_buildServiceControlButtons(),
],
);
}

Widget _buildCommunicationText() {
return ValueListenableBuilder(
valueListenable: _receivedTaskData,
builder: (context, data, _) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('You received data from TaskHandler:'),
Text('$data', style: Theme.of(context).textTheme.headlineMedium),
],
),
);
},
);
}

Widget _buildServiceControlButtons() {
buttonBuilder(String text, {VoidCallback? onPressed}) {
return ElevatedButton(
onPressed: onPressed,
child: Text(text),
);
}

return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
buttonBuilder('start service', onPressed: _startService),
buttonBuilder('stop service', onPressed: _stopService),
buttonBuilder('increment count', onPressed: _incrementCount),
],
),
);
}
}




































Подробнее здесь: https://stackoverflow.com/questions/789 ... round-task
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»