diff --git a/app.config.ts b/app.config.ts index eefcd2a..5b5558a 100644 --- a/app.config.ts +++ b/app.config.ts @@ -60,6 +60,13 @@ export default ({config}: ConfigContext): ExpoConfig => ({ ], }, ], + [ + 'expo-av', + { + microphonePermission: + '$(PRODUCT_NAME)은(는) 음성 녹음 및 오디오 입력 기능을 제공하기 위해 마이크 접근 권한이 필요합니다. 이러한 기능을 계속 사용하려면 마이크 접근을 허용해 주세요.', + }, + ], ], experiments: { typedRoutes: true, diff --git a/app/audio.tsx b/app/audio.tsx new file mode 100644 index 0000000..1e64f89 --- /dev/null +++ b/app/audio.tsx @@ -0,0 +1,108 @@ +import {useEffect, useState} from 'react'; +import {SafeAreaView, View} from 'react-native'; +import {css} from '@emotion/native'; +import {IconButton, Typography} from 'dooboo-ui'; +import {Audio} from 'expo-av'; + +export default function AudioPage(): JSX.Element { + const [permissionResponse, requestPermission] = Audio.usePermissions(); + const [recording, setRecording] = useState(); + const [uri, setUri] = useState(); + const [sound, setSound] = useState(); + const [isPlaying, setIsPlaying] = useState(false); + + const _playBack: Audio.Sound['_onPlaybackStatusUpdate'] = (status) => { + if (status.isLoaded) { + if (status.didJustFinish) { + setIsPlaying(false); + } + } + }; + + useEffect(() => { + return sound + ? () => { + sound.unloadAsync(); + } + : undefined; + }, [sound]); + + const startRecording = async (): Promise => { + try { + if (permissionResponse?.status !== 'granted') { + console.log('Requesting permission..'); + await requestPermission(); + } + + await Audio.setAudioModeAsync({ + allowsRecordingIOS: true, + playsInSilentModeIOS: true, + }); + + console.log('Starting recording..'); + + const {recording: recorded} = await Audio.Recording.createAsync( + Audio.RecordingOptionsPresets.HIGH_QUALITY, + ); + setRecording(recorded); + console.log('Recording started'); + } catch (err) { + console.error('Failed to start recording', err); + } + }; + + const stopRecording = async (): Promise => { + console.log('Stopping recoasync async recording..'); + setRecording(undefined); + await recording?.stopAndUnloadAsync(); + await Audio.setAudioModeAsync({allowsRecordingIOS: false}); + + const recordingUri = recording?.getURI(); + recordingUri && setUri(recordingUri); + }; + + const playSound = async (): Promise => { + if (uri) { + setIsPlaying(true); + + const {sound: audioSound} = await Audio.Sound.createAsync( + {uri}, + {}, + _playBack, + ); + setSound(audioSound); + + console.log('Playing Sound'); + await audioSound.playAsync(); + } + }; + + return ( + + Record + + Play + + + + ); +} diff --git a/app/index.tsx b/app/index.tsx index a9762b1..8bdb037 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -94,7 +94,6 @@ export default function Index(): JSX.Element { onPress={() => push('/details')} style={css` margin-top: 28px; - margin-bottom: 40px; `} styles={{ text: css` @@ -103,6 +102,19 @@ export default function Index(): JSX.Element { }} text={t('SEE_DETAILS')} /> +