Android (안드로이드)

[Android] 화면 스크린샷 찍고 갤러리에 저장하기

Oscar:) 2024. 11. 25. 22:00
728x90

 

 

 

앱에서 스크린샷을 찍고, 이미지로 갤러리에 저장하는 방법을 알아보자.

 

 

비트맵 압축 방식으로 파일을 생성하고,

MediaScan을 사용하여 갤러리에 동기화시켜줄 것이다.

 

 

 


 

✅ Manifest 파일에 권한 추가

 

갤러리에 접근해야 하니, 관련 권한을 추가해주자.

 

AndroidManifest.xml

<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>

 

 

 

 

 

Permission 요청 세팅

 

이전 포스팅과 중복되는 내용이다.

TedPermission 라이브러리 활용해서 간단하게 권한을 요청해주자.

 

private fun checkPermission() {
	TedPermission.create()
		.setPermissionListener(object : PermissionListener {
			override fun onPermissionGranted() {
				takeScreenShot()
			}
			override fun onPermissionDenied(deniedPermissions: List<String>) {
				Log.d(TAG, "onPermissionDenied: 권한 거부됨")
			}
		})
		.setDeniedMessage("권한을 허용해 주셔야\n사용 가능합니다.")
		.setPermissions(android.Manifest.permission.READ_MEDIA_IMAGES)
		.check()
}

 

takeScreenShot() 함수에 스크린샷 관련 코드를 작성할 것이다.

 

 

 

 

 

✅ 스크린샷 찍기

 

크게 3가지 과정으로 볼 수 있다.

 

1. 스크린샷을 찍을 View 지정

2. 파일 생성 후 비트맵 압축

3. 미디어 스캔

 

private fun takeScreenShot() {
	// 캡처할 View 지정하여 Bitmap으로 변환
	val bitmap = bind.main.drawToBitmap()
    try {
    	// 파일 생성 후 비트맵으로 압축 과정
    	val fileName = "${System.currentTimeMillis()}.jpg"
        val filePath = Environment.getExternalStoragePublicDirectory("${Environment.DIRECTORY_PICTURES}/$fileName").toString()
        val file = File(filePath)
        val fos = FileOutputStream(file)
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos)
        fos.close()
        
        // 미디어 스캔
        MediaScannerConnection.scanFile(this, arrayOf(file.path), arrayOf("image/*"), MediaScannerConnection.OnScanCompletedListener { path, uri ->
        	Toast.makeText(this, "스크린 샷이 저장되었습니다.", Toast.LENGTH_SHORT).show()
        })
    } catch (e: Exception) {
    	// 예외처리
    }
}

 

1. 스크린샷을 찍을 View를 지정하고 drawToBitmap() 함수로 비트맵 변환해준다.
예제에서는 화면 전체 레이아웃을 지정했다.

 

 

2. 파일 이름은 간단히 시스템 시간으로 지어주고, 저장할 경로를 지정한 후 File을 생성해준다.

그리고 FileOutputStream을 파라미터로 비트맵으로 압축해준다.

 

위 처럼 Environment.DIRECTORY_PICTURES 경로로 지정하면,

갤러리 내 Pictures 폴더로 저장된다.

 

 

3. 미디어 스캔이 필요한 이유는, 새롭게 생성한 파일이 기기에 곧바로 반영되지 않기 때문이다.

쉽게 말해 미디어 스캔은 갤러리를 새로고침한다고 생각하면 된다.

 

파라미터를 간단히 설명하자면 다음과 같다.

scanFile(Context, 파일 경로, MIME 타입, 스캔 완료 시 콜백)

 

마지막 파라미터인 OnScanCompletedListener 콜백으로 스캔 완료 시 동작을 명시할 수 있다.

해당 리스너의 파라미터로 파일의 경로와 uri를 사용할 수도 있다.

 

 

 

 

✅ 결과

 

● 기본 UI

 

저 버튼을 누르면 checkPermission() 함수가 실행된다.

 

 

 

 

● 갤러리 진입

 

갤러리에 진입하면 위 처럼 Pictures 디렉토리가 생성됨과 동시에

스크린샷이 저장된 것을 확인할 수 있다.

 

 

 

 

● 갤러리 내 저장된 이미지

 

해당 이미지가 저장된 모습이다.

 

 

 

 

● View 변경 지정 시

 

예제에서는 ViewBinding 활용하여 bind.main 을 지정했는데,

// val bitmap = bind.main.drawToBitmap()
val bitmap = bind.imageview.drawToBitmap()

 

위 처럼 ImageView로 변경하여 비트맵을 변환하면 해당 View만 스크린샷을 찍을 수 있다.

 

 

 

 


 

 

 

 

728x90