Cho phép ứng dụng khác khởi động hoạt động của bạn

Nếu ứng dụng của bạn có thể thực hiện một thao tác hữu ích từ một ứng dụng khác, thì bạn nên chuẩn bị để phản hồi các yêu cầu thao tác bằng cách chỉ định bộ lọc ý định thích hợp trong hoạt động.

Ví dụ: nếu xây dựng một ứng dụng mạng xã hội có thể chia sẻ tin nhắn hoặc ảnh với bạn bè của người dùng, bạn nên hỗ trợ ý định ACTION_SEND. Rồi khi người dùng bắt đầu thao tác "chia sẻ" từ một ứng dụng khác, ứng dụng của bạn sẽ xuất hiện dưới dạng tuỳ chọn trong hộp thoại bộ chọn (còn gọi là "hộp thoại phân định") như thấy trong hình 1.

Hình 1. Hộp thoại bộ chọn

Để cho phép ứng dụng khác khởi động hoạt động của bạn theo cách này, bạn cần thêm phần tử <intent-filter> trong tệp kê khai cho phần tử <activity> tương ứng.

Khi ứng dụng của bạn được cài trên một thiết bị, hệ thống sẽ xác định bộ lọc ý định và thêm thông tin vào danh mục nội bộ gồm các ý định được tất cả các ứng dụng đã cài đặt hỗ trợ. Khi một ứng dụng gọi startActivity() hoặc startActivityForResult(), với ý định ngầm ẩn, hệ thống sẽ tìm ra (các) hoạt động nào có thể phản hồi ý định.

Thêm Bộ lọc ý định

Nhằm xác định chính xác ý định nào mà hoạt động của bạn có thể xử lý, mỗi bộ lọc ý định bạn thêm vào phải càng cụ thể càng tốt về loại thao tác và dữ liệu mà hoạt động chấp nhận.

Hệ thống có thể gửi Intent đã định đến một hoạt động nếu hoạt động đó có bộ lọc ý định đáp ứng các tiêu chí sau của đối tượng Intent:

Thao tác
Một chuỗi đặt tên cho thao tác cần thực hiện. Thường một trong những giá trị do nền tảng xác định, chẳng hạn như ACTION_SEND hoặc ACTION_VIEW.

Chỉ định thao tác này trong bộ lọc ý định bằng phần tử <action>. Giá trị bạn chỉ định trong phần tử này phải là tên chuỗi đầy đủ cho thao tác, thay vì hằng số API (xem các ví dụ bên dưới).

Dữ liệu
Nội dung mô tả dữ liệu liên kết với ý định.

Chỉ định dữ liệu này trong bộ lọc ý định bằng phần tử <data>. Khi sử dụng một hoặc nhiều thuộc tính trong phần tử này, bạn có thể chỉ định chỉ loại MIME, chỉ tiền tố URI, chỉ lược đồ URI, hay tổ hợp các thuộc tính này và các thuộc tính khác cho biết loại dữ liệu được chấp nhận.

Lưu ý: Nếu không cần khai báo thông tin cụ thể về dữ liệu Uri (chẳng hạn như khi hoạt động của bạn xử lý loại dữ liệu "bổ sung" khác, thay vì URI), thì bạn chỉ nên chỉ định thuộc tính android:mimeType để khai báo loại dữ liệu mà hoạt động của bạn xử lý, chẳng hạn như text/plain hoặc image/jpeg.

Danh mục
Bổ sung một cách khác để mô tả hoạt động xử lý ý định, thường liên quan đến cử chỉ hoặc vị trí mà người dùng bắt đầu. Có nhiều danh mục được hệ thống hỗ trợ, nhưng hầu hết hiếm khi được sử dụng. Tuy nhiên, tất cả các ý định ngầm ẩn đều được xác định bằng CATEGORY_DEFAULT theo mặc định.

Chỉ định danh mục này trong bộ lọc ý định bằng phần tử <category>.

Trong bộ lọc ý định, bạn có thể khai báo tiêu chí mà hoạt động chấp nhận bằng cách khai báo từng tiêu chí với phần tử XML tương ứng được lồng trong phần tử <intent-filter>.

Ví dụ: đây là một hoạt động có bộ lọc ý định xử lý ý định ACTION_SEND khi loại dữ liệu là văn bản hoặc hình ảnh:

<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
        <data android:mimeType="image/*"/>
    </intent-filter>
</activity>

Mẹo: Nếu bạn muốn biểu tượng trong hộp thoại bộ chọn khác với biểu tượng mặc định cho hoạt động của mình, thêm android:icon vào phần tử <intent-filter>.

Mỗi ý định được chia sẻ chỉ định một thao tác và loại dữ liệu, nhưng bạn có thể khai báo nhiều thực thể của <action>, <category> và phần tử <data> trong mỗi <intent-filter>.

Nếu bất kỳ cặp thao tác và dữ liệu nào loại trừ lẫn nhau trong các hành vi của chúng thì bạn nên tạo các bộ lọc ý định riêng rẽ để chỉ định hành động nào được chấp nhận khi ghép nối với loại dữ liệu nào.

Ví dụ: giả sử hoạt động của bạn xử lý cả văn bản và hình ảnh cho cả ý định ACTION_SENDACTION_SENDTO. Trong trường hợp này, bạn phải xác định hai bộ lọc ý định riêng biệt cho hai thao tác vì ý định ACTION_SENDTO phải sử dụng dữ liệu Uri để chỉ định địa chỉ người nhận bằng lược đồ URI send hoặc sendto. Ví dụ:

