[Android] 안드로이드 앱 프로그래밍


1. 레이아웃

  • 화면 배치를 도와줌
  • Activity의 onCreate() 메소드 안에 setContentView(레이아웃 이름)으로 화면에 표시

제약 레이아웃 (ConstraintLayout)

  • 제약 조건(Constraint) 기반 모델
  • 제약 조건을 사용해 화면 구성
  • 디폴트 레이아웃

리니어 레이아웃 (LinearLayout)

  • 박스(Box) 모델
  • 한 쪽 방향(Horizontal, Vertical)으로 차례대로 뷰를 추가하며 화면 구성
  • 뷰가 차지할 수 있는 사각형 영역을 할당

상대 레이아웃 (RelativeLayout)

  • 규칙(Rule) 기반 모델
  • 부모 컨테이너나 다른 뷰와의 상대적 위치로 화면을 구성
  • 제약 레이아웃을 사용하게 되면서 상대 레이아웃은 권장하지 않음

테이블 레이아웃 (TableLayout)

  • 격자(Grid) 모델
  • 격자 모양의 배열을 사용하여 화면 구성
  • HTML에서 많이 사용하는 정렬 방식과 유사하지만 많이 사용하지는 않음

프레임 레이아웃 (FrameLayout)

  • 싱글(Single) 모델
  • 가장 상위에 있는 하나의 뷰 또는 뷰그룹만 보여주는 방법
  • 여러 개의 뷰가 들어가면 중첩하여 쌓게 됨
  • 가장 단순하지만 여러 개의 뷰를 중첩한 후 각 뷰를 전환하여 보여주는 방식으로 자주 사용
  • visibility 속성으로 특정 뷰를 보이거나 보이지 않게 하여 화면이 전환되는 효과를 만듬

스크롤 뷰 (ScrollView)

  • 어떤 뷰의 내용물이 넘치면 스크롤을 만들 수 있게 도와줌

2. 기본 위젯과 드로어블

  • 기본 위젯: 버튼, 텍스트뷰, 에디트텍스트, 이미지뷰

텍스트뷰 (TextView)

  • 화면에서 글자를 보여주는 역할

    속성

  • text: 텍스트뷰의 문자열을 설정
  • textColor: 문자열의 색상, #AARRGGBB
  • textSize: 문자열의 크기, dp, sp, px(크기의 단위)
  • textStyle: 문자열의 스타일 속성, normal, bold, italic
  • typeFace: 문자열의 폰트, normal, sans, serif, monospace
  • maxLines: 텍스트뷰에서 표시하는 문자열의 최대 줄 수

버튼 (Button)

  • 사용자가 클릭하면 클릭에 대한 반응을 하는 위젯
  • 다양한 유형의 버튼 제공(체크 박스, 라디오 버튼 등)

에디트텍스트 (EditText)

  • 입력상자의 역할, 사용자에게 값을 입력받을 때 사용
  • hint: 기본 안내글
  • inputType: 입력되는 글자의 유형 정의

이미지뷰(ImageView)와 이미지 버튼

  • 이미지를 화면에 표시할 때 사용
  • 두 위젯의 차이점은 버튼처럼 사용 유무
  • @drawable/이미지 파일명

    속성

  • src: 원본 이미지
  • maxWidth, maxHeight: 이미지가 표시되는 최대 폭, 높이. 설정하지 않을 시 원본 이미지가 그대로 표시
  • tint: 이미지뷰에 보이는 이미지의 색상 설정
  • scaleType: 이미지뷰의 크기에 맞게 원본 이미지의 크기를 자동으로 늘리거나 줄여서 보여줄 때 사용

    해상도 설정

  • 초고해상도 /app/res/drawable-xhdpi
  • 고해상도 /app/res/drawable-hdpi
  • 중간 해상도 /app/res/drawble-mdpi
  • 저해상도 /app/res/drawable-ldpi
  • /app/res/drawable에 이미지를 넣으면 일반적으로 사용되는 이미지로 인식함
  • 위 폴더를 직접 생성 후 넣으면 해상도에 맞게 자동 적용됨

드로어블

  • 뷰에 설정할 수 있는 객체
  • 그 위에 그래픽을 그릴 수 있음
  • 비트맵 드로어블(BitmapDrawable), 상태 드로어블(StateListDrawable), 전환 드로어블(TransitionDrawable), 셰이프 드로어블(ShapeDrawable), 인셋 드로어블(InsetDrawable), 클립 드로어블(ClipDrawable), 스케일 드로어블(ScaleDrawable)

이벤트 처리

  • 위임 모델(Delegation Model): 화면에서 발생하는 이벤트를 버튼과 같은 위젯 객체에 전달한 후 그 이후의 처리 과정을 버튼에 위임
  • 위임 모델은 각각의 이벤트를 처리할 수 있는 리스너(Listner) 인터페이스를 등록할 수 있도록 함

    터치 이벤트

  • 화면을 손가락으로 누를 때 발생하는 이벤트

    키 이벤트

  • 키패드나 하드웨어 버튼을 누를 때 발생하는 이벤트

    제스처 이벤트

  • 터치 이벤트 중에서 스크롤과 같이 일정 패턴으로 구분되는 이벤트

    포커스

  • 뷰마다 순서대로 주어지는 포커스

    화면 방향 변경

  • 화면의 방향이 가로와 세로로 바뀜에 따라 발생하는 이벤트
  • 단말 방향이 바뀌었을 때 세로 방향과 가로 XML 레이아웃을 따로 만들 필요가 있음
  • /res/에 layout-land 리소스 폴더를 추가. 이 이름으로 된 폴더는 앱을 실행했을 때 단말에 의해 자동으로 확인된 후 단말을 가로 방향으로 돌리면 이 폴더 안에 들어있는 레이아웃 파일을 우선적으로 적용

토스트 (Toast)

  • 간단한 메시지를 잠깐 보여주었다가 없어지는 뷰
  • 앱 위에 떠있는 뷰
  • 앱이 화면에서 사라지더라도 필요한 메시지가 그대로 표시되므로 앱의 상태와 관계없이 보여줄 수 있다는 장점이 존재

