안드로이드

[Android/Kotlin] 앱 데이터 및 파일 (1) MediaStore

란서 2022. 3. 10. 11:34

앱 데이터 및 파일

대부분의 경우 App은 다른 앱에서 액세스할 필요가 없거나 액세스하면 안되는 파일을 만든다. 이러한 파일들을 시스템에서 제공하는 다음 저장소에 저장할 수 있다.

 

 

  • App별 저장소

    - 내부 저장소 : 영구파일을 저장하는 전용위치 & 캐시 데이터를 제공하는 위치가 모두 포함된 디렉토리

    시스템은 다른 앱에서 이러한 위치에 엑세스하는 것을 방지. Android 10 이상에서는 위치를 암호화하기에 민감한 정보를 저장하기에 탁월.

    - 외부 저장소 : 영구파일을 저장하는 전용위치 & 캐시 데이터를 제공하는 위치가 모두 포함된 디렉토리 +

    다른 앱에 적절한 권한이 있으면 해당 디렉토리에 접근 가능. 하지만 이 디렉토리에 위치한 파일들은 해당 앱에서만 사용 가능. 

    따라서 다른 앱에서 접근하게 만드려면 외부 저장소의 공유 저장 공간 에 대신 저장한 파일만 가능.

    내부 & 외부 저장소는 사용자가 앱을 제거하면 내부 파일이 삭제한다. 따라서 앱 제거 이후에도 사용할 파일들은 적절한 공유 저장 공간에 저장한다.


  • 공유 저장소 
    다른 앱에서 액세스할 수 있거나 다른 앱에 액세스 할 수 있어야 하고, 사용자가 앱을 제거하더라도 보존되어야 하는 데이터를 저장하는 공간

    - 미디어 콘텐츠 : 시스템은 이러한 종류의 파일에 표준 공개 디렉토리를 제공하므로 사용자는 모든 사진을 저장하는 공동 위치, 모든 음악 및 오디오 파일을 저장하는 또 다른 공동 위치 등을 가지게 된다.

    앱은 플랫폼의 MediaStore API 를 사용하여 이 콘텐츠에 엑세스 가능하다.

    - 문서 및 기타 파일.
    - 데이터 세트.


미디어 콘텐츠

공유 저장소의 미디어 파일에 액세스. 많은 앱에서 더욱 풍부한 사용자 환경을 제공하기 위해 사용자가 외부 저장소 볼륨에서 사용가능한 미디어를 제공하고 액세스 프레임 워크는 MediaStore라고 하는 미디어 Collection에 최적화된 색인을 제공하여 미디어 파일을 더욱 쉽게 검색하고 업데이트 할 수 있게 한다. 앱이 제거된 이 후에도 이러한 파일은 남아있다.

미디어 저장소의 추상화와 상호작용하기 위해서는 ContentResolver가 필요하다. (activityAppContext 로 부터 Retrieve)


  • projection
val projection = arrayOf (가져오고 싶은 columns)

: projection은 DB의 쿼리 구문에서 "SELECT" 와 같은 역할을 한다. 보통 

arrayOf(
        MediaStore.Images.Media._ID,
        MediaStore.Images.Media.DISPLAY_NAME,
        MediaStore.Images.Media.DATE_ADDED)

와 같은 columns를 가져올 수 있다.


  • selection
val selection = "${미디어 콘텐츠의 columns값} (>=, <=, >, <, LIKE, ==) ?"

selection의 "WHERE"와 같은 용도로 쓰인다. 조건이 필요 없다면 생략이 가능(null), 조건이 있다면 operation과 "?"을 사용하여 표시하고, ?의 자리는 selectionArgs로 설정할 수 있다.

 

  • selelctionArgs
val selectionArgs = arrayOf(selection ? 에 들어갈 인자)

selection 변수의 ? 에 들어갈 변수를 Array로 set.

arrayOf(
	dateToTimeStamp(day=22, month=10, year=2008).toString()
)

 

  • sortOrder
val sortOrder = "${미디어콘텐츠의 Columns 값} (ASC, DESC)"

sortOrder는 DB쿼리의 "ORDER BY" 에 해당한다.

 

 

MediaStore.media_type

MediaStore의 media_type은 다음과 같다.

 

  • Images : 사진과 스크린샷을 포함하여 DCIM/ , Pictures/ 디렉토리에 저장한다.

    MediaStore.Images 테이블을 사용한다.

  • Videos : DCIM/ , Movies/ , Pictures/ 디렉토리에 저장한다.

    MediaStore.Videos 테이블을 사용한다.

  • Audios : Alarms/ , Audiobooks/ , Music/ , Notifications/ , Podcasts/ , Ringtons/ 디렉토리에 저장한다.

    MediaStore.Audio 테이블을 사용한다.

  • Download : Download/ 디렉토리에 저장한다.

    MediaStore.Downloads 테이블을 사용한다.

  • Files: 해당 콜렉션은 Android 10 이상을 타겟으로 하는 APP에서 "범위 지정 저장소"를 사용하는 여부에 따라 사용이 가능하다.

 

소스 코드

 

//data class MediaStoreImage
val images = mutableListOf<MediaStoreImage>()

val query = getApplication<Application>().contentResolver.query(
	MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
    projection,
    selection,
    selectionArgs,
    sortOrder
)

query?.use {cursor ->
	val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
    val nameColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME)
    val dataModifiedColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_ADDED)
    
    while(cursor.moveToNext()) {
    	val id = cursor.getLong(idColumn)
        val dateModified = Date(TimeUnit.SECONDS.toMillis(cursor.getLong(dateModifiedColumn))
        val displayName = cursor.getString(nameColumn)
        
        val contentUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id)
        
        val image = MediaStoreImage(id, displayName, dateModified, contentUri)
        images += image
    }
}

 

저장소 권한

<uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" 
				android:maxSdkVersion = "28" />