선생님, 개발을 잘하고 싶어요.

[안드로이드 잡학] File 저장하기 (internal , external storage) 본문

개발/android 개발

[안드로이드 잡학] File 저장하기 (internal , external storage)

알고싶은 승민 2022. 3. 14. 19:00

파일 저장소 구분

internal: 항상 접근 가능, 파일을 저장한 앱에서만 접근 가능, 앱 제거시 함께 사라짐

external: removable한 저장소 (usb, disk 등은 항상 제거될 수 있다), 어디서든 접근 가능, 앱 제거해도 그대로 남아있음.

주의 사항) app-specific external은 그냥 외부 disk (sdcard) 등에 저장될 뿐 앱과 함께 제거되고 접근 가능한 속성을 그대로 가진다.

Internal 저장소 사용 예시

class InternalFileStorageUseCase {

    private lateinit var context: Context

    // 내부 저장소에 저장된 파일에 접근하기
    fun accessStoredFile(): File {
        val dir = context.filesDir
        val filename = "sample.txt"
        val file = File(dir, filename)
        return file
    }

    // Stream 사용해서 파일 저장하기
    fun storeFileUsingStream() {
        val filename = "sample.txt"
        val fileContent = "Hello World!"
        // API 24 이상에서, MODE_PRIVATE 사용 안하면, SecurityException 발생
        context.openFileOutput(filename, Context.MODE_PRIVATE).use {
            it.write(fileContent.toByteArray())
        }
    }

    // Stream 사용해서 파일 접근하기
    fun accessFileUsingStream() {
        val filename = "sample.txt"
        context.openFileInput(filename).bufferedReader().useLines { lines ->
            lines.fold("") { some, text ->
                "$some\n$text"
            }
        }
    }

    // 파일 리스트 받아오기
    fun viewListOfFiles() {
        var files: Array<String> = context.fileList()
    }

    // 폴더 만들기
    fun createNestedDir() {
        val dirName = "sub"
        context.getDir(dirName, Context.MODE_PRIVATE)
    }

    // 캐시 파일 만들기
    fun createCacheFile() {
        val cacheDir = context.cacheDir
        val filename = "temp.jpg"
        File.createTempFile(filename, null, cacheDir)
    }

    // 캐시 파일 접근하기, 단 캐시 파일의 경우 안드로이드가 임의로 지워버릴 수 있음.
    fun accessCacheFile(): File {
        val filename = "temp.jpg"
        val cacheFile = File(context.cacheDir, filename)
        return cacheFile
    }

    // 캐시 파일 제거하기
    // 안드로이드가 캐시 파일을 제거를 보장하지는 않음. 적절한 처리할 것
    fun removeCacheFile() {
        val cacheFile = accessCacheFile()
        // case 1
        cacheFile.delete()
        // case 2 
        context.deleteFile(cacheFile.name)
    }
}

 

External 저장소 사용 예시

// 앱 특화된 external 저장소로, API 19 이상부턴 별다른 권한 없이 접근이 가능하다.
// 앱을 제거할 때 함께 제거된다.
// 항상 접근이 보장되는게 아니기 때문에, 앱의 메인 기능을 이 파일에 의존하면 안된다.

// API 28 이하에서는 적절한 권한만 있으면, 다른 앱의 external 영역에 접근할 수 있다.
// API 29 이상에서는 scoped storage로 관리하면 된다, scoped access를 허용하면, 다른 앱의 external 파일에 접근 못함.
class ExternalFileStorageUseCase {

    private lateinit var context: Context

    // external은 항상 접근가능하지 않다. (sd card, usb를 생각해봐라 사용자가 마음대로 뽑아버릴 수 있다.)

    // 쓰기 가능한 상태인지 체크
    fun isExternalStorageWritable(): Boolean {
        return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED
    }

    // 읽기 가능한 상태인지 체크
    fun isExternalStorageReadable(): Boolean {
        return Environment.getExternalStorageState() in
            setOf(Environment.MEDIA_MOUNTED, Environment.MEDIA_MOUNTED_READ_ONLY)
    }

    // 여러 볼륨 중에 고르기
    // API 18 이하에서는 하나만 있다.
    fun selectPhysicalStorageLocation(): File {
        val externalStorageVolumes: Array<out File> =
            ContextCompat.getExternalFilesDirs(context, null)
        val primaryExternalStorage = externalStorageVolumes[0]
        return primaryExternalStorage
    }

    // app-specific 외부 저장소에 파일 접근하기
    fun accessFile(): File {
        val externalDir = context.getExternalFilesDir(null)
        val filename = "sample.txt"
        val file = File(externalDir, filename)
        return file
    }

    // API 30 이상부터 앱에서 external storage에 본인 소유 directory 못만든다.

    fun createCacheFile(): File? {
        if (isExternalStorageWritable()) {
            val externalCacheDir = context.externalCacheDir
            val filename = "temp.jpg"
            val file = File(externalCacheDir, filename)
            return file
        } else {
            return null
        }
    }
}

 

참고 자료

Data and File Storage Overview : 저장할 데이터의 속성에 따라서 무슨 API를 봐야할 지 table 형태로 정리된 자료, 데이터 저장소 작업이 필요할 때 항상 처음으로 참고할 웹사이트

Raywenderlich Saving Data On Android : 안드로이드 데이터 저장 관련 시리즈 중 File 관련 내용만 발췌, 전체 내용을 보고 한번 자신만의 UseCase를 정리하면 요긴하게 사용할 수 있을 것 같음.

Access app-sepcific files : 앱에서만 접근할 수 있는 (context에서 제공하는) 파일 저장소 API, 사용법을 보고 정리하면 좋을 듯

 

 

 

Comments