스낵바 (Snackbar)

  • 외부 라이브러리로 추가되었기 때문에 dependency에 Design 라이브러리를 추가해야함
  • 간단한 메시지를 보여줄 때 사용

대화상자 (AlertDialog)

  • 사용자에게 확인을 받거나 선택하게 할 때 사용
  • 보통 알림 대화상자는 사용자의 입력을 받기보다는 일방적으로 메시지를 전달하는 역할을 하며, ‘예’, ‘아니오’와 같은 전형적인 응답을 처리

프로그레스바 (ProgressBar)

  • 어떤 일의 진행 상태를 표시하거나 작업이 진행 중임을 사용자에게 알려줌
  • 막대, 원 모양이 대표적

3. 화면 전환

레이아웃 인플레이션

  • 실제 앱을 실행하면 XML 레이아웃의 내용이 메모리에 객체화되고, 객체화된 XML 레이아웃을 소스 파일에서 사용
  • 인플레이션 (Inflation): XMl 레이아웃의 내용이 메모리에 객체화되는 과정
  • 레이아웃 객체화 과정은 앱이 실행될 때(런타임) 레이아웃 XML 파일에 정의된 내용들이 메모리에 객체화되기 때문에 매우 중요
  • setContentView() 메소드는 화면에 나타낼 뷰를 지정하거나 레이아웃 내용을 메모리에 객체화하는 두 가지 역할을 수행
  • setContentView()는 화면 전체를 설정하는 역할만을 수행하기 때문에 부분 화면(부분 레이아웃)을 메모리에 객체화 할 수는 없음. 이를 위해서는 인플레이터를 사용해야함(LayoutInflater)

화면 간 전환

  • startActivity(): 액티비티를 소스코드에서 띄울 때 사용
  • startActivityForResult(): 띄웠던 액티비티로부터 다시 원래의 액티비티로 돌아오면서 응답을 받아 처리할 때 사용, setResult()로 응답을 보냄

    안드로이드 앱을 구성하는 네 가지 구성 요소

  • 액티비티(Activity), 서비스(Service), 브로드캐스트 수신자(Broadcast Receiver), 내용 제공자(Content Provider)
  • 위 네 가지 요소들은 앱을 만들어 단말에 설치했을 때 안드로이드 시스템이 이 요소에 대한 정보를 요구하기 때문에 중요
  • Android-Manifest.xml 파일에 그 정보들을 담고 있음. 새 액티비티에 대한 태그를 매니페스트에 추가하지 않으면 새 액티비티를 화면에 보여줄 수 없음

인텐트

  • 다른 액티비티를 띄우거나 기능을 동작시키기 위한 수단으로 사용
  • 무언가 작업을 수행하기 위해 사용되는 일종의 명령 또는 데이터를 전달하는 데 사용
  • 액션(Action, 수행할 기능)과 데이터(data, 액션이 수행될 대상의 데이터)로 구성

    명시적 인텐트 (Explicit Intent)

  • 인텐트에 클래스 객체나 컴포넌트 이름을 지정하여 호출할 대상을 확실히 알 수 있는 경우

    암시적 인텐트 (Implicit Intent)

  • 액션과 데이터를 지정하긴 했지만 호출할 대상이 달라질 수 있는 경우
  • 액션과 데이터 이외에도 여러가지 속성을 가지고 있음
  • 범주 (Category): 액션이 실행되는 데 필요한 추가적인 정보를 제공
  • 타입 (Type): 인텐트에 들어가는 데이터의 MIME 타입을 명시적으로 지정
  • 컴포넌트 (Component): 인텐트에 사용될 컴포넌트 클래스 이름으 명시적으로 지정
  • 부가 데이터 (Extra Data)

플래그

  • 액티비티를 여러 번 호출하면 동일한 액티비티가 메모리에 여러 개 만들어지게 되는데, 이 중복된 액티비티를 띄우지 않도록 조정하는 역할

    액티비티 스택 (Activity Stack)

  • 액티비티는 액티비티 매니저(Activity Manager)라는 객체에 의해 액티비티 스택으로 관리됨
  • 이 스택은 액티비티를 쌓아두었다가 가장 상위에 있던 액티비티가 없어지면 이전 액티비티가 다시 화면에 보이게 함
  • 만약 동일한 액티비티가 여러 개 스택에 들어가서 동시에 데이터를 접근하거나 리소스를 사용하는 문제가 발생 가능

    FLAG_ACTIVITY_SINGLE_TOP

  • 액티비티를 생성할 때 이미 생성된 액티비티가 있으면 그 액티비티를 그대로 사용
  • 기존에 만든 동일한 액티비티를 사용
  • 이미 만들어져있는 액티비티를 다시 띄울 때는 onCreate() 메소드가 실행되지 않으므로 onNewIntent() 메소드를 재정의하여 인텐트를 처리

    FLAG_ACTIVITY_NO_HISTORY

  • 처음 이후에 실행된 액티비티는 액티비티 스택에 추가되지 않음
  • 해당 플래그를 가진 액티비티가 다른 액티비티를 호출하고, 호출된 액티비티가 끝난 후에는 다시 플래그 가진 액티비티를 실행하지 않음

    FLAG_ACTIVITY_CLEAR_TOP

  • 이 액티비티 위에 있는 다른 액티비티를 모두 종료시키게 됨
  • 홈 화면과 같이 다른 액티비티보다 항상 우선하는 액티비티를 만들 때 사용

    부가 데이터 (Extra data)

  • 데이터를 전달할 때에는 Intent안의 번들(Bundle, 해시테이블과 유사) 객체에 데이터를 넣고(putExtra()) 빼서(get~Extra()) 사용
  • 번들 안에 부가 데이터를 넣을 때는 키(Key)와 값(Value)을 쌍으로 만들어 넣음
  • 전달하고 싶은 데이터가 기본 자료형이 아니라 객체(Obejct) 자료형일 때는 객체 자체를 전달할 수 없기 때문에 바이트 배열로 변환하거나 Serializable 인터페이스(안드로이드는 Parcelable을 권장)를 구현하는 객체를 만들어 직렬화한 다음 전달

