안드로이드 앱개발

    Architecture Components(MVVM 패턴)

    Architecture Components란? Android architecture components are a collection of libraries that help you design robust, testable, and maintainable apps. 유지보수를 쉽게하고 테스트 가능한 프로그램을 만들기위해 도움을주는 안드로이드 컴포넌트다. Room 라이브러리 Room은 SQLite에 대한 추상화 레이어를 제공하여 원활한 데이터베이스 액세스를 지원하는 동시에 SQLite를 완벽히 활용한다. SQLite를 API 직접사용하는것이 번거롭고 구조화되어있지도 않으니 Room을 사용한다. SQLite를 API 직접사용하면 구조를 잘 잡지 않는이상 액티비티나 프래그먼트의 코드가 복잡해지고 뷰와 모델 ..

    안드로이드 서비스

    안드로이드 서비스

    서비스란? 앱이 내려가있어도 실행할 프로그램. 서비스는 실행되면 명시적으로 멈춰줘야한다. 안그러면 계속 돌아간다. (바인드 서비스가 아닌이상) 포그라운드 서비스, 백그라운드 서비스, 바인드 서비스 포그라운드 서비스 : 푸시알림 같은 것이나 뮤직앱의 뮤직플레이어. 유저에게 보이는것. 백그라운드 서비스 : 게임을 내려도 계속 돌아간다든가 하는것. 유저에게 안보이는것. 바인드 서비스 : 어플리케이션 컴포넌트가 서비스와 바인딩되어 서비스를 이용할때의 서비스. 포그라운드나 백그라운드 서비스는 동시에 바인드 서비스일 수 있다. 여기서 바인딩이란, 어플리케이션 컴포넌트가 특정 서비스를 사용한다는 뜻이다. (서비스와 컴포넌트가 묶였다고 표현한다) * 바인드 서비스의 경우, 바인드된 컴포넌트들이 모두 언바인드되면 자동으..

    카메라로 사진찍기

    먼저 코드를 보고 하나하나 설명하겠다. fun isExternalStorageWritable(): Boolean { return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED } private fun dispatchTakePictureIntent() { if(!MyFileHelper.isExternalStorageWritable()) Toast.makeText(this, "저장공간이 부족해서 카메라앱을 실행시킬 수 없습니다.", Toast.LENGTH_SHORT).show() Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent -> // Ensure that there..

    파일입출력2 : 저장소 (Android Studio Internal/External Storage)

    파일입출력2 : 저장소 (Android Studio Internal/External Storage)

    지난 시간에는 파일 입출력에 대해서 알아보았다. 이번에는 좀 더 자세하게 들여다보자. //userInfo라는 객체를 json 형태로 바꾼다. val fileContents = Gson().toJson(userInfo) //휴대폰의 내부저장소 중 캐시저장소에 파일을 만든다. val file = File(context.cacheDir, "account_" + userInfo.email) //파일에 준비한 json을 쓴다. file.writeText(fileContents) context.cacheDir은 주석에서 나와있듯이 내부저장소의 캐시저장소를 의미한다. 그럼 내부저장소는 뭘까? 잠시 공식문서의 설명을 보자. 내부 저장소 디렉터리: 이 디렉터리에는 영구 파일을 저장하는 전용 위치와 캐시 데이터를 저장하는..

    파일입출력 1 : 쓰고 읽기 (File I/O in Kotlin)

    코틀린의 파일 입출력은 매우간단하다. 우선 데이터를 파일로 쓸때는 JSON을 이용하면 간편하니 gson 라이브러리를 쓰자. //userInfo라는 객체를 json 형태로 바꾼다. val fileContents = Gson().toJson(userInfo) //휴대폰의 내부저장소 중 캐시저장소에 파일을 만든다. val file = File(context.cacheDir, "account_" + userInfo.email) //파일에 준비한 json을 쓴다. file.writeText(fileContents) 파일을 쓰는건 이렇게만 해도 된다. writeText는 내부적으로 FileOutputStream을 연다음, 인자로 넘긴 String을 파일에 쓴다. 그런 다음 닫는다. (사실 .use를 쓰기때문에 수동..

    AdMob nativeAd 를 RecyclerView를 활용해 표시하기 (nativeAd with RecyclerView)

    AdMob nativeAd 를 RecyclerView를 활용해 표시하기 (nativeAd with RecyclerView)

    필자는 틴더 앱의 스와이프와 비슷한 기능을 구현했다. 광고 또한 스와이프로 넘기면서 볼 수 있게 만들고 싶었다. 그래서 선택한것이 native ad이다. native ad는 전면광고나 배너광고와는 달리 광고의 데이터만 받고 보여주는 레이아웃은 커스텀하게 짤 수 있다. 먼저 광고 스와이프를 구현하기 위해서는 카드(스와이프하는 객체)들 사이에 광고를 넣어야했다. 게다가 카드와 광고는 레이아웃을 다르게하고 싶었다. 그러기 위해서 두가지 타입의 뷰홀더를 만들었다. class CardViewHolder( val layout: View, val swipImg: ImageView, val tv_swipe_title: TextView, val tv_swipe_userName: TextView, val tv_swipe_..

    volley로 이미지 업로드 (volley multipart request)

    volley로 이미지를 업로드하기 위해서는 mime-type이 multipart인 리퀘스트를 보내야한다. 그러려면 volley를 업그레이드하기 위해 돈을내던가, 직접구현해야한다. * 구현한 코드는 맨 밑에 첨부합니다. A HTTP multipart request is a HTTP request that HTTP clients construct to send files and data over to a HTTP Server. It is commonly used by browsers and HTTP clients to upload files to the server. As the official specification says, "one or more different sets of data are com..

    라이브러리는 이해하고 사용하자.

    라이브러리는 이해하고 사용하자.

    틴더처럼 스와이프로 게시물을 탐색하는 앱을 만들고있다. 이는 swipeCardView라는 어댑터뷰를 통해 구현되고, 그 어댑터뷰에 연결할 어댑터는 ArrayAdapter를 상속받는다. 그렇게 잘 개발하다가 스와이프시에 카드뷰를 생성하는데 버벅거리는 이슈가 발생했다. 처음에는 카드에 들어갈 사진을 서버로 http요청하는게 잦아서 그런 줄 알고, 한번 요청할때 좀더 많은양의 데이터를 받아놓는 방식으로 최적화했는데 그래도 여전히 이슈가 해결되지 않았다. 그래서 나는 호출스택을 타고들어갔다. 그리고 라이브러리의 어댑터뷰가 ArrayAdapter의 getView의 convertView를 아예 null로 하드코딩해서 넣고있는걸 발견했다. 도대체 왜 이렇게 만들었는지 모르겠다. 이말은 어댑터의 최대이점인 ‘뷰를 재활..