Như đã biết thông thường một ứng dụng Android sẽ có nhiều Activity,
mỗi Activity
chịu trách nhiệm vẽ màn hình giao diện người dùng và xử lý các sự kiện diễn ra trên giao diện đó, chẳng hạn như vẽ bản đồ, chụp ảnh…v.v Để có thể chuyển đổi qua lại giữa các Activity
thì chúng ta dùng lớp Intent
(tiếng Anh có nghĩa là dự định, tức là dự định làm một cái gì đó), Intent
không những cho phép chúng ta gọi tới các Activity
trong cùng một ứng dụng mà còn cho phép gọi tới những Activity
ở các ứng dụng khác nữa.
Mở một ứng dụng khác
Chúng ta đã từng sử dụng lớp Intent
để di chuyển qua lại giữa các Activity,
làm như thế là chúng ta đã gọi Intent
một cách tường minh, tức là khai báo rõ ràng tên lớp Activity
sẽ được mở bởi Intent.
Còn đôi khi chúng ta muốn mở một ứng dụng khác thì lúc đó chúng ta sử dụng Intent “ngầm”.
Mở Intent ngầm
Các đối tượng Intent
ngầm sẽ không nhận tên của một lớp Activity
nào cả, mà thay vào đó là một hành động nào nó, chẳng hạn như mở ứng dụng bản đồ, mở trình duyệt, mở ứng dụng gửi mail… và các đối tượng Intent
này cũng có thể gửi dữ liệu đến các hành động đó nữa, ví dụ như mở bản đồ tại thành phố Hà Nội, mở trình duyệt tại địa chỉ phocode.com…v.v Thường thì dữ liệu gửi đi sẽ được lưu trong lớp android.net.Uri.
Ví dụ 1:
package com.phocode; import android.content.Intent; import android.net.Uri; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Uri number = Uri.parse("tel:00841218749385"); Intent callIntent = new Intent(Intent.ACTION_DIAL, number); startActivity(callIntent); } }
Đoạn code trên sẽ mở màn hình gọi điện với số điện thoại được chỉ định trong đối tượng Uri.
Ví dụ 2:
package com.phocode; import android.content.Intent; import android.net.Uri; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Uri webpage = Uri.parse("https://phocode.com"); Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage); startActivity(webIntent); } }
Đoạn code trên sẽ mở trình duyệt web mặc định tới website có địa chỉ được chỉ định trong đối tượng Uri
.
Tham số khởi tạo đối tượng Intent
ở đây không phải là tên một lớp Activity nào, mà là một hằng số chỉ định một hành động nào đó, ví dụ như Intent.ACTION_VIEW
là mở trình duyệt web, Intent.ACTION_DIAL
là mở trình gọi điện… tham số thứ 2 là một đối tượng Uri
mang theo dữ liệu cho hành động đó. Danh sách các đối tượng hành động cùng với kiểu dữ liệu Uri
có thể xem ở đây.
Một số đối tượng hành động có thể nhận thêm nhiều dữ liệu chứ không chỉ có một, dữ liệu đó không bắt buộc nhưng có thể truyền đi, lúc đó chúng ta truyền vào bằng phương thức putExtra()
như thường, ví dụ:
package com.phocode; import android.content.Intent; import android.net.Uri; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent emailIntent = new Intent(Intent.ACTION_SEND); emailIntent.setType("text/plain"); emailIntent.putExtra(Intent.EXTRA_EMAIL, "admin@example.com"); emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Hello"); emailIntent.putExtra(Intent.EXTRA_TEXT, "Nice to meet you"); startActivity(emailIntent); } }
Đoạn code trên sẽ mở ứng dụng gửi tin nhắn.
Nếu hệ điều hành thấy có nhiều hơn một ứng dụng có thể mở được đối tượng Intent
này thì hệ điều hành sẽ mở một hộp thoại chứa danh sách các ứng dụng đó cho người dùng chọn, còn nếu chỉ có một ứng dụng có thể mở được thì hệ điều hành sẽ chạy ứng dụng đó luôn.
Kiểm tra Intent có thể mở được hay không
Hệ điều hành Android đảm bảo rằng luôn luôn sẽ có ứng dụng được cài sẵn có thể mở được dữ liệu được gửi đi bởi đối tượng Intent
ngầm. Tuy nhiên chúng ta nên kiểm tra trước thì sẽ tốt hơn bởi vì nếu không có ứng dụng nào có thể mở được đối tượng Intent
của chúng ta thì chương trình của bạn sẽ bị crash (tức là bị tắt mà không rõ lý do).
Để biết được đối tượng Intent mà chúng ta định gọi có thể mở được bởi ứng dụng nào đó hay không thì chúng ta dùng phương thức queryIntentActivities()
của lớp android.content.pm.PackageManager
và truyền vào đối tượng Intent
và chế độ kiểm tra. Ví dụ:
package com.phocode; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.app.Activity; import android.os.Bundle; import android.widget.Toast; import java.util.List; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Uri webpage = Uri.parse("https://phocode.com"); Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage); PackageManager packageManager = getPackageManager(); List activities = packageManager.queryIntentActivities(webIntent, PackageManager.MATCH_DEFAULT_ONLY); boolean isIntentSafe = activities.size() > 0; Toast.makeText(getApplicationContext(), (isIntentSafe ? "Intent is safe" : "Intent is not safe"), Toast.LENGTH_LONG).show(); } }
Chúng ta có thể lấy đối tượng PackageManager
từ phương thức getPackageManager()
của lớp Activity.
List activities = packageManager.queryIntentActivities(webIntent, PackageManager.MATCH_DEFAULT_ONLY); boolean isIntentSafe = activities.size() > 0;
Phương thức queryIntentActivities()
sẽ trả về một đối tượng List
chứa danh sách các lớp Activity
có thể mở được đối tượng Intent
của chúng ta. Ở đây chúng ta chỉ cần xem nếu danh sách này khác rỗng thì tức là đối tượng Intent
của chúng ta có thể mở được
Mở hộp thoại chọn ứng dụng
Ở ví dụ gửi tin nhắn ở trên chúng ta thấy có 2 ứng dụng có thể mở đối tượng Intent
của chúng ta nên hệ điều hành sẽ hiển thị một hộp thoại cho phép người dùng lựa chọn ứng dụng để mở, ngoài ra ở dưới hộp thoại còn có 2 nút là Just Once và Always, nút Just Once có nghĩa là ngay tại thời điểm đó chỉ chọn ứng dụng đó để sử dụng, còn các lần sau thì hệ điều hành sẽ mở lại hộp thoại để người dùng chọn ứng dụng khác, còn nút Always tức là từ nay về sau hệ điều hành sẽ sử dụng ứng dụng đó luôn chứ không bắt người dùng phải chọn lại nữa.
Tuy nhiên nếu muốn chúng ta có thể yêu cầu hệ điều hành mỗi lần chạy sẽ phải mở hộp thoại chọn ứng dụng chứ không sử dụng ứng dụng được gắn mác Always.
Để làm việc này chúng ta tạo một đối tượng Intent và gọi phương thức createChooser()
rồi truyền vào phương thức này đối tượng Intent
mà chúng ta muốn sử dụng. Ví dụ:
package com.phocode; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.app.Activity; import android.os.Bundle; import android.widget.Toast; import java.util.List; public class MainActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent emailIntent = new Intent(Intent.ACTION_SEND); emailIntent.setType("text/plain"); emailIntent.putExtra(Intent.EXTRA_EMAIL, "admin@example.com"); emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Hello"); emailIntent.putExtra(Intent.EXTRA_TEXT, "Nice to meet you"); startActivity(emailIntent); String title = "Choose app to open"; Intent chooser = Intent.createChooser(emailIntent, title); if(emailIntent.resolveActivity(getPackageManager()) != null) startActivity(chooser); } }
Phương thức createChooser()
sẽ nhận đối tượng Intent
mà chúng ta muốn mở và một chuỗi hiển thị tiêu đề cho hộp thoại.
if(emailIntent.resolveActivity(getPackageManager()) != null) startActivity(chooser);
Đoạn code trên chỉ là kiểm tra xem đối tương Intent
của chúng ta có ứng dụng nào có thể mở được hay không thôi, nếu có thì mới cho hiển thị hộp thoại chọn ứng dụng.
Hộp thoại chọn ứng dụng theo cách này sẽ không có 2 nút Just Once và Always.