[ Do it! ] 안드로이드 앱 프로그래밍 - #3. 어플리케이션 구성하기 (3)

ma.caron_g·2022년 3월 8일
0

Do it! - Android Studio

목록 보기
9/18
post-thumbnail

[ 인텐트 ]

인텐트는 다른 액티비티를 띄우거나 기능을 동작시키기 위한 수단으로 사용됩니다.
즉, 무언가 작업을 수행하기 위해 사용되는 일종의 명령 또는 데이터 접근 수단이 됩니다.

[ 인텐트의 역할과 사용 방식 ]

인텐트는 android.content 패키지 안에 정의되어 있습니다.
인텐트는 다른 어플리케이션 구성 요소에 인텐트를 전달할 수 있는 대표적인 메서드는 다음과 같습니다.

메서드설 명
startActivity() / registerForActivityResult화면을 띄울 때 사용
startService() / bindService()서비스를 시작할 때 사용
broadcastIntent()브로드캐스트를 수행할 때 사용

인텐트의 기본 구성요소

  • 액션(Action) - 수행할 기능
  • 데이터(Data) - 액션이 수행될 대상의 데이터
속 성설 명
ACTION_DIAL tel)01012345678주어진 전화번호를 이용해 전화걸기 화면을 보여줌
ACTION_VIEW tel01012345678주어진 전화번호를 이용해 전화걸기 화면을 보여줌. URI 값의 유형에 따라 VIEW 액션이 다른 기능을 수행함.
ACTION_EDIT content://contacts/people/2전화번호부 데이터베이스에 있는 정보 중 ID값이 2인 정보를 편집하기 위한 화면을 보여줌
ACTION_VIEW content://contacts/people전화번호부 데이터베이스의 내용을 보여줌

인텐트에 포함되어 있는 데이터는 그 포맷이 어떤 것인가를 시스템이 확인한 후 적절한 액티비티를 자동으로 찾아 띄워주기도 합니다.
http와 같은 특정 포맷을 사용하면 그 포맷은 등록된 MIME타입으로 구분합니다.
예를 들어, "http://"로 시작하는 문자열의 경우 웹페이지 주소를 나타내는 URL이라고 인식하는 것과 같습니다.

안드로이드의 인텐트 전달 메커니즘도 이렇게 MIME타입을 구분한 후 설치된 앱들 중 적절한 것을 띄워주는 것입니다.

[ 명시적 인텐트 (Explicit Intent) ]

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

[ 암시적 인텐트 (Implicit Intent) ]

액션과 데이터를 지정했지만 호출할 대상이 달라질 수 있는 경우
MIME 타입에 따라 안드로이드 시스템에서 적절한 다른 앱의 액티비티를 찾은 후 띄우는 방식을 사용
설치된 앱 정보를 미리 알고있는 안드로이드 시스템이 인텐트를 이용해 요청한 정보를 처리할 수 있는 적적한 컴포넌트를 찾아본 다음 사용자에게 그 대상과 처리 결과를 보여주는 과정을 거치게 됩니다.

[ 범주 (Category) ]

액션이 실행되는데 필요한 추가적인 정보를 제공합니다.
예를 들어, CATEGORY_LAUNCHER는 최상위 어플리케이션으로 설치된 어플리케이션의 목록을 보여주는 애플리케이션 런처(Launcher) 화면에 이 어플리케이션을 보여주어야 한다는 것을 의미합니다.

[ 타입 (Type) ]

인텐트에 들어가는 데이터의 MIME 타입을 명시적으로 지정합니다.
보통 MIME 타입은 데이터만으로도 구별이 가능하지만 명시적으로 지정할 필요가 있는 경우도 있습니다.

[ 컴포넌트 (Component) ]

액티비티와 같은 독립적인 구성 요소라고 생각하면 쉽습니다.
인텐트에 사용될 컴포넌트 클래스 이름을 명시적으로 지정합니다. 보통 이 정보는 인텐트의 다른 정보를 통해 결정됩니다. 이 속성이 지정될 경우 지정된 컴포넌트가 실행되도록 합니다.
새로운 액티비티를 정의하고 그 액티비티의 클래스 객체를 인텐트에 전달하여 실행하는 방법도 컴포넌트를 지정하는 방식과 동일합니다.

