이번 포스팅에서는 Assets 폴더를 사용하는 법에 대해 알아보겠습니다.
안드로이드의 읽기전용 파일 저장폴더
앱을 만들다보면 읽기전용 파일을 앱에 저장하고 불러와서 사용해야 할 때가 있습니다. 이 때 파일은 다음 두 폴더에 저장할 수 있습니다.
assets folder
resources/raw folder
각 폴더의 특징 은 다음과 같습니다.
값
assets
res/raw
파일명
자유롭게 설정 가능
a-z, 0-9, _ 만 사용가능
서브폴더
사용가능
사용불가
파일 리스팅
list()로 가능
불가능
컴파일타임 파일체크
없음
있음
XML에서 접근
불가능
가능
환경별 설정 분리
불가능
가능
간단히 정리하면 XML과 연계하여 다루어야 할 때는 res/raw
폴더를 사용하고, 그렇지 않을 경우 assets
폴더를 사용하면 될 것 같네요.
앱 만들어보기
그럼 asset폴더를 사용해보기 위해 json 파일을 불러와서 Recyclerview에 표시하는 간단한 앱을 만들어 보겠습니다.
Recyclerview는 RecyclerView에 View Binding 적용하기 에서 작성했던 프로젝트를 참고해서 사용하겠습니다. Json 포맷을 다루어야 하므로 우선 Gson 라이브러리를 추가합니다. Gson에 대한 구체적인 설명에 대해서는 SharedPreferences를 json 포맷으로 관리하기 에서 설명한 내용을 참조하시기 바랍니다.
데이터 준비
New > Folder > Asset Folder
를 선택하여 assets 폴더를 추가합니다.
데이터는 경기데이터드림에서 제공하는 코로나바이러스 감염증 선별진료소 운영 의료기관 현황 데이터를 사용하겠습니다.
sheet
탭에서 json
을 클릭하여 데이터를 다운받습니다. 다운받아보면 내용이 한줄에 모여있어 보기 불편합니다. 사용하는데는 관계 없지만 값들을 정렬하는게 보기에 좋을 것 같으니 Json Formatter 에서 파일을 정렬하고 data.json
이라는 파일명을 붙여 assets 폴더에 저장합니다.
데이터클래스 준비
데이터 파일에는 데이터기준일자, 시군명, 의료기관명, 의료기관 구분, 의료기관 전화번호1, 의료기관 전화번호2, 소재지지번주소, 소재지도로명주소, WGS84위도, WGS84경도 등 여러가지 탭이 있습니다.
각 데이터는 배열 속의 데이터클래스로 관리하기 위해 데이터클래스를 만들어줍니다. 데이터클래스의 특징에 대해서는 Data class 이해하고 RecyclerView에서 사용하기 강의에서 설명한 내용을 참고하시기 바랍니다.
안드로이드 스튜디오에 Kotlin data class File from JSON 플러그인을 설치하면 json 파일을 손쉽게 데이터클래스로 변환할 수 있습니다. 플러그인을 설치한 뒤 New > Kotlin data class File from JSON 을 선택하여 위에서 만든 json 데이터와 클래스명을 입력하면 자동으로 데이터클래스와, 그 클래스를 아이템으로 갖는 배열 클래스가 생성되는데 클래스 이름은 CoronaMed
라고 하겠습니다.
Recyclerview 구축하기
다음으로 새로 만들어진 데이터클래스의 형식에 맞게 Recyclerview와 ViewHolder의 형태를 정의해줍니다. activity_main.xml
에 RecyclerView를 추가합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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:layout_width= "match_parent"
android:layout_height= "match_parent"
tools:context= ".MainActivity" >
<androidx.recyclerview.widget.RecyclerView
android:id= "@+id/recycler_view"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:scrollbars= "vertical"
tools:listitem= "@layout/list_item"
app:layout_constraintBottom_toBottomOf= "parent"
app:layout_constraintEnd_toEndOf= "parent"
app:layout_constraintStart_toStartOf= "parent"
app:layout_constraintTop_toTopOf= "parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
list_item.xml
파일을 만들어서 ViewHolder를 구성합니다.
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android= "http://schemas.android.com/apk/res/android"
xmlns:tools= "http://schemas.android.com/tools"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:orientation= "vertical" >
<TextView
android:id= "@+id/tv_name"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:paddingStart= "24dp"
android:paddingEnd= "16dp"
android:text= "Name"
android:textSize= "20sp" />
<TextView
android:id= "@+id/tv_type"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:paddingStart= "32dp"
android:paddingEnd= "16dp"
android:text= "type"
android:textSize= "18sp" />
<TextView
android:id= "@+id/tv_phonenum"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:paddingStart= "32dp"
android:paddingEnd= "16dp"
android:text= "phonenum"
android:textSize= "18sp" />
<TextView
android:id= "@+id/tv_address"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:paddingStart= "32dp"
android:paddingEnd= "16dp"
android:text= "address"
android:textSize= "18sp" />
</LinearLayout>
그리고 마지막으로 Recyclerview 어댑터를 작성합니다.
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
class MyRecyclerViewAdapter ( private val dataset : CoronaMed ) :
RecyclerView . Adapter < MyRecyclerViewAdapter . MyViewHolder >() {
override fun onCreateViewHolder ( parent : ViewGroup , viewType : Int ): MyViewHolder {
val binding = ListItemBinding . inflate ( LayoutInflater . from ( parent . context ), parent , false )
return MyViewHolder ( binding )
}
override fun onBindViewHolder ( holder : MyViewHolder , position : Int ) {
holder . bind ( dataset [ position ])
}
override fun getItemCount (): Int {
return dataset . size
}
class MyViewHolder ( private val binding : ListItemBinding ) :
RecyclerView . ViewHolder ( binding . root ) {
fun bind ( data : CoronaMedItem ) {
with ( binding ) {
tvName . text = data . mEDINSTNM
tvType . text = data . dISTRCTDIVDTLS
tvPhonenum . text = data . eMGCCENTERTELNO
tvAddress . text = data . rEFINEROADNMADDR
}
}
}
}
assets 폴더속 파일 불러오기
다음은 메인액티비티에서 assets 폴더속 파일을 불러오기 위한 함수를 만들어줍니다. assets 폴더에 접근하기 위해 Asset Manager 인스턴스를 생성하고 open 메소드로 파일을 오픈합니다.그리고 bufferedReader 를 이용해 InputStream을 텍스트로 변환합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
private fun getJsonData ( filename : String ): CoronaMed ? {
val assetManager = resources . assets
var result : CoronaMed ? = null
try {
val inputStream = assetManager . open ( filename )
val reader = inputStream . bufferedReader ()
val gson = Gson ()
result = gson . fromJson ( reader , CoronaMed :: class . java )
} catch ( e : IOException ) {
e . printStackTrace ()
}
return result
}
나머지는 이렇게 얻어온 CoronaMed
객체를 Recyclerview 어댑터에 전달해주면 됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
override fun onCreate ( savedInstanceState : Bundle ?) {
super . onCreate ( savedInstanceState )
setContentView ( binding . root )
val testdata = getJsonData ( "data.json" )
binding . recyclerView . apply {
layoutManager = LinearLayoutManager ( context , LinearLayoutManager . VERTICAL , false )
adapter = MyRecyclerViewAdapter ( testdata !! )
addItemDecoration ( DividerItemDecoration ( context , DividerItemDecoration . VERTICAL ))
}
}
이렇게 해서 assets 폴더에서 json 파일을 불러오는 법에 대해 알아보았습니다.
VIDEO