Nhận dữ liệu từ các ứng dụng khác

Cũng giống như việc gửi dữ liệu đến các ứng dụng khác, ứng dụng cũng có thể nhận dữ liệu từ các ứng dụng khác. Hãy nghĩ về cách người dùng tương tác với ứng dụng của bạn và loại dữ liệu bạn muốn nhận từ các ứng dụng khác. Ví dụ: một ứng dụng mạng xã hội có thể quan tâm đến việc nhận nội dung văn bản, chẳng hạn như một URL cho web thú vị, từ một ứng dụng khác.

Trong một ứng dụng sử dụng tính năng Điều hướng trong Compose, việc nhận dữ liệu do một ứng dụng khác gửi là một quy trình gồm 3 bước:

  1. Khai báo <intent-filter> trong tệp kê khai: Bạn vẫn phải thêm bộ lọc ý định vào hoạt động trong tệp AndroidManifest.xml. Thao tác này sẽ cho hệ điều hành Android biết rằng ứng dụng của bạn có thể nhận các thao tác cụ thể (như ACTION_SEND) và loại MIME (như text/plain).

  2. Xác định navDeepLink trong biểu đồ Điều hướng trong Compose: Đính kèm navDeepLink khớp với thao tác và loại MIME trực tiếp vào đích đến có thể kết hợp sẽ hiển thị nội dung. NavController sẽ tự động chặn ý định đến và chuyển người dùng trực tiếp đến màn hình đó.

  3. Trích xuất tải trọng dữ liệu đến: Trên màn hình đích, hãy truy cập vào các phần bổ sung của ý định (chẳng hạn như EXTRA_TEXT hoặc EXTRA_STREAM) để truy xuất nội dung được chia sẻ và cập nhật trạng thái giao diện người dùng.

Mục tiêu Chia sẻ trực tiếp là các đường liên kết sâu đến một hoạt động cụ thể trong ứng dụng của bạn. Các mục tiêu này thường đại diện cho một người hoặc một nhóm và Trang chia sẻ nội dung trong Android sẽ hiển thị các mục tiêu đó. Ví dụ: một ứng dụng nhắn tin có thể cung cấp mục tiêu Chia sẻ trực tiếp cho một người, liên kết sâu trực tiếp đến cuộc trò chuyện với người đó. Xem phần Cung cấp mục tiêu Chia sẻ trực tiếp để biết hướng dẫn chi tiết.

Hỗ trợ các loại MIME

