Một trong những tính năng quan trọng nhất của Android là một ứng dụng có khả năng chuyển người dùng đến ứng dụng khác dựa trên "thao tác" mà ứng dụng đó muốn thực hiện. Ví dụ: nếu ứng dụng của bạn có địa chỉ của một doanh nghiệp mà bạn muốn hiển thị trên bản đồ, thì bạn không phải tạo một hoạt động trong ứng dụng đó để hiển thị bản đồ. Thay vào đó, bạn có thể tạo một yêu cầu xem địa chỉ thông qua Intent
. Sau đó, hệ thống Android sẽ khởi động một ứng dụng có thể hiển thị địa chỉ trên bản đồ.
Như đã giải thích trong lớp học đầu tiên, Xây dựng ứng dụng đầu tiên, bạn phải dùng ý định để chuyển đổi giữa các hoạt động trong ứng dụng của mình. Thông thường, bạn thực hiện việc này bằng một ý định tường minh, trong đó xác định chính xác tên lớp của thành phần mà bạn muốn bắt đầu. Tuy nhiên, khi muốn yêu cầu một ứng dụng riêng biệt thực hiện thao tác, chẳng hạn như "xem bản đồ", bạn sẽ phải dùng ý định ngầm ẩn.
Bài học này sẽ hướng dẫn bạn cách tạo ý định ngầm ẩn cho một thao tác cụ thể, cũng như cách dùng ý định đó để bắt đầu một hoạt động thực hiện thao tác trong ứng dụng khác. Ngoài ra, bạn cũng có thể xem video được nhúng ở đây để hiểu lý do cần phải thêm hoạt động kiểm tra thời gian chạy cho ý định ngầm ẩn của mình.
Xây dựng một ý định ngầm ẩn
Ý định ngầm ẩn không khai báo tên lớp của thành phần sẽ bắt đầu mà khai báo thao tác sẽ thực hiện. Thao tác chỉ định việc bạn muốn làm, chẳng hạn như xem, chỉnh sửa, gửi hoặc tải nội dung nào đó.
Liên kết các thao tác theo ý định với dữ liệu
Ý định cũng thường bao gồm dữ liệu liên kết với thao tác, chẳng hạn như địa chỉ bạn muốn xem hoặc thư email bạn muốn gửi.
Tuỳ thuộc vào ý định mà bạn muốn tạo, dữ liệu có thể là Uri
, một trong số các loại dữ liệu khác hoặc ý định có thể không cần dữ liệu.
Nếu dữ liệu là Uri
thì bạn có thể dùng một hàm khởi tạo Intent()
đơn giản để xác định thao tác và dữ liệu.
Ví dụ: dưới đây là cách tạo ý định bắt đầu cuộc gọi điện thoại bằng việc sử dụng dữ liệu Uri
để chỉ định số điện thoại:
Kotlin
val callIntent: Intent = Uri.parse("tel:5551234").let { number -> Intent(Intent.ACTION_DIAL, number) }
Java
Uri number = Uri.parse("tel:5551234"); Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
Khi ứng dụng của bạn gọi ý định này bằng cách gọi startActivity()
, ứng dụng Điện thoại sẽ bắt đầu cuộc gọi đến một số điện thoại cụ thể.
Dưới đây là một vài ý định khác cùng với cặp thao tác và dữ liệu Uri
tương ứng:
Xem một bản đồ
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 // val location: Uri = Uri.parse("geo:37.422219,-122.08364?z=14") // z param is zoom level Intent(Intent.ACTION_VIEW, location) }
Java
// 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);
Xem một trang web
Kotlin
val webIntent: Intent = Uri.parse("https://www.android.com").let { webpage -> Intent(Intent.ACTION_VIEW, webpage) }
Java
Uri webpage = Uri.parse("https://www.android.com"); Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);
Thêm dữ liệu bổ sung vào một ý định
Những loại ý định ngầm ẩn khác yêu cầu dữ liệu "bổ sung" cung cấp loại dữ liệu khác, chẳng hạn như một chuỗi. Bạn có thể thêm một hoặc nhiều phần dữ liệu bổ sung bằng các phương thức putExtra()
khác nhau.
Theo mặc định, hệ thống sẽ xác định loại MIME thích hợp mà một ý định yêu cầu dựa trên dữ liệu Uri
đi kèm. Nếu không bao gồm Uri
trong ý định thì thông thường, bạn nên dùng setType()
để chỉ định loại dữ liệu liên kết với ý định. Việc đặt loại MIME sẽ chỉ định thêm những loại hoạt động nào sẽ nhận ý định.
Dưới đây là một số ý định khác có thêm dữ liệu bổ sung để chỉ định thao tác mong muốn:
Gửi email có tệp đính kèm
Kotlin
Intent(Intent.ACTION_SEND).apply { // The intent does not have a URI, so declare the "text/plain" MIME type type = "text/plain" putExtra(Intent.EXTRA_EMAIL, arrayOf("jan@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 }
Java
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[] {"jan@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
Tạo sự kiện trên lịch
Lưu ý: Chỉ API cấp 14 trở lên mới hỗ trợ ý định này cho sự kiện trên lịch.
Kotlin
// Event is on January 23, 2021 -- from 7:30 AM to 10:30 AM. Intent(Intent.ACTION_INSERT, Events.CONTENT_URI).apply { val beginTime: Calendar = Calendar.getInstance().apply { set(2021, 0, 23, 7, 30) } val endTime = Calendar.getInstance().apply { set(2021, 0, 23, 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") }
Java
// Event is on January 23, 2021 -- from 7:30 AM to 10:30 AM. Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI); Calendar beginTime = Calendar.getInstance(); beginTime.set(2021, 0, 23, 7, 30); Calendar endTime = Calendar.getInstance(); endTime.set(2021, 0, 23, 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");
Lưu ý: Bạn cần phải xác định Intent
cụ thể nhất có thể. Ví dụ: nếu muốn hiển thị một hình ảnh bằng ý định ACTION_VIEW
, bạn nên chỉ định loại MIME là image/*
. Việc này sẽ tránh trường hợp ý định kích hoạt các ứng dụng có thể "xem" loại dữ liệu khác (như ứng dụng bản đồ).
Bắt đầu một hoạt động bằng ý định
Sau khi bạn tạo Intent
và đặt thông tin bổ sung, hãy gọi startActivity()
để gửi thông tin đó đến hệ thống:
Kotlin
startActivity(intent)
Java
startActivity(intent);
Xử lý tình huống trong đó không ứng dụng nào có thể nhận ý định
Mặc dù nhiều ý định được xử lý thành công bởi một ứng dụng khác đã cài đặt trên thiết bị (chẳng hạn như ứng dụng điện thoại, email hoặc lịch), nhưng ứng dụng của bạn nên chuẩn bị cho tình huống trong đó không hoạt động nào có thể xử lý ý định của ứng dụng. Mỗi khi bạn gọi một ý định, hãy sẵn sàng nắm bắt ActivityNotFoundException
. Ngoại lệ này sẽ xảy ra nếu không hoạt động nào khác có thể xử lý ý định của ứng dụng:
Kotlin
try { startActivity(intent) } catch (e: ActivityNotFoundException) { // Define what your app should do if no activity can handle the intent. }
Java
try { startActivity(intent); } catch (ActivityNotFoundException e) { // Define what your app should do if no activity can handle the intent. }
Sau khi bạn nắm bắt ngoại lệ này, hãy quyết định những việc ứng dụng nên làm tiếp theo. Bước tiếp theo này phụ thuộc vào các đặc điểm cụ thể của ý định mà bạn cố gọi. Ví dụ: nếu bạn biết một ứng dụng cụ thể có thể xử lý ý định, hãy cung cấp đường liên kết để người dùng tải ứng dụng đó xuống. Bạn có thể tìm hiểu thêm về cách liên kết đến sản phẩm của bạn trên Google Play.
Hộp thoại phân định
Nếu xác định được nhiều hoạt động có thể xử lý ý định, thì hệ thống sẽ hiển thị một hộp thoại (đôi khi gọi là "hộp thoại phân định") để người dùng chọn ứng dụng sẽ sử dụng, như minh hoạ trong hình 1. Nếu chỉ có một hoạt động xử lý ý định, thì hệ thống sẽ bắt đầu ngay hoạt động đó.
Ví dụ đầy đủ
Dưới đây là một ví dụ đầy đủ cho thấy cách tạo ý định xem bản đồ, xác minh rằng hiện có một ứng dụng để xử lý ý định, sau đó khởi động ứng dụng đó:
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) // Try to invoke the intent. try { startActivity(mapIntent) } catch (e: ActivityNotFoundException) { // Define what your app should do if no activity can handle the intent. }
Java
// 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); // Try to invoke the intent. try { startActivity(mapIntent); } catch (ActivityNotFoundException e) { // Define what your app should do if no activity can handle the intent. }
Hiển thị trình chọn ứng dụng
Xin lưu ý rằng khi bạn bắt đầu một hoạt động bằng cách chuyển Intent
cho startActivity()
và có nhiều ứng dụng phản hồi ý định đó, người dùng có thể chọn ứng dụng sẽ sử dụng theo mặc định (bằng cách chọn hộp đánh dấu) ở cuối hộp thoại; xem hình 1). Việc này rất hữu ích khi thực hiện một thao tác mà mỗi lần người dùng thường muốn sử dụng cùng một ứng dụng, chẳng hạn như khi mở trang web (người dùng có khả năng sẽ chỉ sử dụng một trình duyệt web) hoặc chụp ảnh (người dùng có khả năng sẽ ưu tiên một máy ảnh).
Tuy nhiên, nếu thao tác cần thực hiện có thể được nhiều ứng dụng xử lý và mỗi lần người dùng có thể ưu tiên một ứng dụng khác – chẳng hạn như với thao tác "chia sẻ", người dùng có thể chia sẻ một mục thông qua nhiều ứng dụng – bạn nên hiển thị rõ ràng hộp thoại trình chọn như minh hoạ trong hình 2. Hộp thoại trình chọn buộc người dùng mỗi lần đều phải chọn ứng dụng sẽ sử dụng cho thao tác (người dùng không thể chọn ứng dụng mặc định cho thao tác đó).
Để hiển thị trình chọn, hãy tạo Intent
bằng createChooser()
và chuyển ý định đó vào startActivity()
. Ví dụ:
Kotlin
val intent = Intent(Intent.ACTION_SEND) // Create intent to show chooser val chooser = Intent.createChooser(intent, /* title */ null) // Try to invoke the intent. try { startActivity(chooser) } catch (e: ActivityNotFoundException) { // Define what your app should do if no activity can handle the intent. }
Java
Intent intent = new Intent(Intent.ACTION_SEND); // Create intent to show chooser Intent chooser = Intent.createChooser(intent, /* title */ null); // Try to invoke the intent. try { startActivity(chooser); } catch (ActivityNotFoundException e) { // Define what your app should do if no activity can handle the intent. }
Đoạn mã này hiển thị một hộp thoại chứa danh sách các ứng dụng phản hồi ý định được chuyển vào phương thức
createChooser()
. Tham số title
có thể được cung cấp nếu thao tác không phải là
ACTION_SEND
hoặc
ACTION_SEND_MULTIPLE