audio_recorder icon indicating copy to clipboard operation
audio_recorder copied to clipboard

`RuntimeException` on stop

Open ghost opened this issue 6 years ago • 3 comments

If you quickly start and stop a recording, a RuntimeException is thrown from Java, resulting in a PlatformException in Flutter:

D/AudioRecorder(12194): Start
D/AudioRecorder(12194): /data/user/0/dev.hugopassos.buster/cache/af313050-56be-4ec8-b821-2cad871a9cc7.m4a
D/AudioRecorder(12194): Stop
E/MediaRecorder(12194): stop failed: -1007
E/MethodChannel#audio_recorder(12194): Failed to handle method call
E/MethodChannel#audio_recorder(12194): java.lang.RuntimeException: stop failed.
E/MethodChannel#audio_recorder(12194): 	at android.media.MediaRecorder.stop(Native Method)
E/MethodChannel#audio_recorder(12194): 	at com.jordanalcaraz.audiorecorder.audiorecorder.AudioRecorderPlugin.stopNormalRecording(AudioRecorderPlugin.java:134)
E/MethodChannel#audio_recorder(12194): 	at com.jordanalcaraz.audiorecorder.audiorecorder.AudioRecorderPlugin.stopRecording(AudioRecorderPlugin.java:128)
E/MethodChannel#audio_recorder(12194): 	at com.jordanalcaraz.audiorecorder.audiorecorder.AudioRecorderPlugin.onMethodCall(AudioRecorderPlugin.java:66)
E/MethodChannel#audio_recorder(12194): 	at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:222)
E/MethodChannel#audio_recorder(12194): 	at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:96)
E/MethodChannel#audio_recorder(12194): 	at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:643)
E/MethodChannel#audio_recorder(12194): 	at android.os.MessageQueue.nativePollOnce(Native Method)
E/MethodChannel#audio_recorder(12194): 	at android.os.MessageQueue.next(MessageQueue.java:325)
E/MethodChannel#audio_recorder(12194): 	at android.os.Looper.loop(Looper.java:142)
E/MethodChannel#audio_recorder(12194): 	at android.app.ActivityThread.main(ActivityThread.java:6494)
E/MethodChannel#audio_recorder(12194): 	at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#audio_recorder(12194): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
E/MethodChannel#audio_recorder(12194): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
E/flutter (12194): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: PlatformException(error, stop failed., null)
E/flutter (12194): #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:564:7)
E/flutter (12194): #1      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:316:33)
E/flutter (12194): <asynchronous suspension>
E/flutter (12194): #2      AudioRecorder.stop (package:audio_recorder/audio_recorder.dart:49:33)
E/flutter (12194): <asynchronous suspension>
E/flutter (12194): #3      new Future.delayed.<anonymous closure> (dart:async/future.dart:316:39)
E/flutter (12194): #4      _rootRun (dart:async/zone.dart:1120:38)
E/flutter (12194): #5      _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter (12194): #6      _CustomZone.runGuarded (dart:async/zone.dart:923:7)
E/flutter (12194): #7      _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:963:23)
E/flutter (12194): #8      _rootRun (dart:async/zone.dart:1124:13)
E/flutter (12194): #9      _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter (12194): #10     _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:947:23)
E/flutter (12194): #11     Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:21:15)
E/flutter (12194): #12     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:382:19)
E/flutter (12194): #13     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:416:5)
E/flutter (12194): #14     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:172:12)

You should be able to reproduce this issue with the following snippet:

import 'package:audio_recorder/audio_recorder.dart';
import 'package:flutter/material.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:uuid/uuid.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Foo(),
    );
  }
}

class Foo extends StatelessWidget {
  static final _uuid = Uuid();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: RaisedButton(
          child: Text('Quickly start and stop recording'),
          onPressed: quicklyStartAndStopRecording,
        ),
      ),
    );
  }

  Future<void> quicklyStartAndStopRecording() async {
    await PermissionHandler().requestPermissions([PermissionGroup.microphone]);

    final directory = await getTemporaryDirectory();
    final path = join(directory.path, '${_uuid.v4()}.m4a');

    await AudioRecorder.start(
      path: path,
      audioOutputFormat: AudioOutputFormat.AAC,
    );

    await Future.delayed(
      const Duration(milliseconds: 100),
      AudioRecorder.stop,
    );
  }
}

