Lesson 4: Build your first Android app

Hanbinยท2021๋…„ 8์›” 9์ผ
0

Teach Android Development

๋ชฉ๋ก ๋ณด๊ธฐ
4/13
post-thumbnail

๐Ÿ’ก Teach Android Development

๊ตฌ๊ธ€์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ต์œก์ž๋ฃŒ๋ฅผ ์ •๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ํฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.

Android Development Resources for Educators

Choose API levels for your app

  • Minimum SDK: ๊ธฐ๊ธฐ์— ์„ค์น˜ ์‹œ ํ•„์š”ํ•œ ์ตœ์†Œ API level ์ž…๋‹ˆ๋‹ค.
  • Target SDK: API ๋ฒ„์ „ ๋ฐ ํ…Œ์ŠคํŠธ๋œ ๊ฐ€์žฅ ๋†’์€ Android ๋ฒ„์ „์ž…๋‹ˆ๋‹ค.
  • Compile SDK: ์ปดํŒŒ์ผ ์‹œ ์‚ฌ์šฉ๋˜๋Š” Android OS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฒ„์ „์ž…๋‹ˆ๋‹ค.
  • Setting: minSdkVersion <= targetSdkVersion <= compileSdkVersion

API level์€ Android SDK์˜ ํ”„๋ ˆ์ž„์›Œํฌ API ๋ฒ„์ „์„ ์‹๋ณ„ํ•ฉ๋‹ˆ๋‹ค.

Anatomy of an Android App project

  • Activity
  • Resources (layout files, images, audio files, themes, and colors)
  • Gradle files

Android app project structure

MyApplication
โ”œโ”€โ”€ app
โ”‚   โ”œโ”€โ”€ libs
โ”‚   โ””โ”€โ”€ src
โ”‚       โ”œโ”€โ”€ androidTest
โ”‚       โ”œโ”€โ”€ main
โ”‚       โ”‚   โ”œโ”€โ”€ java
โ”‚       โ”‚   โ”œโ”€โ”€ res
โ”‚       โ”‚   โ””โ”€โ”€ AndroidManifest.xml
โ”‚       โ””โ”€โ”€ test
โ”œโ”€โ”€ build.gradle
โ””โ”€โ”€ gradlew

Layouts and resources in Android

Views

  • Views๋Š” Android์˜ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ณธ ์š”์†Œ์ž…๋‹ˆ๋‹ค.
    - ํ™”๋ฉด์˜ ์ง์‚ฌ๊ฐํ˜• ์˜์—ญ์œผ๋กœ ๊ฒฝ๊ณ„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
    - ๋“œ๋กœ์ž‰ ๋ฐ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ๋ฅผ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
    - Examples : TextView, ImageView, Button
  • ๋” ๋ณต์žกํ•œ ํ™”๋ฉด ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ๊ทธ๋ฃนํ™” ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

XML Layouts

XML์„ ์ด์šฉํ•˜์—ฌ ๋ ˆ์ด์•„์›ƒ์„ ํŽธ์ง‘ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Android๋Š” XML์„ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค(View ์†์„ฑ ํฌํ•จ)์˜ ๋ ˆ์ด์•„์›ƒ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค
  • XML์˜ ๊ฐ View๋Š” ํ•ด๋‹น View๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์„ ์ œ์–ดํ•˜๋Š” Kotlin์˜ ํด๋ž˜์Šค์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

XML for a TextView

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!"/>

Size of a View

  • wrap_content
    android:layout_width="wrap_content"
  • match_parent
    android:layout_width="match_parent"
  • Fixed value (use dp units)
    android:layout_width="48dp"

ViewGroups

  • ViewGroup์€ views๊ฐ€ ํ‘œ์‹œ๋˜๋Š” ๋ฐฉ์‹์„ ๊ฒฐ์ •ํ•˜๋Š” ์ปจํ…Œ์ด๋„ˆ์ž…๋‹ˆ๋‹ค.
  • ViewGroup์€ ๋ถ€๋ชจ์ด๊ณ  ๊ทธ ์•ˆ์˜ ๋ทฐ๋Š” ์ž์‹์ž…๋‹ˆ๋‹ค.

