시작하기

Hello World

  1. 기본 설정대로 프로젝트를 생성하면 아래의 4개 주요 파일을 볼 수 있다
  2. MainActivity.java
  3. 앱을 실행하면 이 클래스의 인스턴스가 실행되고 layout을 로드한다

  4. activity_main.xml
  5. 액티비티의 UI를 정의한다

  6. AndroidManifest.xml
  7. 앱의 기본적인 특성을 기술하고, 각 컴포넌트를 정의한다

  8. build.gradle
  9. 앱의 컴파일과 빌드에 관한 구성 설정

앱 컴포넌트

  1. Activity : UI가 있는 단일 화면. 액티비티는 한 번에 하나만 실행할 수 있다
  2. Project window » 우클릭 » New » Activity : 자동으로 매니페스트에도 추가된다

    액티비티 시작 : startActivity() or startActivityForResult()

    액티비티 생애주기 : onCreate(인스턴스 생성 시), onRestart(재시작), onStart(onCreate, onRestart 후), onResume(포그라운드), onPause(백그라운드), onStop(비가시영역 진입), onDestroy(소멸)

    xml에서 saveEnabled 속성을 true로 하면 onSaveInstanceState, onRestoreInstanceState 메서드를 재정의하여 사용할 수 있다

  3. Service : 백그라운드에서 실행되는 요소
  4. 서비스 시작 : startService() or bindService()

  5. ContentProvider : 외부로 공유하는 데이터 집합 관리
  6. ContentProvider 이용 : ContentResolver.query()

  7. BroadcastReceiver : 각 브로드캐스트는 Intent 객체로 전달된다
  8. 브로드캐스트 송신 : sendBroadcast(), sendOrderedBroadcast(), sendStickyBroadcast()

  9. Intent : 컴포넌트 간의 데이터 전달
    • Activity, Service, BroadcastReceiver는 Intent로 활성화되고, ContentProvider는 ContentResolver의 요청으로 활성화된다
    • public Intent(Context packageContext, Class cls)
    • Intent putExtra(String name, ? value)
    • 명시적 인텐트 : 수신 클래스 지정
    • 암시적 인텐트 : 작업을 처리할 수 있는 컴포넌트로 안드로이드가 연결
    • 브로드캐스트 인텐트 : 브로드캐스트 리시버로 등록된 모든 수신자에게 전송
  10. Fragment : Deprecated in API level 28

매니페스트

  1. 구성 요소 선언, 요구 권한 식별, 최소 API 레벨 선언 등
  2. <activity>, <service>, <receiver>, <provider>

    BroadcastReceiver는 registerReceiver()를 통해 동적으로 등록할 수 있다

  3. 다른 앱의 intent에 응답하기 위해 <intent-filter>요소를 해당 요소의 하위에 추가한다
  4. 요구사항 선언
  5. ↓ xml

    <!-- 예. 카메라 없으면 구글 플레이에서 설치 불가 --> <uses-feature android:name="android.hardware.camera.any" android:required="true"/> <!-- http://developer.android.com/guide/topics/manifest/uses-feature-element.html#features-reference --> <!-- API 7이상 --> <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" />
  6. application 엘리먼트
  7. 많은 메모리를 필요로 하는 경우에만 android:largeHeap 속성 이용

  8. 컴포넌트 엘리먼트
  9. 설정이 완료되기 전까지 기능을 제한하려는 경우, android:enabled 속성을 이용해 Activity, Service, BroadcastReceiver의 동작을 막을 수 있다

    ↓ java

    PackageManager manager = getPackageManager(); manager.setComponentEnabledSetting( new ComponentName(this, MainActivity.class), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP );
  10. 인텐트 필터링 예
  11. ↓ xml

    <activity ~> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="video/*"/> </intent-filter> </activity>

UI

  1. 안드로이드 UI는 layout(ViewGroup 객체)들과 widget(View 객체)들의 계층으로 이루어진다
  2. 길이 단위
    • px : 픽셀. 장치마다 밀도가 달라 제각기로 표현된다
    • dp : Density-independent pixels. 160dp는 밀도와 관계없이 1인치로 표시된다
    • mm : 밀리미터
    • in : 인치
    • pt : 포인트 = 1/72 인치
  3. View
    • 버튼, 텍스트 박스 등의 UI 요소
    • TextView, EditText, Button, ImageView, Switch, ...

    • id 속성 : @[+]id/ID
    • ID를 할당할 때는 +를 앞에 붙여 R 클래스의 상수로 등록되도록 한다

    • layout_width, layout_height : 너비, 높이
    • match_parent : 부모 요소의 크기만큼 할당, wrap_content : 내용물만큼 할당, 상수 지정 : 크기 고정

    • background : 배경. 지정하지 않으면 각 뷰의 기본값이 사용된다
    • visibility : 가시성. visible | invisible | gone
    • padding, layout_margin
  4. ViewGroup
    • 자식 요소들을 어디에 위치시킬 지 조정한다
    • ConstraintLayout
    • 형제 요소들과 부모 레이아웃에 대한 거리를 통해 뷰를 조정한다

      여러 요소들을 선택하여 우클릭한 뒤 chain으로 연결하면 한 번에 가로/세로로 배치할 수 있다

    • LinearLayout
    • orientation 속성으로 horizontal | vertical 지정

      gravity 속성으로 정렬 가능. center_horizontal(0x01), left(0x03), right(0x05), fill_horizontal(0x07), center_vertical(0x10), top(0x30), bottom(0x50), fill_vertical(0x70), center(0x11), fill(0x77)

      baselineAligned 속성으로 요소들의 아래 줄을 일치시킬 지 여부를 지정할 수 있다

      요소의 layout_weight 속성으로 너비/높이를 일정 비율씩 나눠가질 수 있다

    • GridLayout
    • 화면의 가로/세로(columnCount/rowCount)를 잘라 만든 격자를 이용해 배치

  5. UI를 업데이트할 때엔 새 Runnable을 생성해 activity.runOnUiThread() 호출
  6. EventListener
  7. 테마 적용 예
  8. BottomNavigationView
  9. com.google.android.material:material 포함

    * Used icons made by Smashicons from www.flaticon.com is licensed by CC 3.0 BY