Pubspec dependencies:

dependencies:
  flutter:
    sdk: flutter

  path_provider: ^1.3.0
  path: ^1.6.2
  uuid: ^2.0.2
  permission_handler: ^3.2.2
  audio_recorder: ^1.0.1

@ZaraclaJ

ghost avatar Sep 06 '19 18:09 ghost

To make matters worse, you cannot stop the recording after is error was thrown. Also, await AudioRecorder.isRecording stays returning true.

If you try to call AudioRecorder.stop() again:

D/AudioRecorder(13610): Stop
E/MediaRecorder(13610): stop called in an invalid state: 0
E/MethodChannel#audio_recorder(13610): Failed to handle method call
E/MethodChannel#audio_recorder(13610): java.lang.IllegalStateException
E/MethodChannel#audio_recorder(13610): 	at android.media.MediaRecorder.stop(Native Method)
E/MethodChannel#audio_recorder(13610): 	at com.jordanalcaraz.audiorecorder.audiorecorder.AudioRecorderPlugin.stopNormalRecording(AudioRecorderPlugin.java:134)
E/MethodChannel#audio_recorder(13610): 	at com.jordanalcaraz.audiorecorder.audiorecorder.AudioRecorderPlugin.stopRecording(AudioRecorderPlugin.java:128)
E/MethodChannel#audio_recorder(13610): 	at com.jordanalcaraz.audiorecorder.audiorecorder.AudioRecorderPlugin.onMethodCall(AudioRecorderPlugin.java:66)
E/MethodChannel#audio_recorder(13610): 	at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:222)
E/MethodChannel#audio_recorder(13610): 	at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:96)
E/MethodChannel#audio_recorder(13610): 	at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:643)
E/MethodChannel#audio_recorder(13610): 	at android.os.MessageQueue.nativePollOnce(Native Method)
E/MethodChannel#audio_recorder(13610): 	at android.os.MessageQueue.next(MessageQueue.java:325)
E/MethodChannel#audio_recorder(13610): 	at android.os.Looper.loop(Looper.java:142)
E/MethodChannel#audio_recorder(13610): 	at android.app.ActivityThread.main(ActivityThread.java:6494)
E/MethodChannel#audio_recorder(13610): 	at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#audio_recorder(13610): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
E/MethodChannel#audio_recorder(13610): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
E/flutter (13610): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: PlatformException(error, null, null)
E/flutter (13610): #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:564:7)
E/flutter (13610): #1      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:316:33)
E/flutter (13610): <asynchronous suspension>
E/flutter (13610): #2      AudioRecorder.stop (package:audio_recorder/audio_recorder.dart:49:33)
E/flutter (13610): <asynchronous suspension>
E/flutter (13610): #3      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:635:14)
E/flutter (13610): #4      _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:711:32)
E/flutter (13610): #5      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
E/flutter (13610): #6      TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:365:11)
E/flutter (13610): #7      TapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:275:7)
E/flutter (13610): #8      PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:455:9)
E/flutter (13610): #9      PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:75:13)
E/flutter (13610): #10     PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:102:11)
E/flutter (13610): #11     _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:218:19)
E/flutter (13610): #12     _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:198:22)
E/flutter (13610): #13     _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:156:7)
E/flutter (13610): #14     _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:102:7)
E/flutter (13610): #15     _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:86:7)
E/flutter (13610): #16     _rootRunUnary (dart:async/zone.dart:1136:13)
E/flutter (13610): #17     _CustomZone.runUnary (dart:async/zone.dart:1029:19)
E/flutter (13610): #18     _CustomZone.runUnaryGuarded (dart:async/zone.dart:931:7)
E/flutter (13610): #19     _invoke1 (dart:ui/hooks.dart:250:10)
E/flutter (13610): #20     _dispatchPointerDataPacket (dart:ui/hooks.dart:159:5)

ghost avatar Sep 06 '19 19:09 ghost

it seems it is a bug. here facing with the same issue!

sayhicoelho avatar Nov 22 '19 18:11 sayhicoelho

may cause by stop() is called immediately after start()... i tried `` try { mRecorder.stop(); mRecorder.reset(); mRecorder.release(); mRecorder = null; }catch (RuntimeException e){

}` ``
Is there a better way?

huangruiLearn avatar Dec 24 '19 09:12 huangruiLearn