이제 두 번째 Android 11 개발자 프리뷰를 사용할 수 있습니다. 테스트해 보고 의견을 공유하세요.

다른 앱으로 사용자 보내기

Android의 가장 중요한 특징 중 하나는 실행하려는 '작업'에 기반하여 사용자를 다른 앱으로 보낼 수 있는 앱의 기능입니다. 예를 들어, 지도에 표시하려는 비즈니스 주소가 있는 앱에서는 지도를 표시하는 활동을 빌드하지 않아도 됩니다. 대신, Intent를 사용하여 주소 보기 요청을 만들 수 있습니다. 그러면 Android 시스템이 지도에 주소를 표시할 수 있는 앱을 시작합니다.

첫 번째 클래스 첫 앱 빌드에서 설명한 대로 앱에서 활동 사이를 이동하려면 인텐트를 사용해야 합니다. 일반적으로 이러한 경우 시작하려는 구성요소의 정확한 클래스 이름을 정의하는 명시적 인텐트를 사용합니다. 그러나, '지도 보기'와 같이 별도의 앱에서 작업을 실행하려는 경우에는 암시적 인텐트를 사용해야 합니다.

이 과정에서는 특정 작업을 위해 암시적 인텐트를 생성하는 방법과 이를 사용하여 다른 앱에서 작업을 실행하는 활동을 시작하는 방법에 관해 설명합니다. 또한, 암시적 인텐트를 사용할 때 런타임 검사를 포함하는 것이 중요한 이유를 알아보려면 이 페이지에 삽입된 동영상을 참조하세요.

암시적 인텐트 빌드

암시적 인텐트는 시작할 구성요소의 클래스 이름을 선언하는 대신에 실행할 작업을 선언합니다. 작업은 보기, 수정, 보내기 또는 가져오기와 같이 원하는 동작을 지정합니다. 또한 인텐트는 보려는 주소 또는 보내려는 이메일 메시지와 같이 작업과 연관된 데이터를 포함하기도 합니다. 만들려는 인텐트에 따라 데이터는 Uri 또는 여러 다른 데이터 유형 중 하나가 될 수 있고 데이터가 전혀 필요하지 않을 수도 있습니다.

데이터가 Uri인 경우 간단한 Intent() 생성자를 사용하여 작업과 데이터를 정의할 수 있습니다.

다음은 전화번호를 지정하는 Uri 데이터를 사용하여 인텐트를 생성하고 전화 통화를 시작하는 예입니다.

Kotlin

    val callIntent: Intent = Uri.parse("tel:5551234").let { number ->
        Intent(Intent.ACTION_DIAL, number)
    }
    

자바

    Uri number = Uri.parse("tel:5551234");
    Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
    

앱이 startActivity()를 통해 이 인텐트를 호출하면 전화 앱은 지정된 전화번호로 통화를 시작합니다.

다음은 몇 가지 다른 인텐트와 해당 작업 및 Uri 데이터 쌍입니다.

  • 지도 보기:

    Kotlin

        // Map point based on address
        val mapIntent: Intent = Uri.parse(
                "geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California"
        ).let { location ->
            // Or map point based on latitude/longitude
            // Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level
            Intent(Intent.ACTION_VIEW, location)
        }
        

    자바

        // Map point based on address
        Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
        // Or map point based on latitude/longitude
        // Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom level
        Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
        
  • 웹 페이지 보기:

    Kotlin

        val webIntent: Intent = Uri.parse("http://www.android.com").let { webpage ->
            Intent(Intent.ACTION_VIEW, webpage)
        }
        

    자바

        Uri webpage = Uri.parse("http://www.android.com");
        Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);
        

다른 종류의 암시적 인텐트는 문자열 같은 다른 데이터 유형을 제공하는 '추가' 데이터가 필요합니다. 다양한 putExtra() 메서드를 사용하여 하나 이상의 추가 데이터를 덧붙일 수 있습니다.

기본적으로 시스템은 포함된 Uri 데이터를 기반으로 인텐트에서 요구하는 적절한 MIME 유형을 결정합니다. 인텐트에 Uri를 포함하지 않는다면 항상 setType()을 사용하여 인텐트와 연관된 데이터 유형을 지정해야 합니다. MIME 유형을 설정하면 인텐트를 수신해야 하는 활동 종류도 함께 지정됩니다.