태스크 (Task)

  • 다른 앱과 흐름 관리
  • 태스크를 이용하면 프로세스처럼 독립적인 실행 단위와 상관없이 어떤 화면들이 같이 동작해야 하는지 흐름을 관리할 수 있음

SharedPreferences

  • 데이터를 간단하게 저장하고 싶을 때 사용

액티비티 수명주기 (Life Cycle)

  • 액티비티는 여러 과정의 상태 정보를 갖고 있으며, 이런 상태 정보는 시스템이 관리하면서 각각의 상태에 해당하는 메소드를 자동으로 호출
  • [새로운 액티비티] -(onCreate(), onStart(), onResume())-> [실행] -(onPuase())-> <-(onResume())- [일시 정지] -(onStop()) -> [중지] -(onDestroy()) -> [소멸]
  • [중지] -(onRestart(), onStart(), onResume()) -> [실행]
  • onCreate->onStart->onResume->onPause->onStop->onDestroy

    onCreate()

  • 액티비티가 처음 만들어졌을 때 호출
  • 화면에 보이는 뷰들의 일반적인 상태를 설정하는 부분
  • 이전 상태가 저장되어 있는 경우에는 번들 객체를 참조하여 이전 상태 복원 가능
  • 이 메소드 다음에는 항상 onStart()가 호출됨

    onStart()

  • 액티비티가 화면에 보이기 바로 전에 호출됨
  • 액티비티가 화면 상에 보이면 이 메소드 다음에 onResume() 메소드가 호출됨
  • 액티비티가 화면에서 가려지게 되면 이 메소드 다음에 onStop() 메소드가 호출됨

    onResume()

  • 액티비티가 사용자와 상호작용하기 바로 전에 호출됨

    onRestart()

  • 액티비티가 중지된 이후에 호출되는 메소드
  • 다시 시작되기 바로 전에 호출됨
  • 이 메소드 다음에는 항상 onStart() 메소드가 호출됨

    onPause()

  • 또 다른 액티비티를 시작하려고 할 때 호출됨
  • 저장되지 않은 데이터를 저장소에 저장하거나 애니메이션 중인 작업을 중지하는 등의 기능을 수행
  • 이 메소드가 리턴되기 전에는 다음 액티비티가 시작될 수 없으므로 이 작업은 매우 빨리 수행된 후 리턴되어야 함
  • 액티비티가 이 상태에 들어가면 시스템은 액티비티를 강제 종료할 수 있음

    onStop()

  • 액티비티가 사용자에게 더 이상 보이지 않을 때 호출됨
  • 액티비티가 소멸되거나 또 다른 액티비티가 화면을 가릴 때 호출됨
  • 액티비티가 이 상태에 들어가면 시스템은 액티비티를 강제 종료할 수 있음

    onDestroy()

  • 액티비티가 소멸되어 없어지기 전에 호출됨
  • 액티비티가 받는 마지막 호출
  • 액티비티가 앱에 의해 종료되거나(finish()), 시스템이 강제로 종료시키는 경우에 호출될 수 있음
  • 액티비티가 이 상테에 들어가면 시스템은 액티비티를 강제 종료할 수 있음



  • onSaveInstanceState() 메소드의 파라미터로 전달되는 번들 객체를 이용해 데이터를 저장하면 onCreate()나 onRestoreInstanceState() 메소드로 저장했던 데이터가 전달됨
  • 이 방식을 사용하면 앱이 강제 종료되거나 비정상 종료된 이후에 앱이 재실행되었을 때도 그 상태 그대로 보일 수 있도록 만들어줌

4. 프래그먼트

프래그먼트 (Fragment)

  • 하나의 화면을 여러 부분으로 나눠서 보여주거나 각각의 부분 화면 단위로 바꿔서 보여주고 싶을 때 사용
  • 화면의 일부분을 다른 화면으로 구성하고 싶을 때 사용
  • 분할된 화면들의 상태를 관리하는 것이 목적
  • 부분 화면
  • 액티비티가 독립적으로 동작하는 방식을 본떠 만듬
  • 분할된 화면들을 독립적으로 구성하기 위해 사용
  • 분할된 화면들의 상태를 관리하기 위해 사용
  • 항상 액티비티 위에 올라가 있어야 함
  • 프래그먼트가 제대로 동작하는 시점은 프래그먼트가 메모리에 만들어진 시점이 아니라 액티비티에 올라가는 시점
  • 프래그먼트와 액티비티가 연결되어야 초기화될 수 있음
  • 프래그먼트 객체가 new 연산자로 만들어졌더라도 액티비티 위에 올라가지 전까지는 프래그먼트로 동작하지 않음
  • 액티비티의 onCreate()에서 getSupportFragmentManger().beginTransaction().add(fragment).commit()으로 액티비티에 추가된 후 프래그먼트 동작을 시켜야 함
  • 뷰 특성: 뷰그룹에 추가되거나 레이아웃의 일부가 될 수 있음. 뷰에서 상속받은 것은 아니며 뷰를 담고 있는 일종의 틀
  • 액티비티 특성: 액티비티처럼 수명주기(Lifecycle)를 가지고 있음. 건텍스트 객체는 아니며 라이프사이클은 액티비티에 종속됨

    onAttach(Activity)

  • 프래그먼트가 액티비티와 연결될 때 호출
  • 먼저 onAttach()가 호출되어 액티비티에 프래그먼트가 추기되고 그 다음에 onCreate()가 호출
  • 액티비티를 위해 설정해야 하는 정보들을 처리해야 함

    onCreate(Bundle)

  • 프래그먼트가 초기화될 때 호출
  • new 연산자를 이용해 새로운 프래그먼트 객체를 만드는 시점이 아님에 주의

    onCreateView(LayoutInflator, ViewGroup, Bundle)

  • 프래그먼트와 관련되는 뷰 계층을 만들어서 리턴

    onActivityCreated(Bundle)

  • 프래그먼트와 연결된 액티비티가 onCreate() 메소드의 작업을 완료했을 때 호출

    onStart()

  • 프래그먼트와 연결된 액티비티가 onStart()되어 사용자에게 프래그먼트가 보일 때 호출

    onResume()

  • 프래그먼트와 연결된 액티비티가 onResume()되어 사용자와 상호작용할 수 있을 때 호출

    onPause()

  • 프래그먼트와 연결된 액티비티가 onPause()되어 사용자와 상호작용을 중지할 때 호출

    onStop()

  • 프래그먼트와 연결된 액티비티가 onStop()되어 화면에서 더 이상 보이지 않을 때나 프래그먼트의 기능이 중지되었을 때 호출

    onDestroyView()

  • 프래그먼트와 관련된 뷰 리소스를 해제할 수 있도록 호출됨

    onDestroy()

  • 프래그먼트의 상태를 마지막으로 정리할 수 있도록 호출됨

    onDetach()

  • 프래그먼트가 액티비티와 연결을 끊기 바로 전에 호출됨

