일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 재사용
- 안드로이드
- Fragment에서 Activity의 함수 사용하기
- espresso
- high order function
- 뷰변경 감지
- Error:Execution failed for task ':app:mergeDebugResources'
- 코틀린
- LayoutManger
- ui test
- 구분선
- Fragment 수동 추가
- 고차함수
- ActivityTestRule
- 안드로이드스튜디오
- adapter
- 스와이프
- IntentTestRule
- recyclerview
- searchview
- viewholder
- 생명주기
- 안드로이드13
- 테마 아이콘
- 리사이클러뷰
- Android
- 코딜리티
- 안드로이드개발레벨업교과서
- binding adapter
- fragment
Archives
- Today
- Total
룬아님의 취중코딩
(파일 다루기 3) URI로 real path 가져오기 본문
SAF로 파일을 불러오거나 파일을 수정할 때에는 URI를 사용합니다.
하지만 개발 요구에 따라 URI가 아닌 실제 저장 위치를 알아야 할 때가 있습니다.
이번에는 파일 다루기 2에서 저장했던 파일의 실제 저장 위치를 가져오도록 해보겠습니다.
1. external storage 권한 받아오기
private val PERMISSIONS_STORAGE = arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
private fun saveJsonFileToExternalStorage() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
....
} else {
ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE)
}
}
// -> 권한 요청을 거절했을 때를 위한 예외처리
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
REQUEST_EXTERNAL_STORAGE -> {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !this.shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) {
AlertDialog.Builder(this)
.setMessage("저장하려면 권한이 필요")
.setCancelable(false)
.setPositiveButton(R.string.settings
) { _, _ ->
try {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
.setData(Uri.parse("package:$packageName"))
startActivityForResult(intent, REQUEST_EXTERNAL_STORAGE)
} catch (e: ActivityNotFoundException) {
e.printStackTrace()
val intent = Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS)
startActivityForResult(intent, REQUEST_EXTERNAL_STORAGE)
}
}
.setNegativeButton(R.string.cancel
) { _, _ -> }
.show()
}
}
}
}
}
MediaStore를 이용하여 외부 저장소에 접근해야하기 때문에 권한이 없는 상태로 query를 사용하면 퍼미션 에러에 의해 앱이 종료됩니다. 반드시 퍼미션 체크를 확실히 하고 다음으로 넘어가길 바랍니다.
2. MediaStore를 이용하여 real path 구하기
private val projection = arrayOf(MediaStore.Files.FileColumns._ID, MediaStore.Files.FileColumns.DISPLAY_NAME, MediaStore.Files.FileColumns.DATA, MediaStore.Files.FileColumns.BUCKET_DISPLAY_NAME)
//id와 display name, path, bucket을 가져오도록
private fun getRealPathFromURI(){
val selection = MediaStore.Files.FileColumns.DISPLAY_NAME + " LIKE ?"
val selectionArgs = arrayOf("%" + ".timetable")
//DISPLAY_NAME에서 .timetable이 포함되어 있는 파일만 가져오도록
val cursor: Cursor? = contentResolver.query(MediaStore.Files.getContentUri("external"), projection, selection, selectionArgs, MediaStore.Images.Media.DATE_ADDED)
//MediaStore.Images.Media.DATE_ADDED을 이용하여 저장된 순서대로 정렬
val dialog = AlertDialog.Builder(this)
if (cursor != null) {
//가장 최신에 저장된 파일을 가져오기 위해서 마지막 파일을 읽어옴
if (cursor.moveToLast()) {
val path = cursor.getString(cursor.getColumnIndex(projection[2]))
dialog.setMessage(if (path.isNullOrEmpty()) "good to save" else path)
}
cursor.close()
} else {
dialog.setMessage("good to save")
}
dialog.setPositiveButton(R.string.action_ok) { _, _ -> }.show()
}
MediaStore는 안드로이드 시스템에서 제공하는 미디어 데이터 DB입니다.
query를 사용하여 특정 DB만 가져올 수 있기 때문에 다양한 방법을 사용하여 자신이 원하는 결과를 얻을 수 있습니다.
http://dktfrmaster.blogspot.com/2016/10/mediastore.html
또한 이 블로그의 글을 통하여 많은 도움을 얻었습니다.
반응형
'개발 > 안드로이드 개발' 카테고리의 다른 글
Gson.fromJson() - 타입이 틀렸을 때 예외처리 하기 (0) | 2019.10.14 |
---|---|
BindingAdapter가 작동하지 않을 때 (0) | 2019.10.12 |
(파일 다루기 2) Android Storage Access Framework를 이용한 파일 저장과 불러오기 (0) | 2019.10.11 |
(파일 다루기 1) Gson을 이용하여 커스텀 객체를 Json 객체로 변환하기 (0) | 2019.10.11 |
PreferenceFragment에서 PreferenceFragmentCompat으로 변경하기 (0) | 2019.10.02 |
Comments