다음은 원하는 작업을 지정하기 위해 추가 데이터를 사용하는 인텐트입니다.

  • 첨부파일이 포함된 이메일 보내기:

    Kotlin

        Intent(Intent.ACTION_SEND).apply {
            // The intent does not have a URI, so declare the "text/plain" MIME type
            type = HTTP.PLAIN_TEXT_TYPE
            putExtra(Intent.EXTRA_EMAIL, arrayOf("jon@example.com")) // recipients
            putExtra(Intent.EXTRA_SUBJECT, "Email subject")
            putExtra(Intent.EXTRA_TEXT, "Email message text")
            putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"))
            // You can also attach multiple items by passing an ArrayList of Uris
        }
        

    자바

        Intent emailIntent = new Intent(Intent.ACTION_SEND);
        // The intent does not have a URI, so declare the "text/plain" MIME type
        emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
        emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipients
        emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
        emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
        emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));
        // You can also attach multiple items by passing an ArrayList of Uris
        
  • 캘린더 일정 만들기:

    Kotlin

        Intent(Intent.ACTION_INSERT, Events.CONTENT_URI).apply {
            val beginTime: Calendar = Calendar.getInstance().apply {
                set(2012, 0, 19, 7, 30)
            }
            val endTime = Calendar.getInstance().apply {
                set(2012, 0, 19, 10, 30)
            }
            putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.timeInMillis)
            putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.timeInMillis)
            putExtra(Events.TITLE, "Ninja class")
            putExtra(Events.EVENT_LOCATION, "Secret dojo")
        }
        

    자바

        Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);
        Calendar beginTime = Calendar.getInstance();
        beginTime.set(2012, 0, 19, 7, 30);
        Calendar endTime = Calendar.getInstance();
        endTime.set(2012, 0, 19, 10, 30);
        calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis());
        calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis());
        calendarIntent.putExtra(Events.TITLE, "Ninja class");
        calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");
        

    참고: 캘린더 일정에 사용되는 이 인텐트는 API 레벨 14 이상에서만 지원됩니다.

