안드로이드 앱을 개발 하는 과정에서
csv 파일을 저장할 필요가 있었다.
그래서 Manifest.xml 에서 권한을 등록하고 파일 관리자를 통해 저장을 했었다.
fun writeToFile(moneyLogs: List<MoneyLog>, fileName: String,context: Context) {
val header = listOf("UID", "Charge", "Sign", "Category", "Date", "Memo", "Budget", "Server")
val csvData = moneyLogs.joinToString("\n") { "${it.uid},${it.charge},${it.sign},${it.category},${it.date},${it.memo},${it.budget},${it.server}" }
val csvString = "${header.joinToString(",")}\n$csvData"
/* val filePath: String =
context.filesDir.path
.toString() + "/$fileName"*/
val fileDownload = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val getDownload = fileDownload.path
val filePath: String = "$getDownload/$fileName"
try {
File(filePath).printWriter().use { out ->
out.write(csvString)
}
}catch (e: Exception){
Toast.makeText(context,"파일을 저장할 수 없습니다",Toast.LENGTH_SHORT).show()
}
}
해당 코드를 사용해 CsvWrite에서 함수를 불러와 권한을 체크한 후 저장을 시도했으나
권한이 없다고만 뜨고, 권한없이 시도하니 권한이 없어서 오류메세지만 나왔었다.
이 부분을 찾아보니 안드로이드11이후 버전은 보안이 강화되어 공용저장소저장을 엄격하게 관리한다고 한다.
그래서 ACTION_CREATE_DOCUMENT 인텐트 사용해 파일을 생성하기로 하였다.
이렇게 하는 경우(사용자가 수동으로 직접 저장을 하므로)
안드로이드 시스템에 의해 자동으로 권한이 부여되기 때문에 권한 체크를 안해도 되는 것 같다.
또한 Android 11(API 레벨 30)부터 onActivityResult() 메소드 또한 더 이상 권장되지 않기 때문에
Activity Result API 사용해서 깔끔하게 구현하였다.
API 호출후 실행되는 저장 코드
@RequiresApi(Build.VERSION_CODES.O)
fun createFile(activity: AppCompatActivity,moneyLogs: List<MoneyLog>,uri: Uri) {
activity.contentResolver.openOutputStream(uri).use { outputStream ->
val writer = OutputStreamWriter(outputStream)
val csvWriter = CSVWriter(writer)
// Write Header
val header = arrayOf("UID", "Charge", "Sign", "Category", "Date", "Memo", "Budget", "Server")
csvWriter.writeNext(header)
/* val csvData = moneyLogs.joinToString("\n") { "${it.uid},${it.charge},${it.sign},${it.category},${it.date},${it.memo},${it.budget},${it.server}" }
val csvString = "${header.joinToString(",")}\n$csvData"*/
// Write Data
moneyLogs.forEach { item->
val row = arrayOf(item.uid.toString(),item.charge.toString(),item.sign.toString(),item.category,item.date,item.memo,item.budget.toString(),item.server.toString())
csvWriter.writeNext(row)
}
csvWriter.close()
}
}
Result API 코드
private val createFileActivityResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == AppCompatActivity.RESULT_OK) {
result.data?.data?.also { uri ->
FileWriter.createFile(mainActivity,MyApplication.db.allLogs,uri)
}
}
}
인텐트 생성 후 API 호출
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "application/csv"
putExtra(Intent.EXTRA_TITLE, "moneyLogs.csv")
}
createFileActivityResultLauncher.launch(intent)
안드로이드 OS와 구성 요소, 생명 주기(세미나) (1) | 2024.01.12 |
---|---|
안드로이드 공부를 위한 지침 (0) | 2023.12.28 |
data binding 실습 (단 방향, 양 방향 통신) (0) | 2023.07.04 |
디자인 패턴 MVC, MVP 그리고 MVVM 학습 (0) | 2023.07.03 |
안드로이드 Manifest에 대해 (0) | 2023.04.02 |
댓글 영역