Android 88

Mainframer - 리모트 서버에서 빌드를 돌려보자

안드로이드 프로젝트 빌드 시간으로 고민하는 사람들이 많을 거라고 생각한다. 좋은 장비가 도움을 줄수는 있지만, 남아도는 좋은 서버가 있다면? (꽤 희망적인 가정인데) Mainframer나 Mirakle을 이용하면 SSH를 통해 리모트 머신에서 프로젝트를 빌드하고 결과를 로컬에 동기화 할 수 있다. 이것이 가능한데에는 rsync가 큰 역할을 한다. 우선 빌드서버와 SSH 연결이 가능한 상태를 가정하도록 하겠다. SSH 연결만 된다면 리모트 머신에서 딱히 준비할 건 없기때문이다. Mainframer Releases 페이지에서 최신 버전의 mainframer.sh를 다운받는다. . └── MyAndroidProject/ ├── app ├── .mainframer/ │ ├── config │ ├── ignore..

Gradle의 이해: Task

Tasks gradle :project:tasks 를 입력하면 프로젝트에서 수행 가능한 Task들을 알 수 있다. Gradle 작업의 중요한 측면은 증분성에 있다. 이는 Gradle이 이전 빌드의 결과를 재사용 할 수 있다는 것을 의미한다. 따라서 프로젝트를 빌드하고 소스 코드의 작은 부분만 변경했다면, 다시 빌드하더라도 다시 수행해야하는 Task들은 처음 빌드보다 적어진다. > Task :app:processProductionDebugGoogleServices UP-TO-DATE > Task :app:productionDebugOssDependencyTask UP-TO-DATE > Task :app:productionDebugOssLicensesTask UP-TO-DATE > Task :app:merg..

[안드로이드] Dialog Queue 구현하기

요구사항 앱 내 액션에 필요한 다이얼로그가 떠야해요. 하지만 유저가 클릭하지 않아도 서버가 푸시하면 앱의 어디서든, 언제든지 다이얼로그가 뜰 수 있어요. 튜토리얼을 할때는 튜토리얼용 다이얼로그를 제외한 모든 다이얼로그가 뜨지 않아야해요. 그리고 이 모든 다이얼로그들이 서로 꼬이지 않아야 해요. 다이얼로그를 한 두개 띄울때는 아무런 문제가 없었다. 하지만 요구사항에 따라 다이얼로그 추가되고, 이내 범벅이 되면서 다이얼로그 위에 다이얼로그가 떠버리거나 순서가 꼬여버려 좋지 않은 UX를 제공하게되는 결과를 야기했다. 아이디어 이것은 고등학교 급식 문제와 같다. 12시 종이 땡 치면 전교생이 우르르 급식을 먹으러오는 상황이다. 하지만 배식 라인(View)은 단 하나뿐! 3학년은 점심시간 중 자습시간이 있어 빨리..

[안드로이드] 순서보장 무한 페이저(Endless Pager) 만들기 with Jetpack Compose

무한 페이저를 만들때 아주 단순하게 생각하면 이렇게 만들기 쉽다. 하지만 이 경우, 초기 페이지가 내가 원하는 페이지가 되지 않는다. 실제 배열의 0번째부터 시작해야하는데, 실제 배열의 길이가 바뀌면 초기 페이지도 어떻게 될지 보장 할 수 없게 된다. val pageCount = Int.MAX_VALUE val pagerState = rememberPagerState( initialPage = Int.MAX_VALUE / 2 ) 무한 페이저는 한 두번이 아니라 나도 초기 페이지 계산하는 공식을 때려 맞추고는 했는데 빡대가리라 뭔가 수학적으로 설명을 하는게 안되서… 헤메고 있던 차, Jetpack Compose Endless Pager만들기 YouTube 강의 영상에서 아주 좋은 댓글을 발견했다. 이 방법..

Google I/O Extended Seoul 2023: Dagger Hilt로 의존성 주입하기

https://speakerdeck.com/fornewid/dagger-hiltro-yijonseong-juibhagi @네이버 웹툰 안성용님 발표자료를 글로 옮긴 것입니다. 의존성 주입이란? 의존성 주입은 하나의 객체가 다른 객체의 의존성을 제공하는 기법. 의존성 주입의 의도는 객체의 생성과 사용의 관심을 분리하는 것. // 의존성 주입 X class Car { private val engine: Engine = Engine() fun start() { engine.start() } } // 의존성 주입 예시 - 생성자에서 전달 class Car(private val engine: Engine) { fun start() { engine.start() } } // 의존성 주입 예시 - 필드 주입 clas..

[안드로이드] 회전목마(Carousel) 애니메이션 구현하기

