从AndroidManifest.xml修改的过程我们可以体会到, Intent 机制即使在程序内部且显式指定接收者,也还是需要在 AndroidManifest.xml 中声明 TestActivity。这个过程并不像一个简单的函数调用,显式的 Intent 也同样经过了Android 应用程序框架所提供的支持,从满足条件的 Activity 中进行选择,如果不在 AndroidManifest.xml中进行声明,则 Android 应用程序框架找不到所需要的 Activity。
请读者通过我们的示例来逐步理解 AndroidManifest.xml在这个过程中所扮演的角色,这样有利于理解 Intent的作用 ,及后面的 Intent Filter。当然,这个例子仅仅是开始,且看下文分解 。
不同应用程序之间的Activity切换
上面的例子我们所做的是在同 一应用程序中进行 Activity 的切换,那么在不同的应用程序中,是否也能这么做呢,答案是肯定的,不过对应的代码要稍作修改。本例中我们需要两个应用程序,可利用上例中 的SimpleIntentTest作为其中之一,另外还需要写一个新的程序,来调用 SimpleIntentTest 应用程序中的 TestActivity。
我们新建程序 CrossIntentTest(注意不是新建一个类,如果是 Eclipse 环境,选择 File->New->Project新建工程),其中只有一个 Activity ,其源代码与 SimpleIntentTest.java 类似 :
packagecom.tope.samples.intent.cross;
importandroid.app.Activity;
importandroid.content.Intent;
importandroid.os.Bundle;
importandroid.view.View;
importandroid.widget.Button;
publicclassCrossIntentTestextendsActivity
implementsView.OnClickListener{
/** Called when the activity is first created. */
@Override
publicvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout. main );
Button startBtn = (Button)findViewById(R.id. start_activity );
startBtn.setOnClickListener( this);
}
publicvoidonClick(View v) {
switch(v.getId()) {
caseR.id. start_activity :
Intent intent = newIntent();
intent.setClassName( "com.tope.samples.intent.simple",
.tope.samples.intent.simple.TestActivity" );
startActivity(intent);
break;
default:
break;
}
}
}
注意比较它与 SimpleIntentTest的不同之处主要在于初始化 Intent 对象的过程:
Intent intent =newIntent();
intent.setClassName( "com.tope.samples.intent.simple",
"com.tope.samples.intent.simple.TestActivity");
startActivity(intent);
这里采用了 Intent 最简单的不带参数的构造函数 , 然后通过 setClassName() 函数来指定要启动哪个包中的哪个 Activity, 而不是像上例中的通过 Intent ( Context packageContext, Class > cls) 这个构造函数来初始化Intent 对象,这是因为,要启动的 TestActivity 与 CrossIntentTest 不在同一个包中 , 要指定 Class 参数比较麻烦 , 所以通常启动不同程序的 Activity 时便采用上面的 setClassName() 的方式。除此之外,你也可以利用Android 提供的类似的 setComponent() 方法,具体使用方法请参考 Android SDK的文档。
另外我们还需要修改SimpleIntentTest 程序中的 AndroidManifest.xml 文件,为 TestActivity 的声明添加Intent Filter ,即将原来的
修改为:
对于不同应用之间的 Activity 的切换,这里需要在 Intent Filter中 设置至少一个 Action,否则其他的应用将没有权限调用这个 Activity 。这里我们开始接触 Intent Filter和 Action 这些概念了,读者应该可以感觉到,设置Intent Filter 和 Action 主要的目的,是为了让其他需要调用这个 Activity 的程序能够顺利的调用它。除了Action之外, Intent Filter 还可以设置 Category 、 Data等,用来更加精确的匹配 Intent 与 Activity。
隐式Intent(Implicit Intent)
如果 Intent机制仅仅提供上面的显式 Intent用法的话,这种相对复杂的机制似乎意义并不是很大。确实,Intent 机制更重要的作用在于下面这种隐式的 Intent ,即Intent的发送者不指定接收者,很可能不知道也不关心接收者是谁,而由Android框架去寻找最匹配的接收者。
最简单的隐式 Intent
我们先从最简单的例子开始。 下面的 ImplicitIntentTest 程序用来启动 Android 自带的打电话功能的 Dialer 程序。
ImplicitIntentTest 程序只包含一个java 源文件 ImplicitIntentTest.java,代码如下所示:
packagecom.tope.samples.intent.implicit;
importandroid.app.Activity;
importandroid.content.Intent;
importandroid.os.Bundle;
importandroid.view.View;
importandroid.widget.Button;
publicclassImplicitIntentTestextendsActivity
implementsView.OnClickListener{
/** Called when the activity is first created. */
@Override
publicvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout. main );
Button startBtn = (Button)findViewById(R.id. dial );
startBtn.setOnClickListener( this);
}
publicvoidonClick(View v) {
switch(v.getId()) {
caseR.id. dial :
Intent intent = newIntent(Intent. ACTION_DIAL );
startActivity(intent);
break;
default:
break;
}
}
}
该程序在Intent 的使用上,与上节中的使用方式有很大的不同,即根本不指定接收者,初始化 Intent 对象时,只是传入参数,设定 Action为 Intent.ACTION_DIAL :
Intent intent = new Intent(Intent. ACTION_DIAL );
startActivity(intent);
这里使用的构造函数的原型如下:
Intent ( String action);
这里读者可暂时将action理解为描述这个 Intent 的一种方式,这种使用方式看上去比较奇怪, Intent 的发送者只是指定了 Action为 Intent.ACTION_DIAL ,那么怎么找到接收者呢?来看下面的例子。
增加一个接收者
事实上接收者如果希望能够接收某些 Intent ,需要像上节例子中一样,通过在 AndroidManifest.xml中增加Activity 的声明,并设置对应的 Intent Filter 和 Action ,才能被 Android 的应用程序框架所匹配。为了证明这一点,我们修改上一 节 SimpleIntentTest 程序中的 AndroidManifest.xml 文件,将 TestActivity 的声明部分改为:
这个截图中的第二幅表示可以选择 Dialer 或者 SimpleIntentTest 程序来完成 Intent.ACTION_DIAL ,也就是说,针对 Intent.ACTION_DIAL, Android 框架找到了两个符合条件的 Activity,因此它将这两个 Activity 分别列出,供用户选择。
回过头来看我们是怎么做到这一点的。我们仅仅在 SimpleIntentTest 程序的 AndroidManifest.xml 文件中增加了下面的两行:
category android:name="android.intent.category.DEFAULT"/>
这两行修改了原来的 Intent Filter,这样这个 Activity 才能够接收到我们发送的 Intent 。我们通过这个改动及其作用,可以进一步理解隐式 Intent, Intent Filter 及 Action, Category 等概念—— Intent 发送者设定 Action 来说明将要进行的动作,而 Intent 的接收者在 AndroidManifest.xml 文件中通过设定 Intent Filter来声明自己能接收哪些Intent 。
【编辑推荐】
【责任编辑:milk TEL:(010)68476606】