android 基础03 -- Intent

时间:2023-03-09 02:15:39
android 基础03 -- Intent

Android 中的 Intent 是将要执行的操作的一种抽象的描述,是一个用于Android 各个组件之间传递消息的对象。

Intent 的基本用法

Intent 基本的使用方法主要有三种:

  • 启动一个新的 Activity 实例。

      通过将 Intent 传入 startActivity()中可以启动一个新的实例,其中的 Intent 描述了要启动的 Activity,并包含了一些必要的数据

  • 启动一个服务

       通过将 Intent 传入 startService() 中可以启动一个服务器执行一些一次性的操作(如下载文件等)。其中的 Intent 描述了要启动的服务,并包含了一些必要的数据。

  • 发送广播

      广播指那些所有应用都可以接受的消息,通过将 Intent 传递给 sendBroadcast()、sendOrderedBroadcast() 或 sendStickyBroadcast(),可以将广播传递给其他应用。

Intent 的类型

  Intent 可以分为两种类型:

  • 显式Intent(Explicit Intents)

      通过完全限定类名来指定要启动的组件。当明确的知道要启动的 ActivityService 的名称时可以使用显式的 Intent。例如,启动一个 ActivityService 去响应用户的操作。创建显式 Intent 启动 Activity 或 Service,系统会立即启动 Intent 指定的组件。

  • 隐式 Intent(Implicit Intents)

      不指定特定的组件,而是声明要执行的操作,从而允许其它的组件来处理。例如发送一个 E-mail,则可以使用隐式的 Intent,允许其它的应用来处理该操作。

显式 Intent的使用

  下面的代码表示,当点击按钮 Next 时,启动一个显式的 Intent,转向一个指定的页面

	Button Next = (Button)findViewById(R.id.Next);
Next.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view){
Intent intent = new Intent(firstActivity.this,secondActivity.class);
startActivity(intent);
}
});
隐式 Intent 的使用

  下面的代码,当点击按钮 Broswer 时,启动一个隐式的 Intent,打开一个 Web 页面

	Broswer Next = (Button)findViewById(R.id.Broswer);
Next.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view){
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.Parse("http://www.baidu.com");
startActivity(intent);
}
});

   创建隐式的 Intent时,Android 系统将 Intent 中指定的内容与设备上其它应用的 AndroidManifest.xml 中声明的 Intent-filter 进行比较,如果 Intent 与声明的 Intent-filter 匹配,则启动对应的组件,并将 Intent传递给它。如果存在多个 intent-filter匹配,则提供一个选择器供用户选择使用哪个应用来处理。

注意:显式的 Intent 总是能够传递给它的目标,而不管目标组件的 intent-filter 是如何定义的

android 基础03 -- Intent

  用户可能没有任何应用可以处理你发送到 startActivity 的隐式 Intent,如果出现这种情况,则调用会失败,且 应用会崩溃 ,因此,在发出一个隐式的 Intent 之前最好验证一下当前设备是否具有可以处理该 Intent 请求的应用。可以调用 Intent 对象的 resolveActivity() 来验证,如果方法返回 null,则说明当前设备没有可以处理该 Intent 的应用,必要情况下应该停止发出此 Intent,如果 返回不为空,则表示至少存在一个可以处理该 Intent的应用。

 

注意:Android 官方建议,通过显式的 Intent 来启动服务,并且不要为服务声明 Intent-Filter,因为使用隐式的 Intent 启动服务时,无法确定响应 Intent* 的服务,用户也无法看到启动的服务,存在一定的安全隐患。在 Android 5.0 开始,使用隐式的 Intent 调用 bindService()将会发生异常。

