핀수로그
  • [Android] 외부저장소에 파일 저장하기
    2023년 11월 13일 23시 36분 38초에 업로드 된 글입니다.
    작성자: 핀수
    728x90
    반응형

    안드로이드 파일 시스템에는 크게 내부저장소, 외부저장소가 존재한다.

    앱 디버깅이나 기타 다른 목적을 위해 앱 경로에 파일을 저장하곤 했는데 이것이 내부저장소이다.

    디바이스 파일 탐색기에서 찾을 수 없고 특별히 권한을 요청하지 않아도 된다.

    그러나 나의 경우에는 디바이스 파일 탐색기에 저장되고, 불러오기를 원했다.

    내부저장소에 저장할 경우 앱 재설치하는 경우 데이터가 다 날아가버리기 때문이다.

    따라서, 외부저장소는 다른 곳에서도 접근이 가능한 곳을 의미한다.

    파일 탐색기를 열어보면 나오는 파일들...이라고 하면 이해가 편할까

    외부저장소의 경우 WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE 권한을 부여 받아야 한다.

     

    파일 저장하기

    디바이스 파일 - 문서 경로에 파일을 저장할 수 있도록 했다.

    override fun saveTestLocationData(fileName: String, data: RawData) {
            CoroutineScope(Dispatchers.IO).launch {
                val gson = GsonBuilder().setPrettyPrinting().create()
                val json = gson.toJson(data)
                val name = "${fileName}_${
                    System.currentTimeMillis().toDate("yyyyMMdd_HHmmss")
                }.json"
    
                val directory =
                    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)
                val file = File(directory, name)
    
                try {
                    withContext(Dispatchers.IO) {
                        val outputStream = FileOutputStream(file)
                        outputStream.write("${json}\n".encodeToByteArray())
                        outputStream.close()
                    }
                    CoroutineScope(Dispatchers.Main).launch {
                        view.onResultSaveTestLocation(isComplete = true)
                        testRecords.clear()
                    }
    
                } catch (e: Exception) {
                    CoroutineScope(Dispatchers.Main).launch {
                        view.onResultSaveTestLocation(isComplete = false)
                        testRecords.clear()
                    }
                }
            }
        }

    파일 불러오기

    파일을 저장했으면 불러와야겠지?

    나의 경우 json 확장자만 불러오고 싶었기 때문에 아래와 같이 작성해주었다.

    /**
     * 확인할 테스트 데이터를 탐색합니다
     *
     */
    private fun searchFiles() {
        val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
        intent.addCategory(Intent.CATEGORY_OPENABLE)
        intent.type = MimeTypeMap.getSingleton().getMimeTypeFromExtension("json")
    
        launcher.launch(intent)
    }
    private val launcher =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                if (result.resultCode == RESULT_OK) {
                    result.data?.let {
                        it.data?.let { uri ->
                            showData(uri)
                        }
                    }
                }
            }
    private fun showData(uri: Uri) {
        CoroutineScope(Dispatchers.Main).launch {
            val cursor = contentResolver.query(uri, null, null, null)
            cursor?.let { c ->
                val nameIndex = c.getColumnIndex(OpenableColumns.DISPLAY_NAME)
                c.moveToFirst()
                fileName = c.getString(nameIndex)
                CoroutineScope(Dispatchers.Main).launch {
                    binding.fileNameTextView.text = fileName
                }
                c.close()
            }
            clearPath()
            contentResolver.openInputStream(uri)?.use { input ->
                try {
                    val data = ByteArray(size = input.available())
                    input.read(data)
                    input.close()
                    val strData = String(data)
                    getLatLngList(strData)
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }
    }

    공부하며 작성된 글이라 잘못된 정보가 있을 수 있습니다.

    말씀해주시면 수정하겠습니다. 감사합니다.

    References

    아래 글을 참고하여 작성 되었습니다. 

     

    Android 저장소 시스템

    다른 앱에서 접근 불가능한 고유 앱 영역. (다른앱과 공유 안된다.) * 사용 함수 getFilesDir() : 앱과 고유하게 연결된 파일 시스템의 디렉터리를 표시하는 File 개체를 반환 getDir(name, mode) : 앱의 고유

    boilerplate.tistory.com

     

    728x90
    반응형
    댓글