안드로이드

(Android) 동영상 촬영 및 DCIM폴더에 저장하기

danune.dev 2022. 6. 22. 10:40

안드로이드에서 제공하는 Intent를 이용해 동영상을 촬영하고 특정한 위치에 저장하는 방법입니다 

비슷한 예제로 사진촬영을 요청할 수 있습니다. 마지막 5번에서 ACTION_VIDEO_CAPTURE 대신 ACTION_IMAGE_CAPTURE를 넘기면 사진을 촬영할 수 있습니다 

여기서는 동영상을 촬영하여 DCIM폴더에 저장하는 방법을 공유합니다 

 

1. 권한 설정

AndroidManifest.xml에 아래 권한을 추가합니다

<manifest>
	<application>
    	<!-- ... -->
    </application>
	<uses-feature android:name="android.hardware.camera" android:required="true" />
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
	<uses-permission android:name="android.permission.CAMERA" />
</manifest>

 

2. file provider 설정

external storage를 사용하기 위해서는 앱에서 접근할 path 들을 미리 정의해줘야 합니다 

우선 Androidanifest.xml에 provider를 설정합니다 

<manifest>
	<application>
    	<!-- ... -->
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="{패키지명: com.test.app}.fileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>
    </application>
</manifest>

그리고 res/xml/file_paths.xml을 추가합니다 

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external-path" path="." />
</paths>

 

3. permission 요청

Manifest에 추가한 권한을 Activity에서 요청합니다. 요청하는 코드 예제는 아래와 같습니다 

- Manifest.permission.WRITE_EXTERNAL_STORAGE

- Manifest.permission.CAMERA

class MainActivity : AppCompatActivity() {

    private val launcher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
        if (granted) { 
            // ...
        } else {
            // ..
        }
    }

    private fun requesWriteExternalStoragePermission() {
        launcher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
    }
}

 

4. File생성

동영상 촬영을 요청하기 전에, 동영상을 저장할 위치에 파일을 생성하여 인자로 전달해야 합니다 

(위치가 상관없다면 넘기지 않아도 됩니다)

private fun createFile(filename: String): Uri? {
    try {
        val dir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "내가 생성할 폴더이름")
        if (!dir.exists())
            dir.mkdir()
        val file = File(dir, filename)
        return FileProvider.getUriForFile(
            this,
            "${packageName}.fileProvider",
            file
        )
    } catch (e: Exception) {
        return null
    }
}

 

5. 동영상 촬영 요청

class MainActivity : AppCompatActivity() {
    val launcherForVideoCapture = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            // 성공
        }
    }
    
    fun captureVideo() {
    	val file = createFile() ?: return
        launcherForVideoCapture.launch(Intent(MediaStore.ACTION_VIDEO_CAPTURE).apply {
            putExtra(MediaStore.EXTRA_OUTPUT, file) / /
        })
    }
}
  • EXTRA_OUTPUT을 넘긴경우 RESULT_OK가 되어도 result.data 가 null로 반환됩니다 (실제 파일은 생성됨)
  • RESULT_OK가 아닌경우 빈 파일이 생성되니, 파일을 제거해야 합니다