接收隐式的 Intent

  要声明应用可以处理哪些隐式的 Intent,需要在 AndroidManifest.xml 中使用 intent-filter 属性为组件声明一个或多个 intent 过滤器,每个 intent 过滤器都可以根据 Intent 的操作、数据和类别指定自身接收的 Intent。仅当隐式的 Intent 匹配某一 Intent的规则时,Android 系统才会将 隐式的 Intent 传递给应用组件。如果一个组件没有声明任何的 Intent 过滤器,那么它只能通过显式Intent 的方式启动。

  每个 Intent 过滤器均由 AndroidMainfest.xml 中的 intent-filter 属性标签来定义,并嵌套在响应的最近中(例如 Activity)

	<Activity android:name=".second">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<catetory android:name="android.intent.category.DEFAULT"/>
<data android:scheme="http"/>
</intent-filter>
     </Activity>

intent-filter 中可以使用的属性

  • action

      在 name 属性中,声明接受的 Intent 操作。该值必须是操作的文本字符串值,而不是类常量。

  • data

  使用一个或多个指定数据 URI 各个方面(scheme、host、port、path 等)和 MIME 类型的属性,声明接受的数据类型。data 标签内的 scheme等几个属性均为可选,但存在线性依赖关系,具体如下:

1. 如果未指定 scheme 则忽略 host
2. 如果未指定 host 则忽略 port
3. 如果未指定 scheme 和 host,则忽略 path
  • category

  在 name 属性中,声明接受的 Intent 类别。该值必须是操作的文本字符串值,而不是类常量。

  在定义 intent-filter 时,我们可以使用上述属性中的一个或多个进行任意的组合,系统通过将

Intent 与 intent-filter 中定义的属性规则进行测试,只有通过所有的测试时,才会将 Intent 传递给该组件。


注意:使用 Intent 过滤器时,无法安全地防止其他应用启动组件。如果需要保证只有自己的应用可以访问应用内部的某些组件,可以针对该组件将其 exported 属性设置为 false


使用 Intent 在 Activity 间传递数据

  • 使用 Intent 向下一个 Activity 传递数据

  下面的例子,当我们点击 Next 按钮时,将输入框的值传入下一个 second 页面

	Button btn = (Button)findViewById(R.id.Next);
final EditText UName = (EditText)findViewById(R.id.UName);
btn.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view){
Intent transferData = new Intent(MainActivity.this,second.class);
transferData.putExtra("data",UName.getText().toString());
startActivity(transferData);
} });

  在 second 页面中,我们可以通过以下的方式来获取传入的数据

	Intent intent = getIntent();
String UName = intent.getStringExtra("data");
  • 使用 Intent 回传数据给上一个 Activity

  有时候我们希望启动一个新的 Activity 来处理一些数据,然后可以回传处理结果到当前的 Activity,这是我们便可以通过 Activity 的 startActivityForResult 来实现。

  下面的例子,在第一个 Activity 中点击按钮时将文本框中的内容传入一个新的 Activity,在第二个 Activity 中对第一个 Activity 传过来的内容进行处理,然后回传给第一个 Activity。

  第一个 Activity:

	Button btn = (Button)findViewById(R.id.Click);
final EditText UName = (EditText)findViewById(R.id.UName);
btn.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view){
Intent intent = new Intent(MainActivity.this,second.class);
intent.putExtra("data",UName.getText().toString());
startActivityForResult(intent,1);//第二个参数表示一个请求码,必须唯一
} });

  第二个 Activity

	Button SayBtn = (Button)findViewById(R.id.Say);
SayBtn.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
String UName = getIntent().getStringExtra("data");
Intent intent = new Intent();
intent.putExtra("return_data","我明白了,你的名字为: " + UName + "很高兴认识你");
setResult(RESULT_OK,intent);
finish();
}
});

  重写第一个 Activity 的 onActivityResult 方法,该方法会在第二个 Activity 销毁后调用

   @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch(requestCode){
case 1:{
if(resultCode == RESULT_OK){
String replyData = data.getStringExtra("return_data");
Toast.makeText(this,replyData,Toast.LENGTH_SHORT).show();
}
}
break;
}
}

在这里我们便可以接收到第二个 Activity 处理后的数据了。