FrameLayout example

FrameLayout์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹จ์ผ ์ž์‹ ๋ทฐ๋ฅผ ๋ณด์œ ํ•ฉ๋‹ˆ๋‹ค.

<FrameLayout
   android:layout_width="match_parent"
   android:layout_height="match_parent">
   <TextView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:text="Hello World!"/>
</FrameLayout>

LinearLayout example

  • ํ–‰ ๋˜๋Š” ์—ด์˜ child views๋ฅผ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค.
  • android:orientation์„ ๊ฐ€๋กœ ๋˜๋Š” ์„ธ๋กœ๋กœ ์„ค์ •
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView ... />
    <TextView ... />
    <Button ... />
</LinearLayout>

View hierarchy

App resources

์ฝ”๋“œ์—์„œ ์‚ฌ์šฉํ•˜๋Š” static ์ฝ˜ํ…์ธ  ๋˜๋Š” ์ถ”๊ฐ€ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.

  • Layout files
  • Images
  • Audio files
  • User interface strings
  • App icon

Common resource directories

์ƒ์œ„ res ํด๋” ์•„๋ž˜์˜ ์ ์ ˆํ•œ res ๋””๋ ‰ํ† ๋ฆฌ์— ํฌํ•จํ•˜์—ฌ ์•ฑ์— ๋ฆฌ์†Œ์Šค๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

main
โ”œโ”€โ”€ java
โ””โ”€โ”€ res
   โ”œโ”€โ”€ drawable
   โ”œโ”€โ”€ layout
   โ”œโ”€โ”€ mipmap
   โ””โ”€โ”€ values

Resource IDs

  • ๊ฐ ๋ฆฌ์†Œ์Šค์—๋Š” ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” ๋ฆฌ์†Œ์Šค ID๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฆฌ์†Œ์Šค ์ด๋ฆ„์„ ์ง€์ •ํ•  ๋•Œ ๊ทœ์น™์€ underscores ํ•จ๊ป˜ ๋ชจ๋‘ lowercase๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค
    (์˜ˆ: activity_main.xml).
  • Android๋Š” ์•ฑ์˜ ๋ชจ๋“  ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์ฐธ์กฐ์™€ ํ•จ๊ป˜ R.java๋ผ๋Š” ํด๋ž˜์Šค ํŒŒ์ผ์„ ์ž๋™ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐœ๋ณ„ ํ•ญ๋ชฉ์€ R.<resource_type>.<resource_name>์œผ๋กœ ์ฐธ์กฐ๋ฉ๋‹ˆ๋‹ค.
    • ์˜ˆ:
      • R.drawable.ic_launcher (res/drawable/ic_launcher.xml)
      • R.layout.activity_main (res/layout/activity_main.xml)

Resource IDs for views

๊ฐœ๋ณ„ view์—๋„ ๋ฆฌ์†Œ์Šค ID๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
android:id ์†์„ฑ์„ XML์˜ view์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. @+id/name ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  <TextView
       android:id="@+id/helloTextView"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Hello World!"/>

์ด์ œ ์•ฑ ๋‚ด์—์„œ TextView๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. R.id.helloTextView

Activities

Whatโ€™s an Activity?

  • Activity๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ํ•˜๋‚˜์˜ ์ฃผ์š” ๋ชฉํ‘œ๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ์ˆ˜๋‹จ์ž…๋‹ˆ๋‹ค.
  • Android ์•ฑ์€ ํ•˜๋‚˜ ์ด์ƒ์˜ Activity๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

MainActivity.kt

class MainActivity : AppCompatActivity() {

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_main)
   }
}

How an Activity runs

Implement the onCreate() callback

์‹œ์Šคํ…œ์ด Activity๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
}

Layout inflation

Make an app interactive

Define app behavior in Activity

์•ฑ์ด ๋ฒ„ํŠผ ํƒญ๊ณผ ๊ฐ™์€ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์— ์‘๋‹ตํ•˜๋„๋ก Activity๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

Modify a View dynamically