[ 부가데이터 (Extra Data) ]

인텐트에 추가적인 정보를 넣을 수 있도록 번들(Bundle) 객체를 담고 있습니다.
이 객체를 통해 인텐트 안에 더 많은 정보를 넣어 다른 어플리케이션 구성 요소에 전달할 수 있습니다.
예를 들어, 이메일을 보내는 액션이 있다면 이메일에 들어갈 제목, 내용 등을 부가 데이터로 넣어 전달해야 이메일 어플리케이션이 그 데이터를 받아 처리할 수 있습니다.

[ 구현 해보기 ]

[ ACTION을 이용한 인텐트 ]

[ activity_main.xml ]

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/edtNumber"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="tel:010-0000-0000"
        android:textSize="24sp"/>
    <Button
        android:id="@+id/btnCall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:padding="15dp"
        android:text="전화 걸기"
        android:textSize="18sp"
        android:textStyle="bold" />

</LinearLayout>

[ MainActivity.java ]

package com.study.doit;

import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        EditText edtNumber = findViewById(R.id.edtNumber);
        Button btnCall = findViewById(R.id.btnCall);

        ActivityResultLauncher startActivityLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
            @Override
            public void onActivityResult(ActivityResult result) {

            }
        });

        btnCall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String data = edtNumber.getText().toString();

                Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(data));
                startActivityLauncher.launch(intent);
            }
        });

    }
}

[ 디자인 ]

[ Component를 이용한 인텐트 ]

[ activity_main.xml ]

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/edtNumber"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="tel:010-0000-0000"
        android:textSize="24sp"/>
    <Button
        android:id="@+id/btnCall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:padding="15dp"
        android:text="전화 걸기"
        android:textSize="18sp"
        android:textStyle="bold" />

</LinearLayout>

[ MainActivity.java ]

package com.study.doit;

import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        EditText edtNumber = findViewById(R.id.edtNumber);
        Button btnCall = findViewById(R.id.btnCall);

        ActivityResultLauncher startActivityLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
            @Override
            public void onActivityResult(ActivityResult result) {

            }
        });

        btnCall.setOnClickListener(new View.OnClickListener() {
            @Override
           public void onClick(View view) {
                Intent intent = new Intent();
                //패키지명과 클래스명을 집어 넣는다.
                ComponentName name = new ComponentName("com.study.doit",  "com.study.doit.PartActivity");

                intent.setComponent(name);
                startActivityLauncher.launch(intent);
            }
        });

    }
}

[ 디자인 ]

컴포넌트 이름은 ComponentName 객체를 만들어 인텐트에 설정하는데
두 개의 파라미터는 각각 패키지명클래스명이 됩니다.

ComponentName 객체를 만들어 대상 액티비티의 이름을 지정할 때도 패키지 이름까지 함께 사용합니다.

[ 인텐트 필터 ]

인텐트 필터는 시스템이 요청하는 인텐트의 정보를 받아 처리할 어플리케이션 구성 요소를 찾기 위해 필요한 정보

액티비티#1명시적 인텐트를 이용해 액티비티#3을 실행시킵니다.
액티비티#3은 문자 메시지를 받아 처리하는 어플리케이션으로 액티비티#3의 컴포넌트 이름을 지정하면 해당 앱을 실행할 수 있으므로 액티비티#3직접 호출하여 문자 메시지를 처리합니다.

액티비티#2암시적 인텐트를 이용해 액티비티#3을 실행시킵니다.
액티비티#3은 지정한 앱이 아니라 문자 메시지를 처리할 수 있는 여러 앱 중의 하나일 수 있으므로 각각 인텐트 필터를 이용해 시스템이 인텐트를 비교할 수 있도록 만들어 줍니다.
만약 문자 메시지를 처리할 수 있는 앱이 여러 개 발견된다면 시스템은 사용자에게 어떤 앱을 실행할 것인지 물어보게 됩니다.
어떠한 경우건 인텐트에 명시된 정보는 최대한 구체적이고 자세해야 시스템이 사용자의 목적에 맞는 앱을 찾아줄 수 있습니다.

profile
다른 사람이 만든 것을 소비하는 활동보다, 내가 생산적인 활동을 하는 시간이 더 많도록 생활화 하자.

0개의 댓글