액션바 (ActionBar)

  • 상단의 메뉴바
  • 기본적으로 제목을 보여주는 타이틀의 기능
  • showAsAction 속성으로 메뉴를 보이게 할 것인지 지정

    옵션 메뉴 (Option Menu)

  • 시스템 메뉴 버튼을 눌렀을 때 나타나는 메뉴
  • 각 화면마다 설정할 수 있는 주요 메뉴

    컨텍스트 메뉴 (Context Menu)

  • 화면을 길게 누르면 나타나는 메뉴
  • 텍스트뷰의 편집상태를 바꾸거나 할 때 사용
  • 각각의 뷰 마다 설정할 수 있음

상단 탭과 하단 탭

탭 (Tab, 내비게이션 위젯)

  • 하나의 뷰에서 여러 개의 정보를 볼 때 일반적으로 사용하는 뷰
  • 상단 탭과 하단 탭으로 구분

    상단 탭 (Top Navigation)

  • 액션바에 탭 기능을 넣어 보여주는 방법으로 제공

    하단 탭 (Bottom Navigation)

  • BottomNavigationView 위젯으로 사용

뷰페이저 (ViewPager)

  • 손가락으로 좌우 스크롤하여 넘겨볼 수 있는 기능을 제공
  • FragmentStatePagerAdapter를 상속
  • Fragment형 ArrayList에 프래그먼트를 넣은 후, ViewPager에 setAdapter(adapter)하면 어댑터 객체가 설정되고 이때부터 뷰페이저는 어댑터에 있는 프래그먼트들을 화면에 보여줄 수 있게 됨

    어댑터 (Adapter)

  • 뷰페이저에 보여줄 각 프래그먼트를 관리하는 역할
  • 뷰페이저에 설정하면 서로 상호작용하면서 화면에 표시해주게 됨

    타이틀스트립 (TitleStrip)

  • 위나 아래쪽에 전체 프래그먼트들 중 몇 번째인지 알려주는 역할

바로가기 메뉴 (NavigationDrawer)

  • 화면의 좌측 상단에 위치한 햄버거 모양 아이콘을 눌렀을 때 나타나는 화면
  • 빠르게 메뉴 기능에 접근하고자 할 때 사용

5. 서비스와 수신자

서비스 (Service)

  • 오래 실행되는 작업을 위한 것
  • 백그라운드에서 실행되는 앱의 구성 요소
  • 매니페스트 파일에 등록 필요
  • 메인 액티비티에서 startService()로 서비스를 실행, 인텐트 객체를 파라미터로 전달

    onStartCommand()

  • 인텐트 객체가 null인 경우 Service.START_STICKY를 반환. 이 값은 서비스가 비정상 종료되었다는 의미이므로 시스템이 자동으로 재시작됨

    onBind()

  • 서비스가 서버 역할을 하면서 액티비티와 연결될 수 있도록 만드는 것

    인텐트 서비스 (IntentService)

  • 서비스처럼 백그라운드에서 실행되는 것은 같지만 길게 지속되는 서비스라기보다는 한 번 실행되고 끝나는 작업을 수행할 때 사용
  • 필요한 함수가 수행되고 나면 종료됨

브로드캐스트 수신자 (Broadcast Receiver)

  • 앱 간에 또는 구성 요소 간에 메시지를 주고받을 수 있도록 한 것
  • 기기 안에서 동작하는 다른 앱 A로부터 특정 메시지를 받기 위해 내가 만든 앱에 브로드캐스트 수신자를 등록하면 A의 메시지가 이곳으로 전달됨
  • 새 브로드캐스트 수신자를 만들면 매니페스트 파일에 등록해야하지만, 소스코드에서 registerReceiver()로 등록할 수도 있음
  • 브로드캐스트 수신자를 포함하고 있는 앱의 메인 액티비티가 적어도 한 번 실행되어야 브로드캐스트 수신자가 메시지를 받을 수 있음

    onReceive()

  • 원하는 브로드캐스트 메시지가 도착하면 자동으로 호출됨
  • 파라미터로 전달되는 Intent 객체안에 해당 데이터가 들어있음

위험 권한 (Dangerous Permission)

  • 대부분 개인정보가 담겨있는 정보에 접근하거나 개인정보를 만들어낼 수 있는 단말의 주요 장치에 접근할 때 부여
  • 위치, 카메라, 마이크, 연락처, 전화, 문자, 일정, 센서
  • AndroidManifest.xml에 태그로 권한을 추가
  • cf. 일반 권한 (Normal Permission)

리소스

  • 자바 코드와 분리하여 이해하기 쉽고 유지관리가 용이하게 만듬
  • 리소스는 빌드되어 설치파일에 추가되지만 애셋(Asset, 둘 다 모두 리소스라고 할 수 있으나 동영상이나 웹페이지와 같이 용량이 큰 데이터를 의미)은 빌드되지 않음
  • 리소스가 갱신되면 그때마다 리소스의 정보가 R.java 파일에 자동으로 기록되며 그 정보는 리소스에 대한 내부적인 포인터 정보가 됨
  • 리소스 유형마다 다른 파일에 넣어야 함
  • /app/res/values: 문자열이나 기본 데이터 타입에 해당하는 정보들이 저장
  • /app/res/drawable: 이미지를 저장, 단말의 해상도에 따라 다른 이미지를 보여줄 수 있도록 폴더를 나누어 저장할 수 있음

