import time import threading from jnius import autoclass from plyer.facades.audio import Audio # Recorder Classes MediaRecorder = autoclass('android.media.MediaRecorder') AudioSource = autoclass('android.media.MediaRecorder$AudioSource') OutputFormat = autoclass('android.media.MediaRecorder$OutputFormat') AudioEncoder = autoclass('android.media.MediaRecorder$AudioEncoder') # Player Classes MediaPlayer = autoclass('android.media.MediaPlayer') class AndroidAudio(Audio): '''Audio for android. For recording audio we use MediaRecorder Android class. For playing audio we use MediaPlayer Android class. ''' def __init__(self, file_path=None): default_path = None super().__init__(file_path or default_path) self._recorder = None self._player = None self._check_thread = None self._finished_callback = None self._format = "opus" def _check_playback(self): while self._player and self._player.isPlaying(): time.sleep(0.25) if self._finished_callback and callable(self._finished_callback): self._check_thread = None self._finished_callback(self) def _start(self): self._recorder = MediaRecorder() # AAC Format, decent quality if self._format == "aac": self._recorder.setAudioSource(AudioSource.DEFAULT) self._recorder.setAudioSamplingRate(48000) self._recorder.setAudioEncodingBitRate(128000) self._recorder.setAudioChannels(1) self._recorder.setOutputFormat(OutputFormat.MPEG_4) self._recorder.setAudioEncoder(AudioEncoder.AAC) else: # OPUS self._recorder.setAudioSource(AudioSource.DEFAULT) self._recorder.setAudioSamplingRate(48000) self._recorder.setAudioEncodingBitRate(128000) self._recorder.setAudioChannels(1) self._recorder.setOutputFormat(OutputFormat.OGG) self._recorder.setAudioEncoder(AudioEncoder.OPUS) self._recorder.setOutputFile(self.file_path) self._recorder.prepare() self._recorder.start() def _stop(self): if self._recorder: self._recorder.stop() self._recorder.release() self._recorder = None if self._player: self._player.stop() self._player.release() self._player = None def _play(self): self._player = MediaPlayer() self._player.setDataSource(self.file_path) self._player.prepare() self._player.start() self._check_thread = threading.Thread(target=self._check_playback, daemon=True) self._check_thread.start() def instance(): return AndroidAudio()