question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

`startRecorder` doesn't seem to access Android native code

See original GitHub issue

Version of flutter_sound

1.4.2 up to 2.0.0. Haven’t tested in previous versions.

flutter doctor

[v] Flutter (Channel stable, v1.12.13+hotfix.5, on Microsoft Windows [Version 10.0.16299.15], locale en-US) [v] Android toolchain - develop for Android devices (Android SDK version 29.0.0) [v] Android Studio (version 3.4) [v] VS Code, 64-bit edition (version 1.35.0) [v] Connected device (1 available)

Platforms you faced the error (IOS or Android or both?)

Android. Haven’t thoroughly tested in iOS, however it doesn’t record as well.

Expected behavior

Upon call of FlutterSound#startRecorder, future should resolve and FlutterSound.onRecorderStateChanged stream should be active.

Actual behavior

FlutterSound#startRecorder future doesnt resolve and will await forever because it gets stuck at _channel.invokeMethod('startRecorder'...); https://github.com/dooboolab/flutter_sound/blob/f0054692f83e5d3ab520ebe07ab4924b2bcaa1e5/lib/flutter_sound.dart#L170

Tested environment (Emulator? Real Device?)

  • Emulators with Android SDK 28 and 29
  • Samsung Galaxy S6 Edge (Android version 7.0)

Steps to reproduce the behavior

  1. Create a new flutter project
  2. Add flutter_sound: 2.0.0 in pubspec.yaml
  3. Add code in main.dart such that it calls startRecorder (see code below)
  4. Press button that calls startRecorder to start recording

main.dart:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_sound/android_encoder.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:intl/intl.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _isRecording = false;
  List<String> _path = [null, null, null, null, null, null, null];
  StreamSubscription _recorderSubscription;
  StreamSubscription _dbPeakSubscription;
  StreamSubscription _playerSubscription;
  FlutterSound flutterSound;

  String _recorderTxt = '00:00:00';
  double _dbLevel;

  @override
  void initState() {
    super.initState();
    flutterSound = FlutterSound();
    flutterSound.setSubscriptionDuration(0.01);
    flutterSound.setDbPeakLevelUpdate(0.8);
    flutterSound.setDbLevelEnabled(true);
  }

  static const List<String> paths = [
    'sound.aac', // DEFAULT
    'sound.aac', // CODEC_AAC
    'sound.opus', // CODEC_OPUS
    'sound.caf', // CODEC_CAF_OPUS
    'sound.mp3', // CODEC_MP3
    'sound.ogg', // CODEC_VORBIS
    'sound.wav', // CODEC_PCM
  ];
  t_CODEC _codec = t_CODEC.CODEC_AAC;

  void startRecorder() async {
    print('start recorder');
    try {
      String path = await flutterSound.startRecorder(
        paths[_codec.index],
        codec: _codec,
        sampleRate: 16000,
        bitRate: 16000,
        numChannels: 1,
        androidAudioSource: AndroidAudioSource.MIC,
      );
      print('startRecorder: $path');

      _recorderSubscription = flutterSound.onRecorderStateChanged.listen((e) {
        DateTime date = new DateTime.fromMillisecondsSinceEpoch(
            e.currentPosition.toInt(),
            isUtc: true);
        String txt = DateFormat('mm:ss:SS', 'en_GB').format(date);

        this.setState(() {
          this._recorderTxt = txt.substring(0, 8);
        });
      });
      _dbPeakSubscription =
          flutterSound.onRecorderDbPeakChanged.listen((value) {
        print("got update -> $value");
        setState(() {
          this._dbLevel = value;
        });
      });

      this.setState(() {
        this._isRecording = true;
        this._path[_codec.index] = path;
      });
    } catch (err) {
      print('startRecorder error: $err');
      setState(() {
        this._isRecording = false;
      });
    }
  }

  void stopRecorder() async {
    print('stop recorder');
    try {
      String result = await flutterSound.stopRecorder();
      print('stopRecorder: $result');

      if (_recorderSubscription != null) {
        _recorderSubscription.cancel();
        _recorderSubscription = null;
      }
      if (_dbPeakSubscription != null) {
        _dbPeakSubscription.cancel();
        _dbPeakSubscription = null;
      }
    } catch (err) {
      print('stopRecorder error: $err');
    }
    this.setState(() {
      this._isRecording = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          children: <Widget>[
            FlatButton(
              child: Text(_isRecording.toString()),
              onPressed: _isRecording ? stopRecorder : startRecorder,
            ),
            Text(_recorderTxt)
          ],
        ),
      ),
    );
  }
}

Thank you!

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:12

github_iconTop GitHub Comments

3reactions
Boehrsicommented, Jan 16, 2020

Just checked the example project and it works. But as soon as I replace

String path = await flutterSound.startRecorder
      (
        paths[_codec.index],
        codec: _codec,
        sampleRate: 16000,
        bitRate: 16000,
        numChannels: 1,
        androidAudioSource: AndroidAudioSource.MIC,
      );

with

String path = await flutterSound.startRecorder(null);

nothing happens when pressing the recording button.It looks like some of the assumed default values aren’t valid on my device (Samsung S7 on Android 8.0.0).

2reactions
hyochancommented, Jan 17, 2020

Just checked the example project and it works. But as soon as I replace

String path = await flutterSound.startRecorder
      (
        paths[_codec.index],
        codec: _codec,
        sampleRate: 16000,
        bitRate: 16000,
        numChannels: 1,
        androidAudioSource: AndroidAudioSource.MIC,
      );

with

String path = await flutterSound.startRecorder(null);

nothing happens when pressing the recording button.It looks like some of the assumed default values aren’t valid on my device (Samsung S7 on Android 8.0.0).

Thanks for trying out~! We’ve narrowed down the problem so I’ll look up at the weekend.

Read more comments on GitHub >

github_iconTop Results From Across the Web

startRecorder doesn't seem to access Android native code #193
Upon call of FlutterSound#startRecorder , future should resolve and FlutterSound.onRecorderStateChanged stream should be active. Actual behavior.
Read more >
Known issues with Android Studio and Android Gradle Plugin
Native debugger crashes with "Debugger process finished with exit code 127" ... This error occurs on Linux-based platforms when starting the native debugger....
Read more >
Troubleshoot known issues with Android Emulator
This page lists known issues, workarounds, and troubleshooting tips for the Android Emulator. If you encounter an issue not listed here or ...
Read more >
Request app permissions - Android Developers
Send and sync data on Wear OS · Network access and sync on Wear OS · Access the ... Overview · Integrate using...
Read more >
Access media files from shared storage | Android Developers
Update in native code · val contentUri: Uri = ContentUris.withAppendedId( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, cursor.getLong(BaseColumns._ID)) val ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found