본문 바로가기
Android Studio

[Android 앱개발 입문] Intent (# 추가하기)

by 젼젼39 2024. 3. 20.

Intent

    : 일종의 메시지 객체

    - 이것을 이용해 다른 앱 구성요소(액티비티, 서비스, 브로드캐스트 리시버)로 작업을 요청할 수 있음
            - startActivity(intent), startService(intent), sendBroadcast(intent)

    - 안드로이드 앱의 구성 요소들 사이에서 실행을 위임하거나 정보를 전달하는 역할을 함

 

1. Intent의 유형

1) 명시적 인텐트 (explicit intent)

     : 특정한 컴포넌트를 직접적으로 호출할 때 사용되는 인텐트

    - 이 방법으로 개발자는 인텐트 객체에 시작하고자 하는 구성 요소의 이름을 명확하게 설정하고,
        startActivity() 또는 startService() 메소드를 통해 해당 컴포넌트를 실행시킴
         (시스템이 액티비티 추론할 필요 없이 개발자가 직접 지정)

        //주로 앱 내부에서 다른 액티비티나 서비스를 시작할 때 사용됨. 
        (ex. 메인 액티비티에서 사용자의 입력을 받아 세부 정보를 표시하는 새로운 액티비티를 띄울 때)

 

2) 암시적 인텐트

    : 특정한 컴포넌트를 명시하지 않고,
        수행하고자 하는 일반적인 작업을 인텐트 객체에 설정해 startActivity() 메소드에 넘김

    - 안드로이드 시스템은 이 인텐트를 처리할 수 있는 모든 애플리케이션을 검색해
        적합한 인텐트 필터를 가진 컴포넌트를 찾아 실행시킴

    (1) 인텐트 필터
            : 특정 인텐트에 반응하는 액티비티, 서비스 또는 브로드캐스트 리시버의 능력을 정의
            = 어떤 인텐트를 수신할 준비가 되어있는지를 나타내는 설정

        - 본인의 앱이 수신할 수 있는 암시적 인텐트가 무엇인지 알기 위해서는
            각 앱 구성 요소에 대한 하나 이상의 인텐트 필터를 <intent_filter> 요소로 매니페스트 파일에 선언해야 함

        - 각 인텐트 필터가 인텐트의 작업, 데이터 및 카테고리를 근거로 어느 유형의 인텐트를 수신할지를 결정함

        // AndroidManifest.xml 에서 android:name 속성 값이 SecondActivity인 <activity>요소 하위에 <intent-filter> 태그 추가

        <activity
            android:name=".SecondActivity"
            android:label="Second Activity"
            android:exported="false" >

            <intent-filter>
                <action android:name="android.intent.action.DIAL"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:scheme="tel"/>
            </intent-filter>

        </activity>

        // action의 action.DIAL : 다이얼을 받을 수 있는 앱
        // data -> 데이터는 tel을 통해 받을것임

        // android:name = 안드로이드 시스템에서 해당 구성 요소를 찾아 실행할 때 사용. (구성 요소의 실제 구현된 클래스 이름)

        // android:label = 앱의 화면에 표시되는 텍스트. 사용자 인터페이스에서 해당 구성 요소를 식별할 때 사용

<action> 수신되는 인텐트의 액션을 지정
(안드로이드에서는 액션에 따라 시스템이 어떤 동작을 수행해야 하는지를 결정)
//ex. android.intent.action.VIEW는 데이터를 보여주는 액션
<category> 인텐트의 추가적인 정보를 제공
이를 통해 시스템이 인텐트를 처리하는 방법을 더 세부적으로 제어 가능
// category android:name="android.intent.category.LAUNCHER"
        -> 앱 실행 시 그 액티비티가 먼저 실행됨
<data> 인텐트와 관련된 데이터를 지정
URI, MIME, 파일 확장자 등의 형태로 지정될 수 있음
// ex. tel 스키마를 가진 데이터를 다루기 위해 <data android:scheme='tel'/>

 

    (2) 일반적 사용법
            : 암시적 인텐트는 주로 다른 앱의 컴포넌트를 실행시키는 데 사용됨
            ex. 사용자가 '지도 보기'를 요청할 때, 해당 작업을 처리할 수 있는 모든 앱 중 사용자가 선택할 수 있게 목록 제공

 

2. 인텐트 객체 분석하기

1) 컴포넌트 이름
        : 타겟 컴포넌트의 이름을 명시해, 인텐트가 전달될 정확한 대상을 지정
            ex.  new Intent(context, TargetActivity.class) 에서 TargetActivity.class 가 컴포넌트 이름임

        - 컴포넌트 이름이 없으면 인텐트는 암시적으로 처리되고, 시스템이 적절한 대상을 찾음

 

2) 액션
        : 인텐트가 수행해야 할 일반적인 작업을 정의. 수행되어야 할 작업을 나타내는 문자열

        - ex.  Intent.ACTION_VIEW : 사용자에게 데이터를 보여줄 때 사용됨
        - ex.  Intent.ACTION_DIAL   : 전화 다이얼을 열기 위해 사용

 

3) 데이터
        : 작업을 수행하는 데 필요한 데이터의 URI(정보의 고유한 명칭. url보다 상위)를 지정함
            ex.  Uri.parse("tel:12345")  : 전화 앱에 전화번호 데이터를 제공         

작업(액션) 데이터 설명
ACTION_VIEW   웹페이지를 표시
ACTION_CALL tel:114 114번 전화번호로 전화연결 시작
ACTION_DIAL tel:114 114번 전화번호로 전화걸기 화면 표시

        - 데이터는 보통 Uri 객체로 액션과 결합해 사용됨

 

