diff --git a/android/src/main/java/com/code/aaron/micstream/MicStreamPlugin.java b/android/src/main/java/com/code/aaron/micstream/MicStreamPlugin.java index 07be9b8..30040a2 100644 --- a/android/src/main/java/com/code/aaron/micstream/MicStreamPlugin.java +++ b/android/src/main/java/com/code/aaron/micstream/MicStreamPlugin.java @@ -3,7 +3,6 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; -import java.util.Arrays; import android.annotation.SuppressLint; import android.media.AudioFormat; @@ -21,38 +20,30 @@ import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; -import io.flutter.plugin.common.PluginRegistry.Registrar; - -/** MicStreamPlugin - * In reference to flutters official sensors plugin - * and the example of the streams_channel (v0.2.2) plugin - */ public class MicStreamPlugin implements FlutterPlugin, EventChannel.StreamHandler, MethodCallHandler { private static final String MICROPHONE_CHANNEL_NAME = "aaron.code.com/mic_stream"; private static final String MICROPHONE_METHOD_CHANNEL_NAME = "aaron.code.com/mic_stream_method_channel"; - /// New way of registering plugin + private EventChannel eventChannel; + private MethodChannel methodChannel; + @Override - public void onAttachedToEngine(FlutterPluginBinding binding) { + public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { registerWith(binding.getBinaryMessenger()); } - /// Cleanup after connection loss to flutter @Override public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { onCancel(null); - } - - /// Deprecated way of registering plugin - public void registerWith(Registrar registrar) { - registerWith(registrar.messenger()); + eventChannel.setStreamHandler(null); + methodChannel.setMethodCallHandler(null); } private void registerWith(BinaryMessenger messenger) { - final EventChannel microphone = new EventChannel(messenger, MICROPHONE_CHANNEL_NAME); - microphone.setStreamHandler(this); - MethodChannel methodChannel = new MethodChannel(messenger, MICROPHONE_METHOD_CHANNEL_NAME); + eventChannel = new EventChannel(messenger, MICROPHONE_CHANNEL_NAME); + eventChannel.setStreamHandler(this); + methodChannel = new MethodChannel(messenger, MICROPHONE_METHOD_CHANNEL_NAME); methodChannel.setMethodCallHandler(this); } @@ -73,12 +64,11 @@ private void registerWith(BinaryMessenger messenger) { private volatile boolean record = false; private volatile boolean isRecording = false; - // Method channel handlers to get sample rate / bit-depth @Override public void onMethodCall(MethodCall call, @NonNull Result result) { switch (call.method) { case "getSampleRate": - result.success((double) this.actualSampleRate); // cast to double just for compatibility with the iOS version + result.success((double) this.actualSampleRate); break; case "getBitDepth": result.success(this.actualBitDepth); @@ -94,13 +84,11 @@ public void onMethodCall(MethodCall call, @NonNull Result result) { @SuppressLint("MissingPermission") private void initRecorder() { - // Try to initialize and start the recorder recorder = new AudioRecord(AUDIO_SOURCE, SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT, BUFFER_SIZE); if (recorder.getState() != AudioRecord.STATE_INITIALIZED) { eventSink.error("-1", "PlatformError", null); return; } - recorder.startRecording(); } @@ -126,113 +114,90 @@ public void run() { break; } - // Wait until recorder is initialised while (recorder == null || recorder.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING); - // Allocate a new buffer to write data to ByteBuffer data = ByteBuffer.allocateDirect(BUFFER_SIZE); - - // Set ByteOrder to native ByteOrder nativeOrder = ByteOrder.nativeOrder(); data.order(nativeOrder); System.out.println("mic_stream: Using native byte order " + nativeOrder); - // Repeatedly push audio samples to stream while (record) { - // Read audio data into buffer recorder.read(data, BUFFER_SIZE, AudioRecord.READ_BLOCKING); - - // push data into stream try { eventSink.success(data.array()); } catch (IllegalArgumentException e) { System.out.println("mic_stream: " + data + " is not valid!"); eventSink.error("-1", "Invalid Data", e); } + data.clear(); } isRecording = false; } }; - /// Bug fix by https://github.com/Lokhozt - /// following https://github.com/flutter/flutter/issues/34993 private static class MainThreadEventSink implements EventChannel.EventSink { private final EventChannel.EventSink eventSink; private final Handler handler; MainThreadEventSink(EventChannel.EventSink eventSink) { - this.eventSink = eventSink; - handler = new Handler(Looper.getMainLooper()); + this.eventSink = eventSink; + handler = new Handler(Looper.getMainLooper()); } @Override public void success(final Object o) { - handler.post(new Runnable() { - @Override - public void run() { - eventSink.success(o); - } - }); + handler.post(() -> eventSink.success(o)); } @Override public void error(final String s, final String s1, final Object o) { - handler.post(new Runnable() { - @Override - public void run() { - eventSink.error(s, s1, o); - } - }); + handler.post(() -> eventSink.error(s, s1, o)); } @Override public void endOfStream() { - handler.post(new Runnable() { - @Override - public void run() { - eventSink.endOfStream(); - } - }); + handler.post(() -> eventSink.endOfStream()); } } - /// End @Override public void onListen(Object args, final EventChannel.EventSink eventSink) { if (isRecording) return; - // Read and validate AudioRecord parameters + if (!(args instanceof ArrayList)) { + eventSink.error("-4", "Invalid parameter type. Expected ArrayList.", null); + return; + } + + @SuppressWarnings("unchecked") ArrayList config = (ArrayList) args; + try { AUDIO_SOURCE = config.get(0); SAMPLE_RATE = config.get(1); CHANNEL_CONFIG = config.get(2); AUDIO_FORMAT = config.get(3); BUFFER_SIZE = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT); - } catch (java.lang.IndexOutOfBoundsException e) { - eventSink.error("-4", "Invalid number of parameteres. Expected 4, got " + config.size(), e); + } catch (IndexOutOfBoundsException e) { + eventSink.error("-4", "Invalid number of parameters. Expected 4, got " + config.size(), e); } catch (Exception e) { eventSink.error("-3", "Invalid AudioRecord parameters", e); } this.eventSink = new MainThreadEventSink(eventSink); - // Start runnable record = true; new Thread(runnable).start(); } @Override public void onCancel(Object o) { - // Stop runnable record = false; while (isRecording); - if(recorder != null) { - // Stop and reset audio recorder + if (recorder != null) { recorder.stop(); recorder.release(); } recorder = null; } -} - +} \ No newline at end of file