728x90
반응형
SMALL
SAF(Scoped Access Framework)를 이용한 파일 쓰기를 대비해야하는데요 ^^
내부저장소에 저장된 파일을 SAF를 이용하여 외부저장소에 복사, 혹은 그 반대의 예제 입니다.
SAF 파일 쓰기는 밑의 포스트를 참조해 주세요.
[Android/Function] - [안드로이드] 외부 저장소에 데이터 파일 저장하기(쓰기) ― SAF(Storage Access Framework)로 파일 쓰기
내부저장소 → 외부저장소(SAF)
-
SAF 열기
/**
* Export
*/
private val REQUEST_WRITE = 43
fun onClickCopy(view: View){
saf()
}
fun saf() {
try {
/**
* SAF 파일 편집
*/
val fileName = //... 파일명
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply{
addCategory(Intent.CATEGORY_OPENABLE)
type = "*/*"
putExtra(Intent.EXTRA_TITLE, fileName)
}
startActivityForResult(intent, REQUEST_WRITE)
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
REQUEST_WRITE -> if (resultCode == RESULT_OK && data != null) {
writeFile(data)
}
else -> super.onActivityResult(requestCode, resultCode, data)
}
}
버튼이 눌리면 SAF를 이용해 파일을 만듭니다.
파일 저장 후 onActivityResult에서 결과를 받아 파일 쓰기를 시작합니다.
-
파일 쓰기(복사)
//내부 저장소 경로
private var mOutputDir = MyApplication.applicationContext().getExternalFilesDir(null)
private var pfd: ParcelFileDescriptor? = null
private var fileOutputStream: FileOutputStream? = null
fun writeFile(data: Intent?) {
val uri = data?.data
try {
pfd = uri?.let { mApplication.contentResolver.openFileDescriptor(it, "w") }
fileOutputStream = FileOutputStream(pfd?.fileDescriptor)
} catch (e: FileNotFoundException) {
e.printStackTrace()
}
// 내부저장소 파일 불러오기
var src: File? = null
if(fileName!=null) { //내부저장소 파일 이름
src = File(mOutputDir, fileName!!)
}
var inChannel: FileChannel? = null
var outChannel: FileChannel? = null
try {
inChannel = FileInputStream(src).channel
outChannel = fileOutputStream?.channel
} catch (e: FileNotFoundException) {
e.printStackTrace()
}
try {
inChannel?.transferTo(0, inChannel.size(), outChannel)
} finally {
inChannel?.close()
outChannel?.close()
//Util.showNotification("저장되었습니다.")
fileOutputStream?.close();
pfd?.close();
}
}
외부저장소(SAF) → 내부저장소
- SAF 열기
fun saf() {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "*/*"
}
startActivityForResult(intent, READ_REQUEST_CODE)
}
saf() 메서드를 통해 외부저장소에서 불러올 파일을 선택합니다.
- 파일 쓰기(복사)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
READ_REQUEST_CODE -> if (resultCode == AppCompatActivity.RESULT_OK && data != null) {
data.data?.also { uri ->
saveFile(uri)
}
}
else -> super.onActivityResult(requestCode, resultCode, data)
}
}
onActivityResult에서 받아온 uri를 이용해 파일 쓰기를 시작합니다.
private var pfd: ParcelFileDescriptor? = null
private var fileInputStream: FileInputStream? = null
private var mOutputDir = MyApplication.applicationContext().getExternalFilesDir(null)
fun saveFile(uri: Uri){
val fileName = getFileName(uri)
try {
pfd = uri.let { mApplicationContext?.contentResolver?.openFileDescriptor(it, "r") }
fileInputStream = FileInputStream(pfd?.fileDescriptor)
} catch (e: FileNotFoundException) {
e.printStackTrace()
}
var newFile: File? = null
if(fileName!=null) {
newFile = File(mOutputDir, fileName)
}
var inChannel: FileChannel? = null
var outChannel: FileChannel? = null
try {
inChannel = fileInputStream?.channel
outChannel = FileOutputStream(newFile).channel
} catch (e: FileNotFoundException) {
e.printStackTrace()
}
try {
inChannel?.transferTo(0, inChannel.size(), outChannel)
} finally {
inChannel?.close()
outChannel?.close()
Util.showNotification("성공적으로 불러왔습니다.")
fileInputStream?.close()
pfd?.close()
}
}
fun getFileName(uri: Uri): String? {
var result: String? = null
if (uri.scheme == "content") {
val cursor: Cursor? = mApplicationContext?.contentResolver?.query(uri, null, null, null, null)
try {
if (cursor != null && cursor.moveToFirst()) {
result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
}
} finally {
cursor?.close()
}
}
if (result == null) {
result = uri.path
val cut = result!!.lastIndexOf('/')
if (cut != -1) {
result = result.substring(cut + 1)
}
}
return result
}
- 참고 자료
Copy file from the internal to the external storage
728x90
반응형
LIST
'Android > Function' 카테고리의 다른 글
ScrollView 안에 있는 자식 뷰에서 독단적으로 scroll 해야 할 때 (0) | 2020.11.23 |
---|---|
[안드로이드] 권한 확인/허가 요청 코드 + 블루투스 확인/요청 (0) | 2020.10.30 |
[안드로이드] 특정 확장자의 파일 목록 불러와서 최신순, 이름순 정렬 하기 (0) | 2020.09.03 |
[Kotlin] 검색 필터링과 아이템 클릭 가능한 RecyclerView 만들기 (1) | 2020.09.01 |