- 갑자기 아래와 같은 경고 안내를 플레이 콘솔로 전달받았다.- 어떤 디바이스나 OS(특히 Android, iOS, 임베디드 환경)에서는 기본 페이지 크기가 16KB일 수 있다. 그래서 범용성을 위해 해당 앱이 여러 환경에서도 문제없이 동작할 수 있도록 접근 방식을 조정해야 한다는 것이다. - 첫 번째로 확인해 볼 만한 요소는 AGP 업그레이드다. 8.5.2 버전 이상으로 업데이트해 주어야 대응이 된다고 한다. - Tools의 AGP Upgrade Assistant를 사용하면 최신화 가능하다. - 두 번째로는 사용되는 라이브러리 조사다. 보통 Room, Coroutine, Compose 같은 자체 라이브러리에는 네이티브(. so) 코드가 포함되지 않아서 괜찮은데, 써드파티 라이브러리들은 사용하고 있을 가..
Android

- 한동안 OOM 방지를 위한 작업들을 진행했는데, 여전히 OOM Crashlytics 보고가 끊이지 않았다. - 사용자 로그 및 계정 접속 테스트를 통해 알아낸 결과, 서버로부터 대량의 데이터를 수신받고 로컬 DB에 업데이트하는 시점에 OOM이 가장 빈번하게 발생하는 것으로 파악되었다. - 현재 서버와 클라이언트는 페이징 방식으로 List 구조의 데이터를 수신받고 로컬 DB에 저장하는데, 최근에 내가 동기화 로직을 리팩터링 하면서 Retrofit Call Response Type을 페이징과 관련된 데이터들 및 중간 매핑 리스트 타입을 포함한 data class로 등록한 시점부터가 문제였다.): Calldata class GetDataWithPageResult( val datas: List, ..

- Compose에서는 이미 렌더링 된 UI를 갱신하기 위해 상태 변경이 일어날 때마다 필요한 부분들을 다시 그리는 Recomposition이라는 메커니즘을 사용한다. - 리컴포지션은 상세하게 Composition -> Layout -> Drawing 세 가지 단계를 거친다. - 리컴포지션이 발생하면 Compose는 Composition 단계부터 새롭게 시작하며, 여기서 컴포저블 노드는 UI 변경 사항을 Compose Runtime에 알리고, 업데이트된 UI가 최신 상태를 반영하도록 보장한다. - 리컴포지션이 발생하는 조건은 다음과 같다.1. 매개변수에 변경이 발생했을 때2. 상태 변경이 관찰되었을 때 - Composition의 주요 작업• @Composable 함수 실행• UI 트리 생성 및 업데이트..
- Jetpack Compose는 개발자가 상태 변경 시 UI를 어떻게 업데이트할지를 나타내는 것이 아닌, 특정 상태에서 UI가 어떻게 보여야 하는지를 설명하는 선언적 UI 프레임워크의 특성을 가지고 있다. - 이는 개발자가 뷰를 데이터의 변화에 따라 수동으로 업데이트해야 하는 명령형 접근 방식과는 차이가 있는 것이다. - 예를 들어 서버로부터 어떤 데이터가 내려왔고, 그 데이터를 UI에 반영해 주려면 UI 레벨에서는 API 호출이 완료된 시점을 체크하여 refresh() 함수를 구현해서 재호출 해야 할 수 있다. - 하지만 Compose의 경우에는 데이터 자체를 State로 관찰하여 즉시 시스템이 UI에 반영할 수 있도록 한다. 선언형 UI 특징- 상태 주도 UI : 시스템은 각 컴포넌트의 상태를 추적..
- SQLite는 SQLiteOpenHelper라는 DB 초기화 및 생성 담당자를 갖고 있다. - onCreate(), onOpen(), onUpgrade() 등의 메서드가 있는데, 여기서 onUpgrade()를 통해 마이그레이션 작업 수행이 가능하다. - 마이그레이션 단계 구분을 위해서 DB 버전을 생성해주어야 한다. 마이그레이션 시, 해당 버전 값을 +1 하는 것을 잊지 말자private static final int DATABASE_VERSION = 11;public static synchronized DBHelper getHelper(Context context) { if (instance == null) instance = new DBHelper(context); return inst..

- 자사 앱 플레이스토어 이동 링크를 웹뷰에서 클릭했는데 다음과 같은 화면이 나왔다.- 웹뷰가 intent:// 스킴을 이해하지 못해서 발생하는 문제다.- 안드로이드 WebView는 http://, https://는 기본 지원하지만, intent:// 같은 커스텀 스킴은 직접 처리해줘야 한다. - 웹뷰 클라이언트를 다음과 같이 수정해 주면 된다. URI_INTENT_SCHEME를 사용해서 대응해 주던지 아니면 외부로 플레이스토어를 열어주던지의 결정이 필요하다.webView.webViewClient = object : WebViewClient() { override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Bo..

- 개념적인 것들을 정리하는 것과 별개로 그날 하루 '개발자 활동'에 대해 무지성으로 기록하는 Dev Diary임1. 앱 데이터 복원 문제- 언제부턴가 앱을 재설치하는데, 사용자 prefs 데이터가 자동으로 복원됨 - 그로 인해 자동으로 로그인까지 진행해 버리는데, token 부분은 데이터가 존재하지 않아 계속 유저 인증 오류 발생android:allowBackup="true"- 안드로이드 자동 백업 옵션을 켜두면 구글 드라이브 기반으로 사용자 설정에 따라 앱 데이터를 복원하는데 이것이 영향을 주는 것으로 판단 - 그러나 우리 서비스는 따로 복원하고픈 prefs.xml 파일을 지정하고 있었다. 그런데도 발생.. - 추가로 확인해 보니 앱에서 사용 중인 어떤 라이브러리들이 백업 기능에 영향을 주고 있었고..
- 코틀린에서 코루틴은 CoroutineContext라는 실행 맥락 안에서 동작한다. - Context는 여러 요소(Job, Dispatcher 등)를 포함하고 있으며, 그중에서도 Dispatcher는 코루틴이 어떤 스레드에서 실행될지를 결정하는 중요한 역할을 한다. - 먼저, 코루틴의 Dispatcher에는 다음과 같은 종류가 있다.Dispatchers.Main설명: 안드로이드 메인(UI) 스레드에서 실행.용도: UI 업데이트, Toast, View 조작, LiveData/StateFlow 수집 등.주의: 긴 연산이나 I/O를 여기서 하면 ANR 발생 가능.CoroutineScope(Dispatchers.Main).launch { textView.text = "UI 업데이트" }2️⃣ Dispatche..

- ImageView에 바로 Shadow(elevation)을 적용할 수는 없는 것으로 보이고, CardView에 ImageView를 add 해서 구현해야 했다.val cardLp = FrameLayout.LayoutParams( FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER).apply { val m = (8 * resources.displayMetrics.density).toInt() setMargins(m, m, m, m)}val card = CardView(this@AddOnActivity).apply { layoutParams = cardLp ..

- WebView란? 안드로이드 앱 안에 내장된 브라우저라고 생각하면 된다. 즉, 앱 안에서 웹페이지(HTML, CSS, JavaScript)를 렌더링 하고 실행할 수 있는 View - 웹사이트를 보여줄 수도 있고, 앱 내부 기능과 연결된 하이브리드 앱 개발에도 자주 사용된다. - 안드로이드에서 애플 로그인 등. 웹뷰로 url에 접근하여 결과를 받아오는 방식이 필요할 때가 있다. - 이 글에서는 url을 웹뷰로 열고, 어떻게 그 안에서 결과 콜백을 받아오는지 확인해본다. 필자는 다이얼로그로 웹뷰를 보여주고자 한다. - 웹뷰의 데이터 전달 방식은 대략 다음과 같다. - 먼저 WebView 자체를 다이얼로그에 ContentView Set한다.) : Dialog(context) { private late..