4) 카테고리
        : 인텐트의 유형을 더 구체적으로 지정하여, 어떤 컴포넌트가 처리할 수 있는지 알려줌

        - ex.  Intent.CATEGORY_HOME  : 홈 화면 애플리케이션을 시작할 때 사용됨

카테고리 설명
CATEGORY_BROWSABLE 대상 액티비티가 웹브라우저에 의해 시작되어서 이미지와 같은 데이터를 표현할 수 있음
CATEGORY_LAUNCHER 이 액티비티가 작업의 최초 액티비티이고, 이것이 시스템의 애플리케이션 시작 관리자에 목록으로 게재되어 있음

 

5) 엑스트라
        : 복잡한 데이터를 인텐트에 전달하기 위한 키-값 쌍의 추가 정보
            ex.  intent.putExtra("extra_key", "value") 에서 "extra_key" 는 전달할 데이터의 키이고, "value"는 실제 값임

        - 엑스트라를 통해 기본 타입부터 Serializable 객체가지 다양한 데이터 전달 가능

 

3. 명시적 인텐트로 다른 액티비티 시작하기

    - 명시적 인텐트는 특정한 액티비티를 시작할 때 사용됨.
        (안드로이드는 이를 통해 현재 액티비티에서 다른 액티비티로 전환할 수 있음)

// 현재 액티비티에서 AnotherActivity를 시작하기 위한 명시적 인텐트 생성
val intent = Intent(this, AnotherActivity::class.java)

// 인텐트에 데이터 추가 (옵션)
intent.putExtra("key", "value")

// AnotherActivity 시작
startActivity(intent)

    1) 인텐트 생성 : Intent 클래스의 객체를 생성함

            - 매개변수 : 현재 컨텍스트 (this) , 시작하고자 하는 액티비티의 Class 객체

    2) 데이터 전달 (선택사항) : putExtra 메소드를 사용해 인텐트에 키-값 쌍으로 이루어진 추가 데이터 삽입 가능

            - 시작될 액티비티에서 이 데이터를 사용할 수 있음

    3) 액티비티 시작 : startActivity 메소드를 호출해 인텐트를 사용함

            - 이 호출이 실행되면 안드로이드 시스템은 명시된 인텐트에 따라 AnotherActivity를 시작함

-> 현재 액티비티에서 다른 액티비티로의 전환을 명확하게 제어 가능 (앱의 흐름 관리에 필수적인 기능)

 

 

activity 추가 => app > new > Activity > Empty Activity

 

1) activity_first.xml 파일 수정

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height=“match_parent"
    android:gravity = “center”
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="첫번째 액티비티 입니다."
        android:id="@+id/textView" />

    <Button
        android:layout_width=“wrap_content"
        android:layout_height="wrap_content"
        android:text="두번째 액티비티 시작하기"
        android:id="@+id/buttonFirstActivity"
        android:layout_marginTop="43dp" />

</LinearLayout>

 

2) activity_Second.xml 수정

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:padding="16dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="두번째 액티비티 입니다."
        android:id="@+id/textView" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="닫기"
        android:id="@+id/buttonSecondActivity"
        android:layout_marginTop="43dp" />

</LinearLayout>

 

3) FirstActivity 수정

class FirstActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_first)

        val btn = findViewById<Button>(R.id.buttonFirstActivity)
        btn.setOnClickListener{
            val intent = Intent(this, SecondActivity::class.java)
            startActivity(intent)
        }
    }
}

 

4) SecondActivity 수정

class SecondActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)

        val btn = findViewById<Button>(R.id.buttonSecondActivity)
        btn.setOnClickListener{
            finish()
        }
    }
}

 

4. 암시적 인텐트로 다른 액티비티 시작하기

    : 암시적 인텐트로 다른 액티비티를 시작하기 위해서는 인텐트 안에 작업과 데이터를 지정해야 함

    ex. 114 번호로 다이얼 작업을 수행할 수 있는 액티비티 실행시키기 위해 call_intent 생성 후 startActivity()메소드에 전달
            tel:114 = 전화번호 114의 URI 객체

val call_intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:114"))
startActivity(call_intent)
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="다이얼 작업 시작하기"
        android:id="@+id/buttonDialActivity"
        android:onClick="doOnBtnClick"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="지도보기 작업 시작하기"
        android:id="@+id/buttonMapActivity"
        android:onClick="doOnBtnClick"/>
package com.example.acrivityintent2

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.View
import android.widget.Button
//import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
//import androidx.core.view.ViewCompat
//import androidx.core.view.WindowInsetsCompat

class FirstActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //enableEdgeToEdge()
        setContentView(R.layout.activity_first)
//        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
//            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
//            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
//            insets
//        }

        val btn = findViewById<Button>(R.id.buttonFirstActivity)
        btn.setOnClickListener {
            val intent = Intent(this, SecondActivity::class.java)
            startActivity(intent)
        }
    }
    fun doOnBtnClick(view: View){
        when(view.id){
            R.id.buttonDialActivity -> {
                val call_intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:114"))
                startActivity(call_intent) 		//암시적 인텐트
            }
            R.id.buttonMapActivity -> {
                val map_intent = Intent(Intent.ACTION_VIEW, Uri.parse("geo:37.565350, 127.01445"))
                startActivity(map_intent)
            }
        }
    }
}

 

 

코드 정렬 -> ctrl + alt + L