<activity android:name="ShareActivity">
    <!-- filter for sending text; accepts SENDTO action with sms URI schemes -->
    <intent-filter>
        <action android:name="android.intent.action.SENDTO"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:scheme="sms" />
        <data android:scheme="smsto" />
    </intent-filter>
    <!-- filter for sending text or images; accepts SEND action and text or image data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>

Lưu ý: Để nhận ý định ngầm ẩn, bạn phải đưa danh mục CATEGORY_DEFAULT vào bộ lọc ý định. Các phương thức startActivity()startActivityForResult() xử lý mọi ý định như thể chúng đã khai báo danh mục CATEGORY_DEFAULT. Nếu bạn không khai báo danh mục đó trong bộ lọc ý định, thì sẽ không có ý định ngầm ẩn nào được phân giải cho hoạt động của bạn.

Để biết thêm thông tin về việc gửi và nhận ý định ACTION_SEND thực hiện hành vi chia sẻ qua mạng xã hội, hãy xem bài về Nhận dữ liệu đơn giản từ ứng dụng khác. Bạn cũng có thể tìm thấy nhiều thông tin hữu ích về chia sẻ dữ liệu trong Chia sẻ dữ liệu đơn giảnChia sẻ tệp.

Xử lý Ý định trong Hoạt động của bạn

Để biết thao tác cần thực hiện trong hoạt động của mình, bạn có thể đọc Intent được dùng để bắt đầu thao tác đó.

Khi hoạt động của bạn bắt đầu, gọi getIntent() để truy xuất Intent mà đã khởi động hoạt động. Bạn có thể thực hiện việc này bất cứ lúc nào trong suốt vòng đời của hoạt động, nhưng thường thì bạn nên thực hiện trong các lệnh gọi lại sớm như onCreate() hoặc onStart().

Ví dụ:

Kotlin

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

    setContentView(R.layout.main)

    val data: Uri? = intent?.data

    // Figure out what to do based on the intent type
    if (intent?.type?.startsWith("image/") == true) {
        // Handle intents with image data ...
    } else if (intent?.type == "text/plain") {
        // Handle intents with text ...
    }
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    // Get the intent that started this activity
    Intent intent = getIntent();
    Uri data = intent.getData();

    // Figure out what to do based on the intent type
    if (intent.getType().indexOf("image/") != -1) {
        // Handle intents with image data ...
    } else if (intent.getType().equals("text/plain")) {
        // Handle intents with text ...
    }
}

Trả về kết quả

Nếu muốn trả về một kết quả cho hoạt động đã gọi hoạt động của bạn, chỉ cần gọi setResult() để chỉ định mã kết quả và kết quả Intent. Khi hoạt động của bạn hoàn tất và người dùng phải quay lại hoạt động gốc, gọi finish() để đóng (và huỷ) hoạt động của bạn. Ví dụ:

Kotlin

// Create intent to deliver some kind of result data
Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri")).also { result ->
    setResult(Activity.RESULT_OK, result)
}
finish()

Java

// Create intent to deliver some kind of result data
Intent result = new Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri"));
setResult(Activity.RESULT_OK, result);
finish();

Bạn phải luôn chỉ định mã kết quả cùng với kết quả. Nói chung, đó là RESULT_OK hoặc RESULT_CANCELED. Sau đó, bạn có thể cung cấp thêm dữ liệu bằng một Intent nếu cần.

Lưu ý: Theo mặc định, kết quả được đặt là RESULT_CANCELED. Vì vậy, nếu người dùng nhấn nút Quay lại trước khi hoàn thành thao tác và trước khi bạn đặt kết quả, hoạt động gốc sẽ nhận được kết quả là "đã huỷ".

Nếu chỉ cần trả về một số nguyên cho biết một trong vài tuỳ chọn kết quả, bạn có thể đặt mã kết quả thành bất kỳ giá trị nào cao hơn 0. Nếu bạn sử dụng mã kết quả để cung cấp một số nguyên và không cần bao gồm Intent, thì bạn có thể gọi setResult() và chỉ chuyển mã kết quả. Ví dụ:

Kotlin

setResult(RESULT_COLOR_RED)
finish()

Java

setResult(RESULT_COLOR_RED);
finish();

Trong trường hợp này, có lẽ chỉ có một vài kết quả khả dĩ, để cho mã kết quả là một số nguyên được xác định cục bộ (lớn hơn 0). Điều này rất hiệu quả khi bạn trả về một kết quả cho một hoạt động trong ứng dụng của riêng bạn, vì hoạt động mà nhận được kết quả có thể tham chiếu đến hằng số công khai để xác định giá trị của mã kết quả.

Lưu ý: Không cần kiểm tra liệu hoạt động của bạn có được bắt đầu bằng startActivity() hay startActivityForResult() hay không. Chỉ cần gọi setResult() nếu ý định để khởi động hoạt động của bạn có thể trông đợi một kết quả. Nếu hoạt động gốc có tên là startActivityForResult(), thì hệ thống sẽ mang đến cho hoạt động kết quả được bạn cung cấp cho setResult(); nếu không, kết quả sẽ bị bỏ qua.