Home 안드로이드 기기에서 파일 가져오기
Post
Cancel

안드로이드 기기에서 파일 가져오기

안드로이드 앱 개발을 하다보면 해당 기기에 있는 파일을 불러오고 싶을 때가 있다 예를 들면 사진이나 동영상 등 말이다 이번 글에서 이러한 기능을 구현하는 방법을 짧고 간단히 알아보겠다

우선 해당 기능을 구현하는 방법은 크게 이전에 사용하던 방법과 최근 방식 이렇게 두 가지로 나눌 수 있다 일단은 이전 방식부터 차근 차근 알아보자

구현 방법

아래 코드들은 두 방법에서 공통으로 사용 될 코드이다

activity_main.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/open_file_button"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:textSize="18sp"
        android:text="파일 열기"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</androidx.constraintlayout.widget.ConstraintLayout>

간단히 로직을 보여줄 버튼 하나로 구성하였으니 실제로 사용할 때는 상황에 맞게 구성하길 바란다

getFileNameFromUri

1
2
3
4
5
6
7
8
9
10
11
12
13
private fun getFileNameFromUri(context: Context, uri: Uri): String? {
    var fileName: String? = null
    val cursor = context.contentResolver.query(uri, null, null, null, null)

    cursor?.use {
        val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
        if (nameIndex != -1 && cursor.moveToFirst()) {
            fileName = cursor.getString(nameIndex)
        }
    }

    return fileName
}

Uri를 통해 파일 이름을 가져오는 함수이다 파일을 잘 불러왔나 확인 용으로 사용한 함수이다

viewBinding

중요한 건 아니지만 해당 코드에서 findViewById 대신 viewBinding을 이용했다

startActivityForResult를 통한 구현

먼저 소개할 방법은 startActivityForResult를 이용한 방법으로 해당 방법은 deprecated된 방법이라 추천하진 않지만 필요한 사람도 있을 거 같아 소개한다

1. REQUESTCODE 선언

1
2
3
companion object {
    const val REQUESTCODE = 200
}

우선 startActivityForResult를 통해 파일을 가져오기 위해서는 필수는 아니지만 companion object로 REQUESTCODE를 선언하는게 좋다

2. startActivityForResult 호출

그 다음으로는 버튼을 클릭 했을 때 파일을 가져오게 만들 것이니 setOnClickListener 안에

1
2
3
4
5
binding.openFileButton.setOnClickListener {
    val intent = Intent(Intent.ACTION_GET_CONTENT)
    intent.type = "*/*"
    startActivityForResult(intent, REQUESTCODE)
}

이런 식으로 Intent(Intent.ACTION_GET_CONTENT) 객체에 type을 설정한 뒤 아까 위에 설정한 REQUESTCODE와 함께 tartActivityForResult에 넣어주면 된다

3. onActivityResult 재정의

그 뒤 onActivityResult를 override 해주는 것이 필요한데 이 부분은 쉽게 말하자면 파일을 선택한 이후 행동할 로직을 작성하는 부분이다

1
2
3
4
5
6
7
8
9
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == REQUESTCODE && resultCode == Activity.RESULT_OK) {
        data?.data?.let { uri ->
            val fileName = getFileNameFromUri(this, uri)
            Toast.makeText(this, fileName, Toast.LENGTH_SHORT).show()
        }
    }
}

우선 조건문으로 onActivityResult에 requestCode와 우리가 startActivityForResult를 통해 넘겨준 REQUESTCODE 값이 일치하는지 resultCode가 RESULT_OK인지 검증하고

만약 둘다 만족한다면 성공적으로 파일을 선택한 값이 들어온 경우이다 우린 이제 여기에 로직을 작성해주면 되는데 난 예시로 보여줘야 하니 getFileNameFromUri를 통해 파일 이름을 가져와서

Toast 메시지로 출력해보겠다

그러면 이렇게 잘 출력되는 걸 볼 수 있다

registerForActivityResult를 통한 구현

다음으로 소개할 방법은 registerForActivityResult를 이용한 방법으로 더 간단하게 가능하며 해당 방법은 현재 기준으로 권장되는 방법이다

1. registerForActivityResult 선언

우선 registerForActivityResult를 통해 파일을 가져오기 위해서는 registerForActivityResult를 선언해야 한다 여기서 인자로 넣을 수 있는 ActivityResultContracts 클래스의 하위 타입은 다양하지만 startActivityForResult와 비슷하게 하기 위해 GetContent로 하겠다

참고로 GetContent는 사용자가 파일을 선택할 수 있게 할 때 쓰는 타입이다

1
2
3
4
5
6
7
private val openFileLauncher =
    registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
        if (uri != null) {
            val fileName = getFileNameFromUri(this, uri)
            Toast.makeText(this@MainActivity, fileName, Toast.LENGTH_SHORT).show()
        }
    }

다음으로 startActivityForResult에서 했던 것처럼 마찬가지로 조건문을 통해 Uri 값을 Null 체크한 뒤 getFileNameFromUri을 통해 파일 이름을 가져와서 Toast 메세지로 출력하게 한다

2. registerForActivityResult 실행

마찬가지로 버튼을 클릭 했을 때 파일을 가져오게 만들 것이니 setOnClickListener 안에

1
2
3
binding.openFileButton.setOnClickListener {
    openFileLauncher.launch("*/*")
}

이런 식으로 openFileLauncher를 launch 해주면 되는데

그러면 마찬가지로 이렇게 잘 출력되는 걸 볼 수 있다

마치며

마치며 계속해서 등장하던 / 같은 문자들은 MIME 타입이라고 부르며 자세한 설명은 여기를 참고하고 간단히는 어떤 파일 형식을 가져올지 지정하는 거라고 보면 된다 참고로 우리가 코드에서 사용한 /는 모든 형식에 파일을 뜻한다

This post is licensed under CC BY 4.0 by the author.