게임에서 아이템이나 캐릭터 선택을 할때 회전 목마처럼 돌아가는 선택 애니메이션을 자주 볼 수 있는데, 이것을 안드로이드에서 구현해 볼 수 있는 기회가 생겼다. 사실 노가다를 하면 어떻게든 구현할 수 있지만, 이번에는 문제를 분석하고 쪼개보는 연습을 겸해봤다. 💡 요구사항: 3가지 종류의 상자가 있고, 이 상자들을 돌려가면서 열 상자를 선택하게 해주세요. 1. 상자 유형 데이터화 첫번째로 해야할 일은 상자를 데이터화하는거다. enum 클래스로 상자의 이미지, 가격, 이름이 담긴 LuckyBoxType을 만들어 주었다. enum을 사용한 이유는 순차적 접근이 sealed class보다 훨씬 쉽기 때문이다. enum class LuckyBoxType( val image: Int = 0, val cost: In..

[안드로이드] 특정 시간 내 중복 Request를 막는 OkHTTP Interceptor 구현하기

특정시간 안에 보낸 동일한 Request에 대해서 서버에 요청하지 않고, 이전에 받은 응답값을 그대로 내려주는 Interceptor를 구현해보았다. Response Body를 어떻게 재사용할 것인가 고민을 많이 했는데, ByteArray 형태로 읽어두고 중복된 요청일때 ResponseBody로 만들어주는 방법을 사용해보았다. 이렇게 짧은 시간안에 연속적으로 요청을하더라도, 500ms 이후에만 새로 요청을 하게된다. 개발중인 앱의 Request Method가 전부 POST이기때문에, Request body까지 읽어서 hashing을 하고있는데, 그럴 필요까지 없으신분들은 Request URL 자체를 hash 값으로 잡아도 무방할 것이다. 혹시 유용했다면 Star를~! HTML 삽입 미리보기할 수 없는 소스

구글 설문지 (Google Forms) 완료시 데이터 외부 API로 전송하기

구글 설문지를 완료했을때 보상을 주거나, 추가 정보를 처리해야 할 일이 있을 수 있다. 그래서 구글 설문지를 완료하면 외부 API로 데이터를 보내는 방법을 정리해보려한다. OAuth Scope 추가하기 먼저 더보기 메뉴에서 [스크립트 편집기]로 진입한다. 외부 API로 요청을 보내기 위해서 아래 scope에 대한 권한이 필요한데, 이것을 정의하려면 appsscript.json을 편집해야한다. "https://www.googleapis.com/auth/script.external_request" 프로젝트 설정 > 편집기에 [appsscript.json 매니페스트 파일 표시] 체크를 하면 편집기에서 appsscript.json이 생긴 것을 볼 수 있을 것이다. { "timeZone": "Asia/Seoul"..

[안드로이드] Push할 때마다 Auto-Formatting적용하기 : GitHook으로 코딩 스타일 맞추기

작업환경을 타지 않는 방법의 필요성 코딩 스타일의 일관성은 가독성, 협업에서 중요한 포인트이지만 개인적인 코딩 습관들, 빡빡한 일정들 등으로 인해 지키기 쉽지 않다. IDE에서 저장시에 코드 포맷팅을 해주는 기능들이 있기는 하지만, 작업환경마다 세팅해줘야한다는 단점이 있다. 따라서 어떤 환경에서 작업하더라도 코딩 스타일을 지켜줄 수 있는 방법이 필요했다. (이 원문을 응용하여 작성된 글입니다.) GitHook + ktlint 그것은 바로 GitHook을 이용하는 방법이다. git init을 하면 .git/hook 폴더에는 여러 GitHook 샘플들이 생긴다. 이 경로 안에 내가 Hook을 발생시키기 원하는 시점에 대한 파일을 “확장자 없이” 넣어주면 간단히 Hook 세팅을 할 수 있다. 샘플 파일들은 ...

[안드로이드] ExoPlayer 깜빡거리거나 검은 화면(Black screen)이 뜰 때

문제발생 Epoxy로 무한 반복되는 배너 캐러셀에 동영상을 적용시키는 중에, 간혹 동영상이 재생될때 검은 화면만뜨고 재생이 안되거나 깜빡이는 문제가 있었다. *하나의 ExoPlayer를 RecyclerView.Adapter에서 재활용해가면서 쓰는 사례다. 정신차리고 setPlayer() Document를 자세히 읽어보니... Player를 다른 View에 붙일때 switchTargetView()를 쓰는걸 추천한다고 되어있다. 하지만 setPlayer()를 직접 쓰고자 할 경우 이전 View에서 Player를 분리하기 위해 setPlayer(null)을 호출하기 이전에 새로운 View에 Player를 연결시켜야 한다. *switchTargetView를 직접 써보려고 했으나, 지원하지 않는 메소드였다. 해결..