SQLite

  1. SQLite 추상화 계층 Room : 문서 1문서 2

권한 요청

알림 보내기

매니페스트 설정 불필요

SensorManager

Location Manager

↓ xml

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

위치 소스 provider

  1. GPS : LocationManager.GPS_PROVIDER, 오차 ~수십 미터, 배터리 소모 많음, 긴 TTFF(Time To First Fix). ACCESS_FINE_LOCATION 권한 필요
  2. 기지국 : LocationManager.NETWORK_PROVIDER, 오차 ~수백 미터, 짧은 TTFF, 적은 배터리 소모. ACCESS_COARSE_LOCATION 권한 필요
  3. LocationManager.PASSIVE_PROVIDER : 다른 앱이 요청한 위치 정보를 사용, ACCESS_FINE_LOCATION 권한 필요

LocationManager

  1. List<String> getProviders (boolean enabledOnly)
  2. void requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener) + removeUpdates
  3. minTime : 업데이트 간 최소 시간(ms), minDistance : 업데이트 간 최소 거리(m)

  4. void requestSingleUpdate (String provider, PendingIntent intent)
  5. void addProximityAlert (double latitude, double longitude, float radius, long expiration, PendingIntent intent) + removeProximityAlert
  6. 근접 경보. 등록한 영역에 들어가거나 나갈 때 인텐트로 알림. ACCESS_FINE_LOCATION 권한 필요

    expiration : 기한 내에 도착하지 못하면 알림 취소. -1이면 무기한

    intent로 KEY_PROXIMITY_ENTERING이라는 boolean 값 전달. true면 들어가는 것, false면 나가는 것

LocationListener

  1. void onLocationChanged(Location location)
  2. void onProviderEnabled(String provider) + onProviderDisabled
  3. 사용자가 위치 설정의 ON/OFF를 변경할 때

  4. void onStatusChanged(String provider, int status, Bundle extras)
  5. Deprecated Since 29 : 절대 호출되지 않는다

    GPS를 이용하도록 설정했음에도 신호가 수신되지 않는 경우 등

    status : LocationProvider.OUT_OF_SERVICE, LocationProvider.TEMPORARILY_UNAVAILABLE, LocationProvider.AVAILABLE

백그라운드, 절전 모드에서의 실행

  1. CPU 항상 켜기 필요 권한 : android.permission.WAKE_LOCK
  2. ↓ java

    PowerManager manager = (PowerManager)getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock lock = manager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TAG_FOR_DEBUG"); lock.acquire(); // business logic lock.release();
  3. 화면 항상 켜기
  4. xml : android:keepScreenOn="true" 또는
    java : getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

  5. 주기적인 백그라운드 알람
  6. ↓ java

    AlarmManager manager = (AlarmManager)getSystemService(ALARM_SERVICE); // 1회 알람 : set(int type, long triggerAtMillis, PendingIntent operation) // 1회 정시 알람 : setExact(int type, long triggerAtMillis, PendingIntent operation) + 오버로딩 manager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+5000, pendingIntent); // 반복 알람 : setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) // 모든 반복 알람은 부정확하다

    알람 type

    1. RTC : System#currentTimeMillis로 얻어지는 시각 기준
    2. ELAPSED_REALTIME : SystemClock#elapsedRealtime로 얻어지는, 부팅 후 경과 시간 기준
    3. RTC_WAKEUP, ELAPSED_REALTIME_WAKEUP : *_WAKEUP 타입은 기기가 자고 있으면 깨워서 실행시킨다
  7. Doze 모드
  8. 네트워크 액세스 정지. WAKE_LOCK 무시. AlarmManager 경보 무시. Wi-Fi 검색 X, JobScheduler 실행 X, AbstractThreadedSyncAdapter 실행 X

    • AlarmManager#setAndAllowWhileIdle, setExactAndAllowWhileIdle를 사용해야 한다
    • AlarmManager#setAlarmClock으로 설정된 경보는 정상적으로 실행되며, 실행 직전에 doze 모드가 종료된다
  9. AsyncTask
  10. onPreExecute(), onProgressUpdate, onPostExecute : 메인 스레드에서 실행된다

  11. Application 객체를 통한 공유
  12. 안드로이드 애플리케이션은 항상 Application 컴포넌트를 하나 갖고 있으며, Context#getApplication로 접근 가능하다
    사용자 정의 Application을 사용하는 경우, 매니페스트의 name 속성을 변경해주고, getApplication() 결과를 캐스팅해야 한다

ProGuard

  1. 코드 최적화 및 난독화
  2. build.gradle의 안드로이드 영역에 아래를 추가
  3. ↓ gradle

    buildTypes { release { runProguard true proguardFile getDefaultProguardFile('proguard-android.txt') } }

최적화

performance

몽키 테스트