13-1. 인텐트 이해하기

StrayCat·2022년 9월 29일
0

1. 인텐트 이해하기

인텐트란?

  • 컴포넌트를 실행하려고 시스템에 전달하는 메세지

  • 컴포넌트를 실행하는 데이터를 담은 인텐트 객체를 시스템에 전달하여 컴포넌트 실행

MainActivity -> DetailActivity 처럼 바로 실행하지 않고,
MainActivity -> 시스템 (Intent) -> DetailActivity 와 같이 실행한다.
컴포넌트 클래스는 시스템이 생성해서 실행하는 클래스이므로 미리 정해진 생명주기를 가지고 있기 때문.

동일 앱의 Activity 뿐만 아니라 외부 앱의 Activity 실행시에도 동일하게 Intent를 시스템에 전달하여 실행한다.


컴포넌트 등록

Activity는 Manifest 파일에 등록해야한다. Activity 하나당 <activity>태그 하나로 등록해야하고 name속성을 포함해야한다.

Activity뿐만 아니라 서비스, 브로드캐스트 리시버, 콘텐츠 프로바이더 모두 Manifest 파일에 등록해야 시스템이 인식할 수 있다.


Intent 전달

MainActivity에서 DetailActivity를 실행하고자 할 경우 아래와 같이 Intent를 생성해 전달해주면 된다.

val intent: Intent = Intent(this, DetailActivity::class.java)
startActivity(intent)

Intent를 전달하면서 추가적인 정보를 같이 보내야 할 경우 엑스트라 데이터(extra data) 를 사용한다.

val intent: Intent = Intent(this, DetailActivity::class.java)
intent.putExtra("data1", "hello")
startActivity(intent)

DetailActivity에서는 getStringExtra(), getIntExtra(), getDoubleExtra() 를 통해 받을 수 있다.

val data1 = intent.getStringExtra("data1")

액티비티 되돌리기

  1. public void startActivity(Intent intent)

  2. public void startActivityForResult(Intent intent, int requestCode)

  3. ActivityResultLauncher

Activity를 호출할 때 위와같이 3가지 방식을 사용할 수 있다. 현재는 3번을 사용하도록 권장하고 있다.

startActivityForResult

  • Activity 전환 후 사후 처리가 필요할 때, 결과 코드를 받아서 처리할 수 있다.

  • requestCode(10)을 intent와 함께 담아 2번째 Activity를 실행한다.

startActivityForResult(intent, 10)
  • 2번째 Activity에서 resultCode(RESULT_OK)를 intent와 담은 후 종료한다.
        intent.putExtra("resultData", "world")
        setResult(RESULT_OK, intent)
        finish()
  • resultCode와 requestCode를 통해 결과를 처리한다.
        override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
            super.onActivityResult(requestCode, resultCode, data)
            if(requestCode == 10 && resultCode == Activity.RESULT_OK){
                val result = data?.getStringExtra("resultData")
            }
        }

ActivityResultLauncher

  • Contract -> ActivityResultLauncher -> launch

  • 요청의 실행자 -> Contract와 Callback 등록 -> 요청발생

  • Contract : 액티비티로 실행할 때 실제 인텐트를 발생시키는 역할

  • ActivityResultLauncher : Contract와 Callback 객체를 등록하여 연결

  • launch : Contract 객체 실행

        val requestLauncher: ActivityResultLauncher<Intent> = registerForActivityResult(
            ActivityResultContracts.StartActivityForResult())  //Contract
            { 
            val resultData = it.data?.getStringExtra("result")
            binding.mainResultView.text = "result: $resultData" 
            } //Callback
  • launcher 실행
        val intent: Intent = Intent(this, DetailActivity::class.java)
        requestLauncher.launch(intent)

명시적 인텐트 / 암시적 인텐트

  • 내부 앱의 컴포넌트를 요청하는 intent를 만들때는 DetailActivity::class.java 와 같이 클래스 타입 레퍼런스를 활용할 수 있다.

  • 외부 앱의 컴포넌트의 경우 위처럼 사용할 수 없으므로, 매니페스트 파일에 선언된 인텐트 필터를 사용한다.

        <activity
            android:name=".MainActivity2"
            android:exported="true"
            <intent-filter>
                <action android:name="ACTION_EDIT"/>
                <data android:scheme="http"/>
            </intent-filter>
        </activity>
  • 아래 예시는 런처 화면에서 아이콘을 클릭했을 때 실행되는 인텐트 필터이다.
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
  • action(기능), category(범주), data(데이터) 태그를 설정하여 구분한다.

  • intent를 생성할 때 intent 정보를 담아서 실행한다.

        val intent = Intent()
        intent.action = "ACTION_EDIT"
        intent.data = Uri.parse("http://www.google.com")
        startActivity(intent)

액티비티 인텐트 동작 방식

  • 암시적 인텐트로 시작할 수 있는 액티비티가 없을 경우에는 에러가 발생하므로 에러처리를 해줘야 한다.

  • 여러개일 경우는 사용자가 선택해서 수행할 수 있으며, intent.setPackage()를 통해 특정 앱을 미리 지정할 수 있다.

intent.setPackage("com.google.android.apps.maps") // 구글맵스 실행

외부 앱 접근 설정

  • 안드로이드11(API 30레벨) 부터는 외부 앱에 접근하여 특정 함수를 사용하기 위해서는 아래와 같이 manifest 파일에 설정을 해줘야 한다.
<manifest ...>
    <queries>
        <package android:name="com.example.test_outter"/>
    </queries>
</manifest>
  • PackageManager$NameNotFoundException 에러가 발생할 경우 작성한다.
  • 아래와 같이 모든 앱에 대해서 권한을 가져올 수 있지만 권장하지는 않는다.
    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
        tools:ignore="QueryAllPackagesPermission" />

0개의 댓글