본문 바로가기
Mobile Programming/Android

[Kotlin] 갤러리 어플리케이션 만들기

by 푸고배 2020. 8. 6.


핸드폰에 저장되어 있는 사진을 불러와 다음과 같은 갤러리 타입으로 사진을 보여주는 페이지를 만든다.

먼저 이미지 로드의 편의성과, 개발의 편의성을 위해 Gradle Scripts<build.gradle(Module:app)에 Glide와 Anko 라이브러리 의존성을 추가해준다.


dependencies {

    implementation 'org.jetbrains.anko:anko:0.10.5'

    implementation 'com.github.bumptech.glide:glide:4.7.1'

}


핸드폰 카메라로 찍은 사진은 내부 저장소에 저장되고, 안드로이드의 미디어 데이터베이스에도 사진의 정보가 저장된다.

저장된 미디어 데이터는 Contents Provider(앱의 데이터 접근을 다른 앱에 허용하는 컴포넌트)로 불러올 수 있다.


안드로이드의 4대 컴포넌트

  • 액티비티 : 화면을 구성합니다.

  • 콘텐츠 프로바이더 : 데이터베이스, 파일, 네트워크의 데이터를 다른 앱에 공유합니다.

  • 브로드캐스트 리시버 : 앱이나 기기가 발송하는 방송을 수신합니다. 이 책에서는 다루지 않습니다.

  • 서비스 : 화면이 없고 백그라운드 작업에 용이합니다.


먼저 activity_main.xml에는 GrideView를 전체 화면 크기로, ID값을 gridView로 설정한다.


외부 저장소 접속을 위해서는 AndroidManifest.xml에 권한 등록이 필요하다.


<manifest xmlns:android ...

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

</manifest>


이후 MainActivity에서 권한을 얻는 alert창을 띄운다.

alert{ } 구문은 Anko를 이용해 간단하게 구현하였다.


private val REQUEST_READ_EXTERMAL_STORAGE = 1000

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

// 권한 부여 확인
if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
// 권한 허용 안됨
if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)){
// 이전에 이미 권한이 거부되었을 때 설명
alert("사진 정보를 얻으려면 외부 저장소 권한이 필수로 필요합니다",
"권한이 필요한 이유") {
yesButton {
// 권한 요청
ActivityCompat.requestPermissions(this@MainActivity,
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
REQUEST_READ_EXTERMAL_STORAGE)
}
noButton { }
}.show()
} else {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
REQUEST_READ_EXTERMAL_STORAGE)
}
} else {
// 권한이 이미 허용됨

getAllPhotos()
    
}
}


// 사용자가 권한 요청 시 호출되는 메서드
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when(requestCode){
REQUEST_READ_EXTERMAL_STORAGE -> {
if((grantResults.isNotEmpty() && grantResults[0]
== PackageManager.PERMISSION_GRANTED)) {
getAllPhotos()
} else {
toast("권한 거부 됨")
}
return
}
}

}



사용자가 해당 앱에서 갤러리 접근을 허용하면 아래의 함수를 실행시켜 사진 정보를 불러온다.


private fun getAllPhotos(){
val cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
null,
null,
null,
MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC")
val uriArr = ArrayList<String>()
if(cursor!=null){
while(cursor.moveToNext()){
// 사진 경로 Uri 가져오기
val uri = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA))
uriArr.add(uri)
}
cursor.close()
}
val adapter = MyAdapter(this,uriArr)
gridView.numColumns=3 // 한 줄에 3개씩
gridView.adapter = adapter

}

 

GrideView를 사용해 그리드 형식으로 이미지를 불러오기 위해서는 Adapter가 필요하다.

따라서 MyAdapter.kt라는 이름의 코틀린 파일을 추가해주고 아래의 코드를 붙여 넣는다.

getCount()는 GrideView에 표시할 View의 수, GetItem은 해당 위치의 데이터 getItemId는 해당 위치의 데이터 아이디 정보, getView는 해당 위치에 보여줄 View를 반환한다.

이 예제에서는 정사각형 모양으로 이미지를 보여주기 위해 getView에서 layoutParams 함수를 통해 이미지 크기를 지정해준다. 

또한 이미지는 Glide 라이브러리를 이용해서 불러온다.


class MyAdapter(val context: Context, uriArr:ArrayList<String>) : BaseAdapter(){
private var items = ArrayList<String>()
init {
this.items = uriArr
}
override fun getCount(): Int {
return items.size
}

override fun getItem(position: Int): Any {
return items[position]
}

override fun getItemId(position: Int): Long {
return position.toLong()
}

override fun getView(p: Int, convertView: View?, parent: ViewGroup?): View {
val imageView = ImageView(context)
val display = context.getResources().getDisplayMetrics()
imageView.padding = 2
imageView.scaleType = ImageView.ScaleType.CENTER_CROP
imageView.layoutParams = LinearLayout.LayoutParams(display.widthPixels/3,display.widthPixels/3)
Glide.with(context).load(items[p]).into(imageView)
return imageView
}

}



참고 자료 :  오준석의 안드로이드 생존코딩(코틀린 편)

반응형

댓글