이번 기능은 사실 이전에 생각조차 해보지 않은 기능이었다. 기존 HTTP, TCP 기반 통신에 익숙해져 있었기 때문이다. 그리고 내가 연동해야할 센서는 0으로 1바이트를 보내면 지속적으로 특정값을 형식에 맞게 보내주는 녀석이었다. 그럼 바로 코드를 공유해보도록 하겠다. private fun fetchUdpData() = CoroutineScope(Dispatchers.Default).launch { println("started fetch") val socket = DatagramSocket() val address = InetAddress.getByName(someIp.split(":")[0]) val packet = DatagramPacket( "0".toByteArray(), "0".toByteAr..
문제의 발단 최근 프로젝트에서 요즘 많이 쓰이는 ListAdapter(feat.DiffUtil)을 사용해보게 되었다. 나는 멤버변수로 MutableList를 가지고 있었고, 해당 리스트를 add, remove로 수정하고 submitList의 파라미터로 전달했다. 그런데 RecyclerView가 새로고침되지 않았다. 발생 원인 ListAdapter에게 submitList로 리스트를 전달하면 ListAdapter 내부의 AsyncListDiffer 멤버변수의 submitList를 호출한다. 해당 메소드는 멤버로 이전에 전달받은 list를 가지고 있고, 기존 멤버변수와 전달받은 파라미터의 list를 비교한다. 만약 두 리스트가 같다면 함수를 리턴한다. (여기서 같다는 의미는 메모리 주소가 같다는 것을 의미한다..
글을 쓰게 된 배경 MaterialSwitch 사용 중 track과 thumb 색상을 앱 테마에 맞춰야했다. 더 정확히 말하면 trackTint와 trackThumb를 바꿔주어야 했고 이 때 Android resource color directory에 selector를 사용해야 했다. 처음에는 위와 같이 selector를 정의했는데 trackTint가 적용되지 않은 것처럼 보였다. 당시 추측으로는 몇 가지 상태값이 빠져있어서 원하는대로 동작하지 않는다고 생각해 상태값을 모두 추가해주었는데도 변함이 없었다. 그렇게 찾게된 공식문서에서 내가 만든 selector는 충실히 본인의 역할을 하고 있었다는 사실을 깨닫게 되었다. 문제의 원인 https://developer.android.com/guide/topic..
이번에는 material 라이브러리를 사용하면서 겪었던 커서 색상 변경에 관련한 에피소드를 하나 풀어보려 한다. 일단 내가 현재 사용하는 버전은 1.9.0 버전이다. Material EditText 사용법 흔히 사용하는 EditText를 material 라이브러리에선 TextInputEditText로 대체하는데 이를 TextInputLayout으로 감싸서 사용한다. Theme 설정하기 나의 경우에는 boxStrokeColor는 xml에서 속성으로 설정이 가능했지만 cursor 색상을 설정할 수가 없었다. (물론, 코드 상으로도 말이다.) 그럼 cursor color는 어디서 바꿔? 답만 말하자면 colorControlActivated 속성의 색상을 바꿔주어야 한다. material에는 여러 속성의 색상이..
이번에는 안드로이드 UrlQuerySanitizer를 Url Query를 파싱하는데 사용하지 않을 때 생긴 문제를 다루고자 한다. 문제 발생 배경 최근 새 프로젝트를 진행 중, API 응답이 json, xml, csv와 같은 형식이 아닌 URL의 GET method 사용 시 붙어있는 Query 형식으로 body 값을 주는 녀석이 있었다. 물론 반복문을 사용해서 일일히 파싱할 수도 있었지만, Retrofit에서 json, xml 형식을 곧장 객체로 변환해주는 기능을 맛 본 이상 그 전으로 돌아가긴 싫었다. 그래서 찾다 보니 우회할 방법으로써 찾은 녀석이 UrlQuerySanitizer였다. 알고 보니 API level 1부터 유구한 역사를 가진 친구였지만 처음 들어봤다.(^^) UrlQuerySanitiz..
이번에는 저번 글과 이어지는 부분이 있는데 시스템 파일로 저장된 크래시 로그 저장하는 방법에 대해 소개해보려 한다. 필요해진 배경 며칠동안 앱을 실행시켜두고 안전성 테스트를 하던 도중이었다. 그런데 갑자기 주말이 지나서 보니 앱이 죽어있던 것이 아닌가.. 분명 어떤 이유에서인지 비정상 종료가 되었을 것인데 그 원인을 보고 싶어 검색해보게 되었는데, 안드로이드에서 크래시 로그를 파일로 저장하는 폴더가 있다고 해서 그 내부를 살펴보게 되었다. 목표물 안드로이드 시스템 내부에 tombstones 라는 폴더가 존재하는데 진짜 언어 그대로 죽은 이유를 적어둔 백트레이스를 가진 폴더이다. 내부를 확인해보니 "tombstone 0"과 같은 형식으로 tombstone에 숫자를 더한 형식의 이름을 가진 파일들이 있었고,..
오늘은 ADB(Android Debug Bridge)로 스크린샷을 찍고 저장하는 방법에 대해 공유해보겠다. 필요해진 배경 이 기능이 필요했던 이유를 설명하자면 Android TV 같은 녀석들은 Android Studio가 설치된 컴퓨터와 USB 연결을 통해 실행할 수 없는 경우가 있다. 그렇게 되면 같은 Wifi 망에 접속해 원격 ADB로 실행해야 했다. 또한 Android TV 같은 경우 일반 스마트폰처럼 전원버튼과 음량버튼으로 스크린샷을 찍을 수 없기 때문에 이 글의 주제인 ADB로 스크린샷 저장하는 방법을 찾아보게 되었다. 방법 일단 ADB로 디바이스가 연결되어있다는 전제 하에 글을 작성해보도록 하겠다. adb shell screencap -p /sdcard/screenshot.png 위 명령어를 ..
TextClock은 생각해보면 되게 흔한 기능인데 텍스트로 시간을 보여주기 위한 방법을 고민하다 찾게된 클래스이다. 놀랍게도 API 17에서 추가된 꽤 오래된 클래스였다. 형식 지정하기(format) TextClock으로 시간을 보여줄 때 형식을 지정할 수 있다. 12시간제 혹은 24시간제로 말이다. 게다가 SimpleDateFormat에서 사용하던 형식과 같이 사용할 수 있다. 나의 경우, 특정 단말기에서 시간 형식 지정이 되지 않았다. 그래서 이리저리 검색하던 결과 방법을 찾았다. 바로 12시간제 혹은 24시간제 중 하나를 null로 처리해주는 것이다. // 12시간제를 사용하는 경우 textClock.format12Hour = "HH:mm:ss" textClock.format24Hour = null..
먼저 내가 경험한 버그는 단순히 Android 14버전에서 모두 나오는 현상이 아님을 알린다. 왜냐하면, Android 14버전의 구글 픽셀폰에서는 이 버그가 발생하지 않기 때문이다. 어떤 버그인가? setTypeface 메소드가 작동하지 않는 버그이다. setTypeface 메소드는 공식 사이트의 링크를 첨부한다. https://developer.android.com/reference/android/widget/TextView#setTypeface(android.graphics.Typeface) TextView | Android Developers android.inputmethodservice developer.android.com Android 14, One UI 6.0의 삼성 디바이스에서 발생하는..
모드 리스트 RESIZE_MODE_FIT = 0 RESIZE_MODE_FIXED_WIDTH = 1 RESIZE_MODE_FIXED_HEIGHT = 2 RESIZE_MODE_FILL = 3 RESIZE_MODE_ZOOM = 4 모드 설명 RESIZE_MODE_FIT의 경우, 설정된 비율에 맞춰 width 혹은 height를 줄인다. 이 모드는 기본 값이다. AspectRatioFrameLayout 클래스의 생성자에서 resizeMode 멤버 변수 값을 0으로 설정하기 때문에 초기값은 0이다. RESIZE_MODE_FIXED_WIDTH의 경우, width를 고정하고 height를 늘이거나 줄여 설정된 비율을 맞춘다. RESIZE_MODE_FIXED_HEIGHT의 경우, height를 고정하고 width를 늘..