매니페스트

  • 설치된 앱의 구성 요소가 어떤 것인지, 그리고 어떤 권한이 부여되었는지 시스템에 알려주는 역할
  • 모든 안드로이드 앱은 가장 상위 폴더에 매니페스트 파일이 있어야 함
  • 앱이 실행되기 전에 시스템이 알아야 할 내용들을 정의하고 있음
  • 앱의 패키지 이름 지정
  • 앱 구성 요소에 대한 정보 등록(액티비티, 서비스, 브로드캐스트 수신자, 내용 제공자)
  • 각 구성 요소를 구현하는 클래스 이름 지정
  • 앱이 가져야 하는 권한에 대한 정보 등록
  • 다른 앱이 접근하기 위해 필요한 권한에대한 정보 등록
  • 앱 개발 과정에서 프로파일링을 위해 필요한 instrumentation 클래스 등록
  • 앱에 필요한 안드로이드 API의 레벨 정보 등록
  • 앱에서 사용하는 라이브러리 리스트

그래들 (Gradle)

  • 안드로이드 스튜디오에서 사용하는 빌드 및 배포 도구
  • 한 앱의 빌드 섲렁은 build.gradle 파일에 넣어 관리
  • 그래들 파일은 프로젝트 수준과 모듈 수준으로 나눠 관리

    프로젝트 수준 build.gradle

  • 프로젝트 안에 들어있는 모든 모듈에 적용되는 설정을 담고 있음
  • 이 파일을 수정하는 경우는 거의 없음
  • 가끔 외부 도구를 포함시키기 위해 buildscript의 dependencies안에 classpath를 추가하는 정도의 수정

    모듈 수준 build.gradle

  • 각각의 모듈에 대한 설정을 담고 있음
  • app 모듈의 설정 정보를 담고 있음
  • 새로운 모듈을 추가한다면 그 모듈에 대한 build.gradle 파일도 새로 추가해야 함

6. 선택 위젯

나인패치 (Nine Patch)

  • 이미지가 늘어나거나 줄어들 때 생기는 이미지 왜곡을 해결
  • 나인패치 이미지로 만든 파일 이름은 filename.9.png 처럼 파일 확장자 앞에 .9를 붙여야 함
  • 안드로이드에서는 이 방식의 파일을 원본 이미지의 가로, 세로 끝부분의 픽셀을 모두 나인패치 이미지의 정보를 담은 것으로 인식
  • 가운데 부분만 늘어나므로 이미지의 크기가 커지더라도 모서리 부분은 원래 이미지 모양을 유지할 수 있음

카드뷰 (CardView)

  • 프로필과 같은 간단 정보를 넣기 위해 각 영역을 구분하는 역할

리싸이클러뷰 (RecyclerView)

  • 리스트 모양으로 보여줄 수 있는 위젯
  • 기본적으로 상하 스크롤이지만 좌우도 가능
  • 각각의 아이템이 화면에 보일 때 메모리를 효율적으로 사용하도록 캐시(Cache) 메커니즘이 구현되어 있음
  • 리스트뷰보다는 리싸이클러뷰를 권장
  • 선택 위젯이기 때문에 어댑터가 데이터 관리와 뷰 객체 관리를 담당
  • 리싸이클러뷰에 보이는 여러 개의 아이템은 내부에서 캐시되기 때문에 아이템 개수만큼 객체로 만들어지지는 않음
  • 메모리를 효율적으로 사용하려면 뷰홀더에 뷰 객체를 넣어두고 사용자가 스크롤하여 보이지 않게 된 뷰 객체를 새로 보일 쪽에 재사용하는 것이 효율적이기 때문에 이 과정에서 뷰홀더가 재사용됨
  • 레이아웃 매니저로 리싸이클러뷰가 보일 기본적인 형태를 설정(세로, 가로, 격자 방향)

    onCreateViewHolder()

  • 뷰홀더가 새로 만들어지는 시점에 호출
  • 뷰 타입을 위한 정수값이 파라미터로 전달됨

    onBindViewHolder()

  • 뷰홀더 객체가 만들어질 때와 재사용될 때 자동으로 호출
  • 재활용할 수 있는 뷰홀더 객체를 파라미터로 전달하기 때문에 그 뷰홀더에 현재 아이템에 맞는 데이터만 설정

    getItemCount()

  • 어댑터에서 관리하는 아이템의 개수를 반환
  • 리싸이클러뷰에서 어댑터가 관리하는 아이템의 개수를 알아야 할 때 사용

스피너 (Spinner, 콤보박스)

  • 여러 아이템 중에서 하나를 선택하는 위젯
  • 선택 위젯

7. 애니메이션과 다양한 위젯

애니메이션 (Animation)

  • 애니메이션이 어떻게 동작할지 정의한 정보는 XML로 만든 후 자바 소스에서 애니메이션 객체로 로딩한 후 뷰 객체의 startAnimation() 메소드를 사용하여 애니메이션을 동작
  • 트윈 애니메이션 (Tweened Animation)으로 위치 이동, 회전, 스케일, 투명도, 속도 조절이 가능

페이지 슬라이딩

시크바 (SeekBar)

  • 상태 표시 위젯
  • 프로그레스바를 확장하여 만든 것, 프로그레스바의 속성을 갖고 있으면서 사용자가 값을 조정할 수 있게 함
  • 시크바의 일부분을 터치하면 터치한 부분으로 즉시 이동할 수 있는 방법을 제공, 가운데에 있는 핸들(Handle)을 드래그하여 좌우로 이동시킬 수 있음

    onStartTrackingTouch()

    onStopTrackingTouch()

    onProgressChanged()

  • 사용자에 의해 변경된 progress 값을 전달받을 수 있음

키패드 제어

  • 키패드가 올라오지 않도록 하려면 매니페스트에 속성을 추가해야 함(android:windowSoftInputMode=”stateHidden”)

    showSoftInput()

    hideSoftInputFromWindow()


