要启动一个Activity有两种方法,一种是通过显式Intent启动,而另一种是通过隐式Intent启动。
一、显示Intent
显示Intent是明确目标Activity的类名。
1、通过Intent(Context packageContext, Class> cls)构造方法
该方法是最常用的,只适用于当前应用,只能启动本应用中的Activity。
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
2、通过Intent的setComponent()方法
创建Component对象的方法,常用的是前面三个构造方法。
ComponentName componentName = new ComponentName(this, SecondActivity.class);
// 或ComponentName componentName = new ComponentName(this, "com.example.app.SecondActivity");
// 或ComponentName componentName = new ComponentName(this.getPackageName(), "com.example.app.SecondActivity");
Intent intent = new Intent();
intent.setComponent(componentName);
startActivity(intent);
3、通过Intent的setClass/setClassName方法
Intent intent = new Intent();
intent.setClass(this, SecondActivity.class);
// 或intent.setClassName(this, "com.example.app.SecondActivity");
// 或intent.setClassName(this.getPackageName(), "com.example.app.SecondActivity");
startActivity(intent);
二、隐式Intent
隐式Intent通过设置Action、Data、Category,让系统来筛选出合适的Activity。筛选是根据所有的
1、通过Action调用拨打电话,打开网页,发送邮件
Uri number = Uri.parse("tel:5551234");
Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
Uri website = Uri.parse("http://xxxxx.com");
Intent webIntent = new Intent(Intent.ACTION_VIEW, website);
Uri emailUri = Uri.parse("mailto:[email protected]");
intent emailIntent = new Intent(Intent.ACTION_SENDTO, emailUri);
2、默认的情况下,系统基于所包含的 Uri 数据确定Intent需要的相应 MIME 类型。如果Intent中不包含Uri,应该使用 setType()来指定与Intent相关的数据。设置MIME类型指定那一种类型的activity可以接收这个Intent。
发送一个邮件附件:
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"[email protected]"});
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"));
这个Intent没有Uri,所以声明MIME类型为 “text/plain”
注意:定义Intent时要尽可能具体,这是非常重要的。比如,如果你使用ACTION_VIEW inten想要展示一张图片,那你就应该指定MIME类型为 image/*. 这就防止了你的app被Intent触发之后意外地查看到其它的数据类型。
3、注意异常
1)、捕获异常
Intent intent = new Intent("asasasas");
try{
startActivity(intent);
} catch(ActivityNotFoundException e) {
Toast.makeText(this, "找不到对应的Activity", Toast.LENGTH_SHORT).show();
}
2)、先判断是否有匹配的activity
Intent intent = new Intent(Intent.ACTION_DIAL);
ComponentName componentName = intent.resolveActivity(getPackageManager());
if(componentName != null) {
String className = componentName.getClassName();
Toast.makeText(this, className, Toast.LENGTH_SHORT).show();
}
3)、通过PackageManager的queryIntentActivities方法判断是否有匹配的activity
PackageManager packageManager = getPackageManager();
List activities = packageManager.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
boolean isIntentSafe = activities.size() > 0;
注意:在显式Intent中也要注意避免出现ActivityNotFoundException 异常,可能在创建ComponentName时参数有错,虽然ComponentName不为null,但启动的时候找不到对应的activity则会抛出该异常。
开发文档中建议:
对 Intent
对象调用 resolveActivity()
。如果结果为非空,则至少有一个应用能够处理该 Intent,且可以安全调用 startActivity()
。 如果结果为空,则不应使用该 Intent。如有可能,您应停用发出该 Intent 的功能。
// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");
// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(sendIntent);
}
三、使用应用选择器
如果有多个应用响应隐式 Intent,则用户可以选择要使用的应用,并将其设置为该操作的默认选项。 如果用户可能希望今后一直使用相同的应用执行某项操作(例如,打开网页时,用户往往倾向于仅使用一种网络浏览器),则这一点十分有用。
但是,如果多个应用可以响应 Intent,且用户可能希望每次使用不同的应用,则应采用显式方式显示选择器对话框。 选择器对话框每次都会要求用户选择用于操作的应用(用户无法为该操作选择默认应用)。 例如,当应用使用 ACTION_SEND
操作执行“共享”时,用户根据目前的状况可能需要使用另一不同的应用,因此应当始终使用选择器对话框,如图 所示。
要显示选择器,请使用 createChooser()
创建 Intent
,并将其传递给 startActivity()
。例如:
Intent sendIntent = 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 the chooser dialog
Intent chooser = Intent.createChooser(sendIntent, title);
// Verify the original intent will resolve to at least one activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
}