MainActivity.kt ์•ˆ์—์„œ
view ๊ณ„์ธต๊ตฌ์กฐ์—์„œ View์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
val resultTextView: TextView = findViewById(R.id.textView)

view instance์—์„œ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
resultTextView.text = "Goodbye!"

Set up listeners for specific events

View.OnClickListener

XML์— ์„ ์–ธ๋œ Button์„ id๋ฅผ ์ฐธ์กฐํ•ด ๊ฐ€์ ธ์˜จ ๋’ค click event๋ฅผ ๋“ฑ๋กํ•œ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

class MainActivity : AppCompatActivity(), View.OnClickListener {

   override fun onCreate(savedInstanceState: Bundle?) {
       ...
       val button: Button = findViewById(R.id.button)
       button.setOnClickListener(this)
   }

   override fun onClick(v: View?) {
       TODO("not implemented")
   }
}

SAM (single abstract method)

ํ•จ์ˆ˜๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

val runnable = Runnable { println("Hi there") }


// ์œ„์˜ ๋ฐฉ์‹๊ณผ ๊ฐ™์€ ํ‘œํ˜„์ž…๋‹ˆ๋‹ค.
val runnable = (object: Runnable {
    override fun run() {
        println("Hi there")
    }
})

View.OnClickListener as a SAM

Click listener๋ฅผ ๋ณด๋‹ค ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

class MainActivity : AppCompatActivity() {

   override fun onCreate(savedInstanceState: Bundle?) {
       ...

       val button: Button = findViewById(R.id.button)
       button.setOnClickListener({ view -> /* do something*/ })
   }
}

Late initialization

class Student(val id: String) {

    lateinit var records: HashSet<Any>

    init {
        // retrieve records given an id
    }
}

Lateinit example in Activity

class MainActivity : AppCompatActivity() {

    lateinit var result: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
       ...
       result = findViewById(R.id.result_text_view)
    }
}

Lateinit์„ ์‚ฌ์šฉํ•ด TextView๋ฅผ Notnullํ•˜๊ฒŒ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Gradle: Building an Android app

What is Gradle?

  • ์ž๋™ํ™” ์‹œ์Šคํ…œ ๊ตฌ์ถ•
  • ์ผ๋ จ์˜ ์ž‘์—…์„ ํ†ตํ•ด ๋นŒ๋“œ cycle์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.(์˜ˆ: kotlin์†Œ์Šค ์ปดํŒŒ์ผ, ํ…Œ์ŠคํŠธ ์‹คํ–‰, ์•ฑ์„ค์น˜)
  • ์‹คํ–‰ํ•  ์ž‘์—…์˜ ์ ์ ˆํ•œ ์ˆœ์„œ๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ํ”„๋กœ์ ํŠธ์™€ third-party libraries๊ฐ„์˜ ์ข…์†์„ฑ์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

Gradle build file

  • ํ”Œ๋Ÿฌ๊ทธ์ธ ์„ ์–ธ
  • Android ์†์„ฑ ์ •์˜
  • dependencies ์ฒ˜๋ฆฌ
  • repositories ์—ฐ๊ฒฐ

Plugins

์•ฑ์— ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ์ธํ”„๋ผ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

Android configuration

Android ํ•„์š”ํ•œ ์†์„ฑ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

android {
   compileSdkVersion 30
   buildToolsVersion "30.0.2"

   defaultConfig {
       applicationId "com.example.sample"
       minSdkVersion 19
       targetSdkVersion 30
   }
}

Dependencies

App์— ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.

dependencies {
   implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
   implementation 'androidx.core:core-ktx:1.3.2'
   implementation 'androidx.appcompat:appcompat:1.2.0'
   implementation 'com.google.android.material:material:1.2.1'
   ...
}

Repositories

ํ•ด๋‹น ์ €์žฅ์†Œ์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

repositories {
    google()
    mavenCentral()
}

Common Gradle tasks

  • Clean
  • Tasks
  • InstallDebug