8. 스레드와 핸들러

스레드 (Thread)

  • 하나의 프로세스 안에서 동시에 수행되어야 하는 작업을 위해 사용
  • 동시 수행이 가능한 작업 단위
  • 멀티 스레드 방식은 같은 프로세스 안에 들어 있으면서 메모리 리소스를 공유하므로 효율적인 처리가 가능하지만, 데드락(Deadlock)을 조심해야 함
  • new 연산자로 객체를 생성한 후 start() 메소드를 호출하면 시작할 수 있음
  • 생성자는 파라미터가 없는 경우와 Runnable 객체를 파라미터로 갖는 두 가지로 구분

    오랜 시간 작업을 수행할 때

  • 서비스 사용: 백그라운드 작업은 서비스로 실행하고 사용자에게는 알림 서비스로 알려줌. 만약 메인 액티비티로 결과 값을 전달하고 이를 이용해서 다른 작업을 수행하고자 한다면 브로드캐스팅으로 결과 값을 전달할 수 있음
  • 스레드 사용: 스레드는 같은 프로세스 안에 있기 때문에 작업 수행의 결과를 바로 처리할 수 있음. 그러나 UI 객체는 직접 접근할 수 없으므로 핸들러(Handler) 객체를 사용

핸들러 (Handler)

  • 메시지 큐로 메인 스레드에서 처리할 메시지를 전달하는 역할을 담당
  • 핸들러를 이용하면 특정 메시지가 미래의 어떤 시점에 실행되도록 스케줄링할 수 있음

    메시지 큐 (Message Queue)

  • 앱을 실행할 때 프로세스가 만들어지면 그 안에 메인 스레드가 함께 생성되는데, 그 최상위에서 관리되는 앱 구성요소(액티비티, 브로드캐스트 수신자 등)와 윈도우를 관리
  • 순차적으로 코드를 수행할 수 있게 함

    메인 스레드에 접근하기 위해 핸들러를 사용할 때 필요한 세 가지 단계

  • obtainMessage(): 새로 만든 스레드가 수행하려는 정보를 메인 스레드로 전달하기 위해 먼저 핸들러가 관리하는 메시지 큐에서 처리할 수 있는 메시지 객체 하나를 참조, 호출 결과로 메시지 객체를 반환
  • sendMessage(): 이 메시지 객체에 필요한 정보를 넣은 후 메시지 큐에 넣음
  • handleMessage(): 메시지 큐에 들어간 메시지는 순서대로 핸들러가 처리하게 되며, 이때 이 메소드에 정의된 기능이 수행됨. 이 코드가 수행되는 위치는 새로 만든 스레드가 아닌 메인 스레드가 됨

Runnable

  • 새로 만든 Runnable 객체를 핸들러의 post()로 전달해주면 이 객체에 정의된 run() 메소드 안의 코드들은 메인 스레드에서 실행

일정 시간 후에 실행

  • Thread.sleep() 메소드 사용
  • 핸들러의 sendMessageAtTime(), sendMessageDelayed()

스레드로 메시지 전송

  • 메인 스레드에서 별도의 스레드로 메시지를 전달할 때 사용
  • 메인 스레드는 UI 객체들을 처리하기 위해 메시지 큐와 루퍼를 사용
  • 하지만 별도의 스레드를 새로 생성하면 루퍼가 없으므로 메인 스레드나 다른 스레드에서 메시지 전송 방식으로 스레드에 데이터를 전달한 후 순차적으로 작업을 수행하고 싶다면 루퍼를 만든 후 실행해야 함

    루퍼 (Looper)

  • 메시지 큐에 들어오는 메시지를 지속적으로 보면서 하나씩 처리

AsyncTask

  • AsyncTask 클래스를 상속하여 새로운 클래스를 만들면 그 안에 스레드를 위한 코드와 UI 접근 코드를 한꺼번에 넣을 수 있음
  • 스레드로 처리해야 하는 코드를 하나의 AsyncTask 클래스로 정의할 수 있는 장점

    doInBackground()

  • 새로 만든 스레드에서 백그라운드 작업을 수행
  • execute() 메소드를 호출할 때 사용된 파라미터를 배열로 전달 받음

    onPreExecute()

  • 백그라운드 작업을 수행하기 전에 호출됨
  • 메인 스레드에서 실행
  • 초기화 작업에 사용됨

    onProgressUpdate()

  • 백그라운드 작업의 진행 상태를 표시하기 위해 호출됨
  • 작업 수행 중간에 UI 객체에 접근하는 경우에 사용
  • 이 메소드가 호출되도록 하려면 백그라운드 작업 중간에 publishProgress() 메소드를 호출해야 함

    onPostExecute()

  • 백그라운드 작업이 끝난 후 호출
  • 메인 스레드에서 실행
  • 메모리 리소스를 해제하는 등의 작업에 사용
  • 백그라운드 작업 결과는 Result 타입의 파라미터로 전달됨

    onCancelled()

  • AsyncTask 객체의 cancel() 메소드를 호출 시 동작
  • 작업을 취소

9. 서버

네트워킹 (Networking)

  • 인터넷에 연결되어 있는 원격지의 서버 또는 원격지의 단말과 통신해서 데이터를 주고받는 동작들을 포함
  • 인터넷에 연결되어 있는 여러 단말을 동시에 사용할 수 있어서 다양한 데이터 자원을 효율적으로 사용할 수 있기 때문에 중요

    2-tier C/S (Client/Server)

  • 클라이언트와 서버가 일대일로 연결
  • 원격지의 서버를 연결하는 가장 단순, 많이 사용하는 방식
  • 대부분 클라이언트가 서버에 연결되어 데이터를 요청하고 응답받음
  • HTTP 프로토콜(웹페이지를 볼때 사용), FTP 프로토콜(파일 전송), POP3 프로토콜(메일을 주고받음) 등의 연결 방식

    3-tier

  • 클라이언트, 응용서버, 데이터 서버간의 연결 방식
  • 응용 서버와 데이터 서버로 서버를 구성하면 데이터베이스를 분리할 수 있어서 중간에 비즈니스 로직(Business Logic)을 처리하는 응용서버가 좀 더 다양한 역할을 할 수 있다는 장점이 생김

    P2P 모델 (Peer-to-Peer)

  • 서버를 두지 않고 단말끼리 서버와 클라이언트 역할을 수행
  • 정보 검색이나 파일 송수신으로 정보를 공유하는 데 많이 사용

