1. 삼성 휴대폰 USB 드라이버 사이트
https://developer.samsung.com/android-usb-driver
2. 안드로이드 젯팩
구글 안드로이드팀에서 공식 발표한 라이브러리 모음으로, 퀄리티 높은 앱을 만들 수 있다.
주요 라이브러리로는 AppSearch, CameraX, Compose, Data Binding, LiveData, WorkManager, Navigation, Test, ViewBinding 등이 있다.
모두 [androidx.이름] 같은 패키지명으로 구성된다.
안드로이드 젯팩 홈페이지 : https://developer.android.com/jetpack?hl=ko
3. 구글 ML 키트
구글 머신 러닝 기술을 안드로이드, iOS와 같은 모바일 기기에서 사용할 수 있게 해주는 라이브러리이다.
대표적인 라이브러리로는 바코드 스캐닝, 얼굴 인식, 텍스트 인식, 포즈 인식, 언어 감지 등이 있다.
구글 ML 키트 홈페이지 : https://developers.google.com/ml-kit?hl=ko
4. Room 지속성 라이브러리
Room 지속성 라이브러리를 사용하면 스마트폰 내장 데이터베이스에 데이터를 쉽게 저장할 수 있다.
예전에는 로컬 데이터베이스로 SQLite를 사용했는데, 이 SQLite에 추상화 계층을 추가한 것이 Room 지속성 라이브러리이다.
Room은 엔티티, 데이터 접근 객체(DAO), 룸 데이터베이스로 구성된다.
5. RecyclerView (리사이클러뷰)
기본 ListView에 성능과 유연성을 더한 것이 RecyclerView이다.
뷰를 재활용하기 때문에 성능이 향상되고, 휴대폰 전력 소비를 줄이며, 반응성이 높아졌다고 한다.
RecyclerView는 어댑터와 레이아웃 매니저로 구성되어 있다.
1) 어댑터는 아이템뷰를 생성하고, 데이터를 바인딩해준다.
바인딩은 아이템뷰에 알맞은 데이터를 순서대로 넣어주는 것을 의미한다.
2) 레이아웃 매니저는 어댑터에 생성한 아이템뷰의 배치를 결정한다.
Linear / Grid / StaggeredGrid (지그재그형식의 격자) 이 3종류가 있다.
6. Retrofit 라이브러리
레트로핏은 자신을 "안드로이드와 자바를 위한 Type-safe한 HTTP 클라이언트"라고 소개한다.
Request Body와 Response Body를 원하는 타입으로 안전하게 바꿔주기 때문에 type-safe하고,
네트워크 관련 스레딩, 캐싱, 에러 핸들링, Response 파싱 등등에 필요한
Boilerplate(보일러 플레이트)를 줄여주면서 읽기 편한 코드를 작성할 수 있게 도와준다고 한다.
레트로핏을 사용할 때는 반드시 3가지 요소를 구현해야 한다.
1. HTTP 메서드들을 정의한 인터페이스
2. 레트로핏 클라이언트 객체를 생성하는 레트로핏 클래스
3. JSON 데이터를 담을 데이터 클래스
7. 11장에서 GeoCoder를 사용할 때 geocoder.getFromLocation()이 Deprecated인 문제 해결
https://www.inflearn.com/questions/911936/geocoder-getfromlocation-%EC%97%90%EB%9F%AC
그런데, 위 링크의 코드처럼 변경하고도 addresses 리스트의 첫번째 요소만 address에 저장하기 때문에
만약 첫번째 요소에 주소가 제대로 저장되어 있지 않았다면,
"thoroughfare"나, "countryName", "adminArea"에 null이 저장되고, 그대로 출력되는 문제가 발생한다.
따라서 최종 수정 코드는 다음과 같다.
/**
* 위도와 경도 정보를 LocationProvider를 이용해 가져온다.
* 위도와 경도 각각은 getLocationLatitude()와 getLocationLongitude()를 사용한다.
*/
private fun updateUI() {
locationProvider = LocationProvider(this@MainActivity)
// 위도와 경도 정보를 가져온다
val latitude : Double = locationProvider.getLocationLatitude()
val longitude : Double = locationProvider.getLocationLongitude()
if (latitude != 0.0 || longitude != 0.0) {
// 1. 현재 위치를 가져오고, UI 업데이트 (getFromLocation이 Deprecated이기 때문에 GeocodeListener 구현)
if (Build.VERSION.SDK_INT < 33) { // SDK 버전이 33보다 작다면, 그대로
// 1-1. 현재 위치 가져오기
val address = getCurrentAddress(latitude, longitude)
// 1-2. 주소가 null이 아니여야, UI 업데이트
address?.let {
binding.tvLocationTitle.text = "${it.thoroughfare}" // 예시 : 쌍문동
binding.tvLocationSubtitle.text = "${it.countryName} ${it.adminArea}"
// 예시 : 대한민국 서울특별시
}
} else { // SDK 버전이 33보다 같거나 크다면
val geocoder = Geocoder(this, Locale.getDefault())
var address : Address? = null
val geocodeListener = @RequiresApi(33) object : Geocoder.GeocodeListener {
override fun onGeocode(addresses: MutableList<Address>) {
// 주소 리스트에서 address를 하나씩 꺼낸 다음에, 처음으로 thoroughfare에 값이 있는 address로 설정한다
for (add in addresses) {
if (add.thoroughfare != null && add.thoroughfare.length > 0) {
address = add;
break;
}
}
address?.let {
binding.tvLocationTitle.text = "${it.thoroughfare}" // 예시 : 쌍문동
binding.tvLocationSubtitle.text = "${it.countryName} ${it.adminArea}"
// 예시 : 대한민국 서울특별시
}
}
override fun onError(errorMessage: String?) {
address = null
Toast.makeText(this@MainActivity,
"주소가 발견되지 않았습니다.", Toast.LENGTH_LONG).show()
}
}
geocoder.getFromLocation(latitude, longitude, 7, geocodeListener)
}
// 2. 현재 미세먼지 농도를 가져오고, UI 업데이트
getAirQualityData(latitude, longitude)
} else { // 위도, 경도 정보가 모두 없다면
Toast.makeText(this@MainActivity,
"위도, 경도 정보를 가져오지 못했습니다. 새로고침을 눌러주세요.", Toast.LENGTH_LONG).show()
}
}
그리고 SDK 버전이 33보다 작다면 그대로 getCurrentAddress() 함수를 호출하니까, 이 함수도 수정해야 한다.
fun getCurrentAddress(latitude : Double, longitude: Double) : Address? {
val geocoder = Geocoder(this, Locale.getDefault())
// Address 객체는 주소와 관련된 여러 정보를 가지고 있다.
val addresses : List<Address>?
addresses = try {
// Geocoder 객체를 이용하여, 위도와 경도로부터 리스트를 가져온다
geocoder.getFromLocation(latitude, longitude, 7)
} catch (ioException : Exception) {
Toast.makeText(this, "지오코더 서비스를 사용할 수 없습니다.", Toast.LENGTH_LONG).show()
return null
} catch (illegalArgumentException : IllegalArgumentException) {
Toast.makeText(this, "잘못된 위도와 경도입니다.", Toast.LENGTH_LONG).show()
return null
}
// 여기서부터 수정된 코드
var address : Address? = null
// 주소 리스트에서 address를 하나씩 꺼낸 다음에, 처음으로 thoroughfare에 값이 있는 address로 설정한다
if (addresses != null && addresses.size != 0) {
for (add in addresses) {
if (add.thoroughfare != null && add.thoroughfare.length > 0) {
address = add;
break;
}
}
} else { // 에러는 아니지만, 주소가 발견되지 않은 경우
Toast.makeText(this, "주소가 발견되지 않았습니다.", Toast.LENGTH_LONG).show()
return null
}
return address
}
8. 14장 패키지 이름을 example에서 변경하면, 구글 맵 API가 먹통이 되는 오류 해결
책에서는 설명이 나와있지 않아서 생각해보니 구글 맵 API를 등록할 때, "패키지 이름"과 "SHA-1 인증서 디지털 지문값"을 입력했었다. 이 부분도 수정해야 한다!
9. gitignore 간단하게 만들어주는 사이트
https://www.toptal.com/developers/gitignore
10. 구글 안드로이드 공식 출시 체크리스트
https://developer.android.com/distribute/best-practices/launch/launch-checklist?hl=ko
는 2023년 11월부터 개인 개발자들이 안드로이드 앱을 출시하는 과정이 까다로워졌다;;;
언젠가는 조건 맞춰서 하겠지만, 20달러가 아깝다...
https://support.google.com/googleplay/android-developer/answer/14151465
'안드로이드 > 도서 내용 정리' 카테고리의 다른 글
내용 정리 Part. 2 - [SNS 앱을 만들면서 배우는 안드로이드 클라이언트 개발] (0) | 2024.04.09 |
---|---|
내용 정리 Part. 1 - [SNS 앱을 만들면서 배우는 안드로이드 클라이언트 개발] (0) | 2024.04.03 |
내용 정리 - [핵심만 골라 배우는 젯팩 컴포즈] (0) | 2024.03.14 |