사용자의 디바이스를 식별하거나 정보 파악을 위해서 id 또는 기기명, OS 버전 등의 확인이 필요한 경우가 있다. 이러한 정보를 Build Class에서 가져올 수 있다. GPT를 통해 확인한 Build Class에 담긴 정보는 아래와 같다. 1. Build.VERSION: Android 운영 체제의 버전 정보를 제공합니다. 예를 들어, Build.VERSION.SDK_INT를 통해 API 레벨(안드로이드 버전 코드)을 얻을 수 있습니다. 2. Build.VERSION_CODES: Android API 레벨을 상수로 정의한 클래스입니다. 코드에서 각 버전에 대한 조건을 확인할 때 사용됩니다. 3. Build.MODEL: 기기의 모델 이름을 제공합니다. 4. Build.MANUFACTURER: 제조사 정보..
전체 글
Crashlytics 살피던 중, 아래와 같은 Error Report를 발견했다. Fatal Exception: java.lang.IllegalArgumentException: View=DecorView@b5f5db7[TestActivity] not attached to window manager at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:657) at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:564) at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.j..

사용자에게 좀 더 신속한 데이터 갱신 처리를 제공하기 위해 백그라운드 동기화 처리를 구현하기로 했다. Jetpack에서 지원하는 WorkManager를 사용해 보기로 했다. 먼저 build.gradle에 다음 설정을 추가해준다. implementation "androidx.work:work-runtime-ktx:2.8.1" 그리고 작업 정의를 위한 Worker 클래스를 생성한다. class SyncWorker(val context: Context, params: WorkerParameters) : Worker(context, params) { override fun doWork(): Result { syncAndCallApi() return Result.success() } } doWork 내에서 비동기..
사용자가 프로필 사진을 변경하기 위해 갤러리에서 사진을 선택해 가져오는 로직이 노후화되어 전체적으로 재구성했다. registerForActivityResult를 활용했다. https://developer.android.com/training/basics/intents/result?hl=ko 활동에서 결과 가져오기 | Android 개발자 | Android Developers 활동에서 결과 가져오기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 앱 내에서든 다른 앱에서든 다른 활동을 시작하는 것은 단방향 작업이 아니어도 됩 developer.android.com 먼저 갤러리로 진입할 수 있는 로직을 작성한다. val permissions = if (Build.VERSION...
Android에서 비동기 처리를 위해 많이 사용되던 AsyncTask가 deprecated 되었는데, 프로젝트에 아직도 사용되는 부분들이 존재하여 Coroutine을 활용하여 비동기 처리하도록 수정을 진행했다. public class CheckApiTask extends AsyncTask { @Override protected void onPreExecute() { super.onPreExecute(); //Task 실행 전 UI 작업 } @Override protected Boolean doInBackground(String[] params) { try { //Background 작업 } catch (Exception e) { e.printStackTrace(); } return false; } @Ov..

안드로이드에서는 위치, 외부 저장소 등의 접근을 위해 사용자에게 시스템 다이얼로그 직접 접근 권한 허가를 받아야 한다. 최근 Android 13부터는 알람까지 접근 권한을 받아야 활성화되는 것으로 변경되었다. 하지만 사용자들이 매번 허용한다고 보장할 수 없다.. 접근 권한 허가 요청을 2번 이상 거부 당하거나 과거 OS 버전처럼 다시 보지 않음을 체크하여 거부할 경우, 사용자가 특정 기능 사용을 영구적으로 제한받을 수 있다. 실제로 위와 같은 이유로 특정 기능이 안 된다는 사용자 리포트가 들어와 재설치를 안내하고, 권한 허가를 요청드린 경우가 있었는데, 이런 비용 낭비 시나리오를 대응하기 위해 영구적으로 권한 접근을 거절당하더라도 안내 Dialog를 통해 사용자가 직접 권한 설정을 변경할 수 있는 로직을..

안드로이드 앱은 난독화 처리를 하지 않으면 디컴파일러로 소스 코드 내용이 그대로 유출될 수 있다. 예를 들어 특정 라이브러리들의 소스 코드를 보면 난독화 처리가 적용되어 있는 것을 확인할 수 있다. 안드로이드에서는 이런 난독화 처리를 위해 Proguard라는 기능을 제공하고 있다. 운영 중인 서비스에 아직 적용이 되지 않아 뒤늦게 적용을 진행했다.. (프로가드 적용이 필요하거나 필요하지 않은 부분에 대한 조사가 시간이 걸렸다. 앱 개발 시 초기부터 신경 쓰자..) Proguard의 주요 기능은 다음과 같다. 코드 축소 (Shrinking): 사용되지 않는 코드와 리소스를 제거하여 APK 크기를 줄입니다. 이는 애플리케이션을 더 가볍게 만들고 다운로드 및 설치 시간을 단축하는 데 도움이 됩니다. 코드 최적..

구글 플레이 스토어에 앱을 업데이트하는 중 다음과 같은 경고가 표시되기 시작했다. 해당 경고가 가리키는 코드를 확인해 보니 압축 파일 처리에 대한 함수였다. fun unZip(zipFile: File, destFolder: File): List { val result = ArrayList() ZipFile(zipFile).use { zip -> zip.entries().asSequence().forEach { entry -> if (entry.isDirectory) { File(destFolder, entry.name).mkdirs() } else { zip.getInputStream(entry).use { input -> val file = File(destFolder, entry.name) file...

안드로이드에서 뒤로 가기 기능 구현 시, 사용되던 onBackPressed 메서드가 deprecated 되었다. 대신, onBackPressedCallback으로 새롭게 탄생했다. https://developer.android.com/reference/androidx/activity/OnBackPressedCallback OnBackPressedCallback | Android Developers androidx.appsearch.builtintypes.properties developer.android.com 먼저 Callback을 선언한다. private val onBackPressedCallback = object : OnBackPressedCallback(true) { override fun ha..

안드로이드에서 Deivce의 설정을 통해 실제 시간과 다른 시간이 설정되었을 경우, 네트워크 통신에 실패하거나 각종 서비스 진입을 거부당하는 경우가 발생한다. 사용자 측면과 개발자의 측면에서 모두 이런 혼란을 방지하기 위해 실제 시간과 Device 시간이 동일한지 비교할 수 있는 방법이 필요했다. 그래서 'NTP 서버'를 활용한 비교 로직을 구성해본다. NTP : Network Time Protocol의 약자로 Network 상에 연결된 장비와 장비 간에 시간 정보를 동기화하기 위한 프로토콜을 말하며 NTP 서버와 클라이언트 세팅을 통해 시간을 동기화 먼저 아래 라이브러리를 import 한다. implementation 'commons-net:commons-net:3.6' commons-net은 Apac..