소켓 (Socket)

  • IP 주소로 목적지 호스트를 찾아내고 포트로 통신 접속점을 찾아냄
  • TCP, UDP 방식이 존재

    HTTP 프로토콜

  • 소켓으로 웹서버에 연결한 후에 요청을 전송하고 응답을 받은 다음 연결을 끊음 (비연결성, Stateless)

    웹으로 요청

  • HttpURLConnection 객체로 HTTP 클라이언트를 생성
  • setRequestProperty()로 GET, POST 요청 방식을 설정할 수 있음

Volley

  • 웹 요청과 응답을 단순화하기 위해 만들어진 라이브러리
  • 요청(Request) 객체를 만들고 이 요청 객체를 요청 큐(RequestQueue)에 넣어주면 요청 큐가 알아서 웹서버에 요청하고 응답까지 받아줌
  • 스레드, 핸들러를 사용하지 않음
  • 요청 큐가 내부에서 스레드를 만들어 웹서버에 요청하고 응답받는 과정을 진행
  • 요청 큐는 한 번만 만들어 계속 사용할 수 있기 때문에 static 키워드를 붙이며, 특정 액티비티에서만 사용하는 것이 아니라 앱 전체에서 사용하는 것이 일반적
  • 외부 라이브러리

JSON (JavaScript Object Notation)

  • 자바스크립트 객체 포맷을 데이터로 주고받을 때 사용할 수 있도록 문자열을 표현한 것

    GSON

  • 자바스크립트에서처럼 JSON 문자열을 객체로 변환할 수 있도록 해줌
  • JSON 문자열을 자바 객체로 바꾼 후 그 객체 안에 들어있는 데이터를 접근하여 사용
  • 외부 라이브러리

10. 데이터베이스와 내용 제공자

SQLite

  • 안드로이드의 임베디드 데이터베이스로 개발된 경량급(Light-weight) 관계형 데이터베이스
  • 파일로 만들어진 하위 수준의 구조
  • 데이터 조회 속도가 빠르고 표준 SQL을 지원

데이터베이스와 테이블

openOrCreateDatabase()

  • 데이터베이스를 생성하거나 조회

    deleteDatabase()

  • 데이터베이스 삭제

    execSQL()

  • 데이터베이스를 만들고 난 다음 SQL문을 실행할 때 사용

헬퍼(Helper) 클래스로 업그레이드 지원

  • 테이블의 정의가 바뀌어서 스키마를 업그레이드해야 할 때 API에서 제공하는 헬퍼 클래스를 사용
  • SQLiteOpenHelper 클래스 사용