Accessibility

  • ์žฅ์• ์ธ์„ ํฌํ•จํ•œ ๋” ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ๋” ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์•ฑ์˜ ๋””์ž์ธ๊ณผ ๊ธฐ๋Šฅ์„ ๊ฐœ์„ ํ•˜๋Š” ๊ฒƒ์„ ๋งํ•ฉ๋‹ˆ๋‹ค.
  • ์•ฑ์˜ ์ ‘๊ทผ์„ฑ์„ ๋†’์ด๋ฉด ์ „๋ฐ˜์ ์œผ๋กœ ๋” ๋‚˜์€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๊ณ  ๋ชจ๋“  ์‚ฌ์šฉ์ž์—๊ฒŒ ํ˜œํƒ์„ ์ค๋‹ˆ๋‹ค.

Make apps more accessible

  • foreground and background์˜ ์ƒ‰์ƒ ๋Œ€๋น„ ๋น„์œจ๋กœ ํ…์ŠคํŠธ ๊ฐ€์‹œ์„ฑ์„ ํ–ฅ์ƒ ์‹œํ‚ต๋‹ˆ๋‹ค.
    • background์— ๋Œ€ํ•œ ์ž‘์€ ํ…์ŠคํŠธ์˜ ๊ฒฝ์šฐ ์ตœ์†Œ 4.5:1
    • background์— ๋Œ€ํ•œ ํฐ ํ…์ŠคํŠธ์˜ ๊ฒฝ์šฐ ์ตœ์†Œ 3.0:1
  • ํฌ๊ณ  ๊ฐ„๋‹จํ•œ ์ปจํŠธ๋กค ์‚ฌ์šฉ
    • ํ„ฐ์น˜ ๋Œ€์ƒ์˜ ํฌ๊ธฐ๋Š” ์ตœ์†Œ 48dp x 48dp์ด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐ UI์š”์†Œ ์„ค๋ช…
    • ์ด๋ฏธ์ง€ ๋ฐ ์ปจํŠธ๋กค์— ๋Œ€ํ•œ ์„ค๋ช…์„ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

add content labels

contentDescription ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด screen reader๋กœ ์ฝ์–ด์ง‘๋‹ˆ๋‹ค.

<ImageView
    ...
    android:contentDescription="@string/stop_sign" />

TextView์˜ text์˜ ๊ฒฝ์šฐ ์ด๋ฏธ accessibility services์— ์ œ๊ณต๋˜์—ˆ์œผ๋ฏ€๋กœ ์ถ”๊ฐ€ label์ด ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค.

No content label needed

์ˆœ์ „ํžˆ ์žฅ์‹์šฉ ๊ทธ๋ž˜ํ”ฝ ์š”์†Œ์— ๋Œ€ํ•ด์„œ๋Š” ๋‹ค์Œ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
android:importantForAccessibility="no"
๋ถˆํ•„์š”ํ•œ ๊ณต์ง€๋Š” ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ด ์‚ฌ์šฉ์ž์—๊ฒŒ ๋” ์ข‹์Šต๋‹ˆ๋‹ค.

TalkBack

  • Android ๊ธฐ๊ธฐ์— ํฌํ•จ๋ด Google ์Šคํฌ๋ฆฐ ๋ฆฌ๋”
  • device๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ํ™”๋ฉด์„ ๋ณผ ํ•„์š”๊ฐ€ ์—†๋„๋ก ์Œ์„ฑ ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • ์ œ์Šค์ฒ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ device๋ฅผ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Switch access

  • ํ„ฐ์น˜์Šคํฌ๋ฆฐ ๋Œ€์‹  ํ•˜๋‚˜ ์ด์ƒ์˜ ์Šค์œ„์น˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ device๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์•ฑ UI๋ฅผ ์Šค์บ”ํ•˜๊ณ  ์„ ํƒํ•  ๋•Œ๊นŒ์ง€ ๊ฐ ํ•ญ๋ณต์„ ๊ฐ•์กฐ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
  • ์™ธ๋ถ€ ์Šค์œ„์น˜, ์™ธ๋ถ€ ํ‚ค๋ณด๋“œ, Android device์˜ ๋ฒ„ํŠผ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€