MediaRecorder์™€ MediaStore

์ €์žฅ์†Œ ์•ก์„ธ์Šค ์ •์ฑ… ๋ณ€๊ฒฝ

Android 10 ์ด์ƒ์„ ํƒ€๊ฒŸํŒ…ํ•˜๋Š” ๊ธฐ๊ธฐ๋ถ€ํ„ฐ ์™ธ๋ถ€ ์ €์žฅ์†Œ ๋ฃจํŠธ๋Š” ์•„์˜ˆ ์‚ฌ์šฉํ•  ์ˆ˜๊ฐ€ ์—†๊ณ  ๋ช‡ ๊ฐ€์ง€ ํ—ˆ์šฉ๋œ ๊ณต๊ฐ„๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค. ๋˜, ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์™ธ๋ถ€ ์ €์žฅ์†Œ์— ์•ก์„ธ์Šคํ•  ๊ฒฝ์šฐ์— SAF๋‚˜ MediaStore๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๊ฐ•์ œ๋˜์—ˆ๋‹ค.

์ด ์ €์žฅ์†Œ ์ •์ฑ…์€ ํ•œ์ฐธ ๋์ง€๋งŒ MediaRecorder์—์„œ ์•ฝ๊ฐ„ ํ—ค๋งธ๋Š”๋ฐ ์†”๋ฃจ์…˜์ด ์žˆ๋Š” ์›นํŽ˜์ด์ง€๊ฐ€ ์—†๊ธธ๋ž˜ ์ •๋ฆฌํ•ด ๋‘”๋‹ค.

MediaRecorder

์‹œ์‹œ์ฝœ์ฝœํ•œ ๊ฒƒ๋“ค์€ ๋„ํ๋จผํŠธ์— ์ž˜ ๋‚˜์™€ ์žˆ๋‹ค.

์™ธ๋ถ€์ €์žฅ์†Œ์— ์ €์žฅํ•˜๊ธฐ

recorder = new MediaRecorder(); recorder.setAudioSource(MediaRecorder.AudioSource.MIC); recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); recorder.setOutputFile(fileName);

์—ฌ๊ธฐ์„œ setOutputFile์˜ fileName์€ ์ €์žฅํ•˜๊ณ ์ž ํ•˜๋Š” ํŒŒ์ผ๋ช…์˜ full path๋งŒ ์‚ฌ์šฉํ•˜๋ฉด ๋๋‹ค.
์ด ํ•จ์ˆ˜๋Š” ๋‚ด๋ถ€ ์ €์žฅ์†Œ(data/data/{app_name})์—์„œ๋Š” ๊ณ ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
ํ•˜์ง€๋งŒ MediaStore๋กœ ์ ‘๊ทผํ•ด์•ผํ•˜๋Š” ์™ธ๋ถ€ ์ €์žฅ์†Œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์—๋Š” ๋”์ด์ƒ String์œผ๋กœ๋œ path๋กœ ์ ‘๊ทผํ•  ์ˆ˜๊ฐ€ ์—†๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด outputFile์˜ Path๋ฅผ ์–ด๋–ป๊ฒŒ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์„๊นŒ?
setOutputFile์€ FileDescriptor๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๊ฐ–๋Š” ๊ฒƒ์ด ์žˆ๋Š”๋ฐ ์ด๋ฅผ ์ด์šฉํ•œ๋‹ค.

mediarecorder.png

  • ์‹ค์ˆ˜ ์˜ˆ์ œ
FileDescriptor getFileDescriptor(){
	ContentValues values = new ContentValues(); 
	values.put(MediaStore.Video.Media.DISPLAY_NAME, "filename.MP4"); 
	values.put(MediaStore.Video.Media.MIME_TYPE, "video/*");
	ContentResolver resolver = getContentResolver();
	Uri item = contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
	ParcelFileDescriptor fileDescriptor = null;
	try {
		fileDescriptor = resolver.openFileDescriptor(item, "w");
		return fileDescriptor.getFileDescriptor();
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	}
	return null;
}

์ด๋ ‡๊ฒŒ FileDescriptor๋ฅผ ์–ป์œผ๋ฉด?

์•ˆ๋œ๋‹ค.