참고: 최대한 Intent를 구체적으로 정의해야 합니다. 예를 들어, ACTION_VIEW 인텐트를 사용하여 이미지를 표시하려면 image/* MIME 유형을 지정해야 합니다. 그러면 다른 유형의 데이터를 '볼' 수 있는 앱(예: 지도 앱)이 인텐트에 의해 트리거되지 않습니다.

인텐트를 수신할 앱이 있는지 확인

Android 플랫폼에서 특정 인텐트가 내장된 앱(예: 전화, 이메일 또는 캘린더 앱) 중의 하나로 해결되도록 보장하기는 하지만 항상 인텐트를 호출하기 전에 확인 단계를 포함해야 합니다.

주의: 인텐트를 호출했을 때 기기에 인텐트를 처리할 수 있는 앱이 없다면 앱이 비정상 종료됩니다.

인텐트에 응답할 수 있는 활동이 있는지 확인하려면 queryIntentActivities()를 호출하여 Intent를 처리할 수 있는 활동 목록을 가져와야 합니다. 반환된 List가 비어있지 않다면 안전하게 인텐트를 사용할 수 있습니다. 예:

Kotlin

    val activities: List<ResolveInfo> = packageManager.queryIntentActivities(
            intent,
            PackageManager.MATCH_DEFAULT_ONLY
    )
    val isIntentSafe: Boolean = activities.isNotEmpty()
    

자바

    PackageManager packageManager = getPackageManager();
    List<ResolveInfo> activities = packageManager.queryIntentActivities(intent,
            PackageManager.MATCH_DEFAULT_ONLY);
    boolean isIntentSafe = activities.size() > 0;
    

만약 isIntentSafetrue이면 최소한 하나의 앱이 인텐트에 응답합니다. false이면 인텐트를 처리할 앱이 없습니다.

참고: 인텐트 사용 기능을 사용자가 사용하려고 하기 전에 중지해야 하는 경우에 대비하여 활동이 처음 시작할 때 이 검사를 실시해야 합니다. 인텐트를 처리할 수 있는 앱을 알고 있다면 사용자에게 앱 다운로드 링크를 제공할 수도 있습니다(Google Play의 제품에 연결하는 방법 참조).

인텐트를 이용하여 활동 시작

그림 1. 인텐트를 처리할 수 있는 앱이 둘 이상 있을 경우 표시되는 선택 대화상자의 예

Intent를 생성하고 추가 정보를 설정한 후 startActivity()를 호출하여 시스템으로 보냅니다. 시스템이 인텐트를 처리할 수 있는 활동을 두 개 이상 식별한 경우 그림 1과 같이 사용자가 사용할 앱을 선택할 수 있도록 대화상자('확인 대화상자'라고도 함)를 표시합니다. 인텐트를 처리할 수 있는 활동이 하나밖에 없을 경우, 시스템은 활동을 바로 시작합니다.

Kotlin

    startActivity(intent)
    

자바

    startActivity(intent);
    

다음은 지도 보기 인텐트를 생성하고 인텐트를 처리할 수 있는 앱이 있는지 확인하여 시작하는 방법을 보여주는 완성된 예입니다.

Kotlin

    // Build the intent
    val location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California")
    val mapIntent = Intent(Intent.ACTION_VIEW, location)

    // Verify it resolves
    val activities: List<ResolveInfo> = packageManager.queryIntentActivities(mapIntent, 0)
    val isIntentSafe: Boolean = activities.isNotEmpty()

    // Start an activity if it's safe
    if (isIntentSafe) {
        startActivity(mapIntent)
    }
    

자바

    // Build the intent
    Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
    Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);

    // Verify it resolves
    PackageManager packageManager = getPackageManager();
    List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
    boolean isIntentSafe = activities.size() > 0;

    // Start an activity if it's safe
    if (isIntentSafe) {
        startActivity(mapIntent);
    }
    

앱 선택기 표시

그림 2. 선택기 대화상자

IntentstartActivity()에 전달하여 활동을 시작할 때 인텐트에 응답하는 앱이 둘 이상 있다면 사용자는 어떤 앱을 기본으로 사용할지 선택할 수 있습니다(대화상자 하단의 체크박스 선택, 그림 1 참조). 이는 일반적으로 사용자가 항상 동일한 앱을 사용하여 웹페이지를 열거나(사용자는 하나의 웹브라우저만 사용) 사진을 촬영(사용자는 하나의 카메라만 선호)하는 등의 작업을 실행하려고 할 때 유용합니다.

하지만 실행할 작업이 여러 앱에서 처리할 수 있고 사용자가 매번 다른 앱을 선호한다면(예: '공유' 작업과 같이 사용자가 한 항목을 공유할 수 있는 앱을 여러 개 갖는 경우) 그림 2와 같이 명시적으로 선택기 대화상자를 표시해야 합니다. 선택기 대화상자는 사용자가 작업에 사용할 앱을 매번 선택하도록 합니다(사용자가 작업에 사용할 기본 앱을 선택할 수 없음).

선택기를 표시하려면 createChooser()를 사용하여 Intent를 생성하고 startActivity()에 전달합니다. 예:

Kotlin

    val intent = Intent(Intent.ACTION_SEND)
    ...

    // Always use string resources for UI text.
    // This says something like "Share this photo with"
    val title = resources.getString(R.string.chooser_title)
    // Create intent to show chooser
    val chooser = Intent.createChooser(intent, title)

    // Verify the intent will resolve to at least one activity
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(chooser)
    }
    

자바

    Intent intent = new Intent(Intent.ACTION_SEND);
    ...

    // Always use string resources for UI text.
    // This says something like "Share this photo with"
    String title = getResources().getString(R.string.chooser_title);
    // Create intent to show chooser
    Intent chooser = Intent.createChooser(intent, title);

    // Verify the intent will resolve to at least one activity
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(chooser);
    }
    

이 예는 createChooser() 메서드에 전달된 인텐트에 응답하는 앱의 목록을 대화상자에 표시하고 제공된 텍스트를 대화상자의 제목으로 사용합니다.