룬아님의 취중코딩

(파일 다루기 2) Android Storage Access Framework를 이용한 파일 저장과 불러오기 본문

개발/안드로이드 개발

(파일 다루기 2) Android Storage Access Framework를 이용한 파일 저장과 불러오기

룬아님 2019. 10. 11. 17:14

이번에는 파일 다루기 1에서 만들었던 JsonString을 SAF(Storage Access  Framework)를 이용하여 저장하고 불러와보겠습니다.

https://developer.android.com/guide/topics/providers/document-provider#create

불러오는 중입니다...

 

0. Manifest에 퍼미션 추가

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

 

1. 파일 만들기

private val WRITE_REQUEST_CODE: Int = 43

private fun createFile() {
    val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
        addCategory(Intent.CATEGORY_OPENABLE)
        type = "text/timetable"
        putExtra(Intent.EXTRA_TITLE, System.currentTimeMillis().toString() + ".timetable")
    }
    startActivityForResult(intent, WRITE_REQUEST_CODE)
}

Intent.ACTION_CREATE_DOCUMENT을 사용하면 SAF를 이용하여 파일을 저장할 수 있습니다.
type은 나중에 파일을 불러올 때에도 사용되는 필터이니 만약 자신의 앱에서만 사용할 파일이라면 개별적인 타입을 지정하셔도 좋습니다.
저는 timetable이라는 타입을 사용하였습니다.

위의 코드를 보시면 파일은 만들고 있는데 안에 내용을 채워주는 코드가 없는 것을 확인할 수 있습니다.
그래서 request code를 이용하여 파일을 만든 이후에 내용을 채워주어야 합니다.

 

2. result를 이용하여 만든 파일에 값을 채워주기

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == WRITE_REQUEST_CODE) {
        when (resultCode) {
            Activity.RESULT_OK -> data?.data?.also {
                writeInFile(it, Gson().toJson(Timetable()))
            }
            Activity.RESULT_CANCELED -> {
            }
        }
    }
}


private fun writeInFile(@NonNull uri: Uri, @NonNull text: String) {
    try {
        val outputStream = contentResolver.openOutputStream(uri)
        outputStream?.also {
            val bw = BufferedWriter(OutputStreamWriter(it))
            bw.write(text)
            bw.flush()
            bw.close()
        }

    } catch (e: IOException) {
        e.printStackTrace()
    }
}

result로 들어온 data에는 uri가 들어있습니다.
그 uri를 이용하여 특정 객체를 json형식의 string으로 변환하여 1번을 통해 만들어진 파일에 내용을 저장하였습니다.

이렇게 SAF를 이용한 저장은 마무리 되었습니다.

 

3. 이번에는 SAF를 이용하여 파일을 불러오겠습니다.

private val READ_REQUEST_CODE: Int = 42

private fun getSaveDataFromExternalStorage() {
    val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
        addCategory(Intent.CATEGORY_OPENABLE)
        type = "text/timetable"
    }
    startActivityForResult(intent, READ_REQUEST_CODE)
}

이번에는 Intent.ACTION_GET_DOCUMENT를 사용하여 파일을 가져오도록 합니다.
category에 Intent.CATEGORY_OPENABLE을 추가하면 열수있는 파일이 필터링되고
type을 추가하여 저장할 때 지정했던 타입의 파일만 가져올 수 있도록 지정해주었습니다.

 

4. result를 이용하여 데이터를 꺼내옵니다.

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == WRITE_REQUEST_CODE) {
    
        ...
        
    } else if (requestCode == READ_REQUEST_CODE) {
        when (resultCode) {
            Activity.RESULT_OK -> data?.data?.also {
                try {
                    val timetableList = Gson().fromJson(readTextFromUri(it), TimetableList::class.java)
                    updateTimetable(timetableList)
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
            }
            Activity.RESULT_CANCELED -> {
            }
        }
    }
}

이번에도 Gson을 사용하여 가져온 String값을 객체로 변환하고 리스트를 갱신해주었습니다.

 

이것으로 SAF를 이용하여 파일을 저장하고 불러오는 것을 성공했습니다.

반응형
Comments