๋‚ด๋ถ€์ €์žฅ์†Œ๋Š” full path๋งŒ ๋„ฃ์œผ๋ฉด ํŒŒ์ผ์ด ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์ ธ ์žˆ์ง€ ์•Š์•„๋„ ๊ทธ ์œ„์น˜์— ๊ทธ ํŒŒ์ผ๋ช…์œผ๋กœ write๊ฐ€ ๋˜์—ˆ๋˜ ๋ฐ˜๋ฉด, ์ด๋ ‡๊ฒŒ ํ•  ๋•Œ์—” ๋‚ด๊ฐ€ ์ž„์‹œ ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด ๋‘์–ด์•ผ ํ•œ๋‹ค.

์—ฌ๊ธฐ์„œ ๊ธฐ์กด ์ฝ”๋“œ๋ž‘ ๊ผฌ์˜€์–ด์„œ ์กฐ๊ธˆ ํ—ค๋งธ๋˜ ๊ฑฐ์˜€๋‹ค.

  • ์ •์ƒ ์˜ˆ์ œ
FileDescriptor getFileDescriptor() {
	ContentValues values = new ContentValues(); 
	values.put(MediaStore.Video.Media.DISPLAY_NAME, "filename.MP4"); 
	values.put(MediaStore.Video.Media.MIME_TYPE, "video/*");
	if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { 
		// ํ•ด๋‹น ํŒŒ์ผ์„ ๋‹ค๋ฅธ ์•ฑ์—์„œ ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์„ ๋ง‰๋Š” ํ”Œ๋ž˜๊ทธ.
		values.put(MediaStore.Video.Media.IS_PENDING, 1);
	}
	ContentResolver resolver = getContentResolver();
	Uri item = contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
	ParcelFileDescriptor fileDescriptor = null;
	try {
		// file write ์ถ”๊ฐ€ 
		fileDescriptor = resolver.openFileDescriptor(item, "w");
		if (fileDescriptor != null) {
		// ๋นˆ ํŒŒ์ผ ์ƒ์„ฑ
		String str = "hello";
		byte[] strToByte = str.getBytes();
		FileOutputStream fos = new FileOutputStream(fileDescriptor.getFileDescriptor());
		fos.write(strToByte);
		fos.close();
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
			values.clear();
			// ํ•ด๋‹น ํŒŒ์ผ์„ ๋‹ค๋ฅธ ์•ฑ์—์„œ ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์„ ๋‹ค์‹œ ํ—ˆ์šฉ.
			values.put(MediaStore.Images.Media.IS_PENDING, 0); 
			contentResolver.update(item, values, null, null);
		}
		return fileDescriptor.getFileDescriptor();
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	}
	return null;
}

Recording์ด ์ •์ƒ์ ์œผ๋กœ ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์„œ์น˜ํ•˜๋‹ค๊ฐ€ ๋ชป ์ฐพ๊ณ  ๊ถ๋ฆฌํ•ด๋‚ธ ๋ฐฉ๋ฒ•์ด๋ผ ์ œ๋Œ€๋กœ ๋œ ์†”๋ฃจ์…˜์ด ๋”ฐ๋กœ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.
์ง€์ ์€ ์–ธ์ œ๋‚˜ ํ™˜์˜.

  • ์ด์ „ ๊ธ€์„ ์˜ต์‹œ๋””์–ธ์œผ๋กœ ์˜ฎ๊ฒผ๋”๋‹ˆ ๋Œ“๊ธ€ ๊ธฐ๋Šฅ์ด ์—†์–ด ์ง€์ ์„ ๋ชป ๋ฐ›๋Š”๋‹ค. netlify๋กœ deploy๋œ ์‚ฌ์ดํŠธ๊ฐ€ ๊ตฌ๊ธ€ ๊ฒ€์ƒ‰์— ์ž˜ ์•ˆ ๊ฑธ๋ฆฐ๋‹ค๊ณ  ํ•ด์„œ ๋ฐฉ๋ฌธ๊ฐ์ด ์—†์„ ๊ฒƒ ๊ฐ™์ง€๋งŒ, ๊นƒํ—™ ๋ธ”๋กœ๊ทธ ๋•Œ์ฒ˜๋Ÿผ Utterances๋ฅผ ๋ถ™์ผ ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ ๊ฒ€ํ† ํ•ด ๋ณผ ์˜ˆ์ •.