Tốt nhất là ứng dụng phải có khả năng nhận được nhiều loại MIME nhất có thể. Ví dụ: một ứng dụng nhắn tin được thiết kế để gửi văn bản, hình ảnh và video lý tưởng nhất là hỗ trợ nhận text/*, image/* và video/*. Dưới đây là một vài loại MIME phổ biến để gửi và nhận dữ liệu trong Android.

Bộ nhận đăng ký Người gửi gửi
text/*
  • text/plain
  • text/rtf
  • text/html
  • text/json
image/*
  • image/jpg
  • image/png
  • image/gif
video/*
  • video/mp4
  • video/3gp
Đuôi tệp được hỗ trợ application/pdf

Xem sổ đăng ký chính thức của IANA về các loại nội dung nghe nhìn MIME.

Tạo mục tiêu chia sẻ hiệu quả

Khi người dùng nhấn vào một mục tiêu chia sẻ liên kết với một hoạt động cụ thể, hãy cho phép họ xác nhận và chỉnh sửa nội dung được chia sẻ trước khi ứng dụng của bạn sử dụng nội dung đó. Điều này đặc biệt quan trọng đối với dữ liệu văn bản.

Nhận dữ liệu trong ứng dụng

Để nhận dữ liệu được chia sẻ trong một ứng dụng bằng Compose, bạn cần khai báo bộ lọc ý định trong tệp kê khai, định tuyến ý định đến màn hình thích hợp bằng đường liên kết sâu và trích xuất tải trọng từ ý định để cập nhật giao diện người dùng.

Cập nhật tệp kê khai

Bộ lọc ý định thông báo cho hệ thống biết những ý định mà một thành phần ứng dụng chấp nhận. Tương tự như cách bạn tạo ý định bằng hành động ACTION_SEND trong bài học Gửi dữ liệu đến các ứng dụng khác, bạn tạo bộ lọc ý định để nhận ý định bằng hành động này. Bạn xác định bộ lọc ý định trong tệp kê khai bằng phần tử <intent-filter>. Ví dụ: nếu ứng dụng của bạn xử lý việc nhận nội dung văn bản, thì tệp kê khai bao gồm một hoặc nhiều hình ảnh thuộc bất kỳ loại nào sẽ có dạng như đoạn mã sau:

<activity android:name=".ui.MyActivity" android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.SEND_MULTIPLE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
</activity>

Khi một ứng dụng khác cố gắng chia sẻ bất kỳ nội dung nào trong số này bằng cách tạo một ý định và truyền ý định đó đến startActivity(), ứng dụng của bạn sẽ được liệt kê dưới dạng một lựa chọn trong Trang chia sẻ nội dung trong Android hoặc trình phân giải ý định. Nếu người dùng chọn ứng dụng của bạn, thì thao tác này sẽ bắt đầu hoạt động tương ứng (.ui.MyActivity trong ví dụ trước). Sau đó, bạn có thể xử lý nội dung một cách phù hợp trong mã và giao diện người dùng.

Trong tính năng Điều hướng trong Compose, hãy đính kèm trực tiếp navDeepLink vào đích đến có thể kết hợp sẽ hiển thị nội dung. Khi một ứng dụng khác chia sẻ dữ liệu được chia sẻ khớp với bộ lọc ý định của bạn, tính năng Điều hướng trong Compose sẽ định tuyến người dùng trực tiếp đến đích đến này:

navDeepLink khớp với thao tác và loại MIME của ý định gửi đến để chuyển đến đúng màn hình đích. Khi đã ở đích đến đó, trình xử lý của bạn sẽ kiểm tra ý định để xác định tải trọng nào đã nhận được (chẳng hạn như một hình ảnh so với nhiều hình ảnh) và trích xuất các thành phần bổ sung tương ứng.

Xử lý nội dung đến

Để truy xuất nội dung do Intent phân phối, hãy đọc hoạt động hiện tại từ LocalActivity.current trong thành phần kết hợp, sau đó kiểm tra ý định để xác định việc cần làm tiếp theo. Nếu hoạt động này có thể được bắt đầu từ các phần khác của hệ thống (chẳng hạn như trình chạy), hãy cân nhắc điều này khi kiểm tra ý định.

Hãy đặc biệt chú ý kiểm tra dữ liệu đến: có thể loại MIME không chính xác hoặc hình ảnh được gửi có thể cực kỳ lớn. Xử lý dữ liệu nhị phân hoặc các thao tác I/O nặng (chẳng hạn như giải mã hình ảnh lớn hoặc ghi tệp) không đồng bộ bằng cách sử dụng coroutine (chẳng hạn như Dispatchers.IO) thay vì trên luồng giao diện người dùng chính.

@Composable
fun SharesheetHandler() {
    val activity = LocalActivity.current
    val intent = activity?.intent

    when (intent?.action) {
        Intent.ACTION_SEND -> {
            if (intent.type == "text/plain") {
                handleSendText(intent) // Handle text being sent
            } else if (intent.type?.startsWith("image/") == true) {
                handleSendImage(intent) // Handle single image being sent
            }
        }

        Intent.ACTION_SEND_MULTIPLE -> {
            if (intent.type?.startsWith("image/") == true) {
                handleSendMultipleImages(intent) // Handle multiple images being sent
            }
        }

        else -> {
            // Handle other intents, such as being started from the home screen
        }
    }
}

private fun handleSendText(intent: Intent) {
    intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
        // Update UI state with the shared text
    }
}

private fun handleSendImage(intent: Intent) {
    val imageUri = IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java)
    imageUri?.let {
        // Update UI state with the shared image
    }
}

private fun handleSendMultipleImages(intent: Intent) {
    val imageUris =
        IntentCompat.getParcelableArrayListExtra(intent, Intent.EXTRA_STREAM, Uri::class.java)
    imageUris?.let {
        // Update UI state with the shared images
    }
}

Khi trích xuất dữ liệu nhị phân hoặc URI từ các ý định bổ sung (chẳng hạn như EXTRA_STREAM), hãy sử dụng IntentCompat.getParcelableExtra() hoặc IntentCompat.getParcelableArrayListExtra() từ thư viện AndroidX Core, như trong các hàm handleSendImage và handleSendMultipleImages trước đó. Android 13 (cấp độ API 33) không dùng phương thức Intent.getParcelableExtra(String) không có tham số nữa mà thay bằng các phương thức an toàn về kiểu, lấy loại lớp dự kiến.

Việc cập nhật giao diện người dùng sau khi nhận dữ liệu có thể đơn giản như cập nhật trạng thái để điền sẵn TextField hoặc phức tạp như áp dụng bộ lọc cho hình ảnh. Điều gì xảy ra tiếp theo là tuỳ thuộc vào ứng dụng của bạn.

Chia sẻ URL của ảnh chụp màn hình

Khi chụp ảnh màn hình, bạn có thể chia sẻ ảnh chụp màn hình và mọi URL liên quan. Điều này mang lại trải nghiệm phong phú hơn cho người dùng. Khi nhận được URL, hãy nhớ lấy trường EXTRA_TEXT từ ý định, như trong ví dụ sau:

IntentCompat.getParcelableExtra(intent, Intent.EXTRA_STREAM, Uri::class.java).let {
    // Handle the EXTRA_TEXT as well
    val extraText = intent.getCharSequenceExtra(Intent.EXTRA_TEXT)
    // Update UI state with the shared image and the EXTRA_TEXT if available
}

Đảm bảo người dùng nhận ra ứng dụng của bạn

Ứng dụng của bạn được thể hiện bằng biểu tượng và nhãn trong Trang chia sẻ nội dung trong Android và trình phân giải ý định. Cả hai đều được xác định trong tệp kê khai. Bạn có thể đặt nhãn cho hoạt động hoặc bộ lọc ý định để cung cấp thêm thông tin bối cảnh.

Kể từ Android 10 (API cấp 29), Trang chia sẻ nội dung trong Android chỉ sử dụng các biểu tượng được đặt trong tệp kê khai trên thẻ application của bạn. Android bỏ qua các biểu tượng được đặt trên thẻ intent-filter và activity.

Nhận nội dung đa dạng thức

Mặc dù ý định ACTION_SEND cho phép nhận dữ liệu từ Trang chia sẻ nội dung trong Android và trình phân giải ý định ở cấp hoạt động hoặc cấp điều hướng, nhưng ứng dụng cũng có thể nhận nội dung đa dạng thức (chẳng hạn như hình ảnh, video, tệp âm thanh và văn bản được tạo kiểu) thông qua các hoạt động tương tác trực tiếp với giao diện người dùng. Các cơ chế này bao gồm:

  • Dán từ bảng nhớ tạm (trình đơn chạm và giữ)
  • Chèn nội dung nghe nhìn trực tiếp từ bàn phím phần mềm (IME), chẳng hạn như hình dán hoặc ảnh GIF
  • Kéo và thả nội dung từ một ứng dụng khác ở chế độ nhiều cửa sổ hoặc chia đôi màn hình

Trong giao diện người dùng dựa trên Khung hiển thị, Android 12 (cấp độ API 31) và AndroidX Core 1.7 giới thiệu API OnReceiveContentListener hợp nhất. Trình nghe này hợp nhất việc xử lý nội dung từ bảng nhớ tạm, bàn phím và thao tác kéo và thả vào một lệnh gọi lại duy nhất. Để biết hướng dẫn chi tiết về cách triển khai tính năng này trong Khung hiển thị, hãy xem phần Nhận nội dung đa dạng thức.

Trong Jetpack Compose, bạn có thể xử lý việc nhận nội dung đa dạng thức được chèn vào các thành phần giao diện người dùng (chẳng hạn như trường văn bản) bằng cách sử dụng đối tượng sửa đổi Modifier.contentReceiver hoặc đối tượng sửa đổi kéo và thả.