내용 제공자 (Content Provider)

  • 앱에서 관리하는 데이터를 다른 앱에서도 접근할 수 있도록 함
  • 앱 구성요소이기 때문에 매니페스트 파일에 등록해야 사용 가능
  • 데이터베이스, 파일, SharedPreferences를 공유할 수 있음
  • CRUD 동작(Create, Read, Update, Delete)을 기준으로 함
  • 내용 제공자에서 허용한 통로로 접근하려면 콘텐트 리졸버(ContentResolver) 객체가 필요
  • 내용 제공자를 만들기 위해서는 고유한 값을 가진 content URI를 생성해야 함 (content://AUTHORITY/BASE_PATH)
  • ContentResolver 객체로 내용 제공자에 접근
  • 내용 제공자를 이용해 값을 조회하고 싶다면 Cursor의 query()를 사용

11. 뷰에 그래픽 그리기

뷰에 그래픽 그리기

  • 1단계: 뷰 상속
  • 2단계: 페인트 객체(Paint) 초기화
  • 3단계: onDraw() 메소드 구현
  • 4단계: onTouchEvent() 메소드 구현
  • 5단계: 메인 액티비티에 CustomView 클래스 추가

    그래픽 클래스

  • 캔버스(Canvas): 뷰의 표면에 직접 그릴 수 있도록 만들어주는 객체
  • 페인트(Paint): 그래픽 그리기 위해 필요한 색상 등의 속성을 담고 있음
  • 비트맵(Bitmap): 픽셀로 구성된 이미지로 메모리에 그래픽을 그리는 데 사용
  • 드로어블 객체(Drawable): 사각형, 이미지 등의 그래픽 요소가 객체로 정의되어 있음

드로어블 객체로 만들어 그리기

  • 리소스 파일의 사용: 프로젝트 리소스에 이미지와 같은 파일을 포함시킨 후 읽어 들여 사용
  • XML로 정의하여 사용
  • 소스 코드에서 객체를 만들어 사용
  • ShapeDrawable, BitmapDrawable, PictureDrawable, LayerDrawable 등

비트맵 이미지

  • 비트맵(Bitmap) 객체: 메모리에 만들어지는 이미지
  • 더블 버퍼링(Double Buffering): 별도의 메모리 공간에 미리 그래픽을 그린 후 뷰가 다시 그려져야 할 필요가 있을 때 미리 그려놓은 비트맵을 화면에 표시하는 방법
  • BitmapFactory 클래스: 비트맵 이미지를 만들기 위한 클래스 메소드를 제공

    decodeFile()

  • 파일에서 읽기
  • 파일 패스를 지정하면 해당 위치의 이미지 파일을 읽어옴

    decodeResource()

  • 리소스에서 읽기

    decodeByteArray()

  • 바이트 배열에서 읽기

    decodeStream()

  • 스트림에서 읽기

페인트보드

  • 터치 이벤트를 처리하여 빈 화면 위에 손가락으로 그림을 기를 수 있는 형태

멀티터치(Multi-Touch) 이미지 뷰어

  • 여러 개의 손가락으로 터치

머티리얼 디자인 (Material Design)

  • 구글이 안드로이드에 적용한 디자인 트렌드

12. 멀티미디어

카메라

  • FileProvider.getUriForFile() 메소드로 카메라 앱에서 공유하여 사용할 수 있는 파일 정보를 Uri 객체로 만듬

음악 파일

미디어플레이어(MediaPlayer) 클래스

  • 음악 파일과 같은 오디오 재생과 동영상 재생을 담당
  • 인터넷에 있는 파일, 프로젝트 파일, 단말 SD 카드의 파일 데이터 소스를 지정할 수 있음

동영상

  • 비디오뷰(VideoView) 위젯으로 XML에 태그 추가
  • 미디어콘트롤러(MediaController) 객체로 동영상의 재생 상태와 동영상을 제어
  • 동영상 재생을 위해서는 VideoView와 MediaPlayer를 사용할 수 있음
  • 더 세밀한 제어를 원한다면 MediaPlayer

오디오 녹음

  • 미디어리코더(MediaRecorder)로 오디오 녹음, 동영상 녹화를 진행
  • 미디어리코더 객체를 생성한 후 오디오 입력 및 출력 형식 설정, 오디오 인코더와 파일 지정하고 녹음 시작

13. 위치기반 서비스와 앱 위젯

GPS

  • 안드로이드 기반의 스마트폰 위치는 위치 관리자(LocationManager) 시스템 서비스가 관리

    위치 관리자 객체 참조

  • 위치 관리자(LocationManager)는 시스템 서비스로 제공되므로, getSystemService() 메소드를 이용해 위치 관리자 객체를 참조

    위치 리스너 구현

  • 위치 관리자가 알려주는 현재 위치는 위치 리스너(LocationListner)를 통해 받게 되므로 새로운 리스너를 구현하여 전달 받은 위치 정보를 처리

    위치 정보 업데이트 요청

  • 위치 관리자에게 위치 정보가 변경될 때마다 알려달라고 요청하기 위해 requestLocationUpdates() 메소드를 호출

    매니페스트에 권한 추가

  • ACCESS_FINE_LOCATION 권한 추가

앱 위젯 (AppWidget)

  • 홈 화면에서 위젯을 바로 보여주고 싶을 때 사용
  • 앱 위젯 호스트(App Widget Host, 위젯을 담고 있는 그릇), 앱 위젯 제공자(App Widget Provider, 위젯을 보여주는 제공자)
  • AppWidgetProvider 클래스를 상속
  • onUpdate() 재정의

    앱 위젯 구성할 때 필요한 요소

  • 위젯의 초기 뷰 레이아웃: 앱 위젯이 처음 화면에 나타날 때 필요한 레이아웃, XML로 정의
  • 앱 위젯 제공자 정보(App Widget Provider Info) 객체: 앱 위젯을 위한 메타데이터(레이아웃, 업데이트 주기 등)을 가짐. 앱 위젯 제공자 클래스에 대한 정보를 가지고 있음. XML로 정의
  • 앱 위젯 제공자(App Widget Provider): 앱 위젯과 정보를 주고받기 위한 기본 클래스. 브로드캐스트 수신자로 만들며 앱 위젯의 상태변화에 다른 기능을 구현

14. 푸시 서비스와 센서 및 단말 기능

진동과 소리

  • Vibrator 시스템 서비스 객체의 vibrate() 메소드로 진동 패턴이나 시간을 지정
  • Rintone 객체의 play() 메소드로 소리를 이용할 수 있음

상단 알림 (Notification)

  • NotificationManager 시스템 서비스를 이용해 화면 상단에 알림을 띄울 수 있음

푸시 서비스

  • 구글 클라우드 서버에서 구글 Play tmxhdjrk tjfclehls eksakfrlfh qhsownsms qkdtlr
  • 구글 서비스를 사용하지 않으면 폴링(Polling, 일정 시간 간격으로 서버와 연결이 끊어졌는지 검사) 메커니즘을 구현해야 하는데, 그 과정에서 단말의 하드웨어 리소스나 전원을 많이 소모하는 문제가 발생하므로 구글에서 제공하는 FCM(구글 푸시 서비스)를 사용하는 것이 효과적

    FCM 푸시 메시지 처리 과정

    (1) 구글 클라우드 서버에 단말 등록 (2) 애플리케이션 서버에 등록 ID 전송 (3) 애플리케이션 서버로 메시지 전송 요청 (4) 애플리케이션 서버가 구글 클라우드 서버로 메시지 전송 (5) 구글 클라우드 서버가 대상 단말에게 메시지 수신

센서

  • 가속 센서(Accelerometer): 가속도 감지, 외부의 충격량과 방향 감지
  • 자이로스코프 센서(Gyroscope): 회전 정보 감지, 다양한 축을 따른 회전각 감지
  • 중력 센서(Gravity): 축의 방향과 중력 감지
  • 조도 센서(Light): 빛의 세기 감지
  • 선형 가속 센서(Linear Acceleration): 각 축에 따른 가속도를 감지하는 3차원 벡터
  • 근접 센서(Proximity): 근접한 물체와의 거리 감지, 단말에 따라 가깝거나 먼 정도만 표시할 수도 있음
  • 온도 센서(Temperature): 온도 감지
  • 방향 센서(Orientation): 방향각 감지

시스템 서비스 (System Service)

  • 단말이 켜졌을 때 자동으로 실행되어 백그라운드에서 동작

    ActivityManager

  • 액티비티나 서비스를 관리하는 시스템 서비스
  • 앱의 실행 상태를 알 수 있도록 함

    PackageManager

  • 앱의 설치에 대한 정보를 알 수 있도록 함

    AlarmManager

  • 일정 시간에 알림을 받을 수 있도록 시스템에 등록해주는 역할

네트워크 기능

  • ConnectivityManager로 단말의 인터넷 연결 상태를 파악

다중 창 (Multi Window)

  • 단말 화면에 여러 개의 액티비티가 보이도록 지원하는 기능

참고

  • 안드로이드 앱 프로그래밍 6판 (정재곤, 이지스퍼블리싱)