【Android笔记】探究活动②使用Intent在活动之间穿梭

1.第一行代码Android 第2版 郭霖 著

2.[Android总结篇——Intent机制详解及示例总结]

http://www.cnblogs.com/X-knight/p/5438042.html

3.[Android Studio Intent使用(显式、隐式) 第一行代码]

https://blog.csdn.net/u012005313/article/details/47006689

探究活动②

使用Intent在活动之间穿梭

在第一次使用Intent的时候,只知道它可以用于在活动之间进行跳转,但并不理解它具体是做什么的,只知道在android中它的使用频率很高,经常用到。

Intent介绍

在Android中Intent机制是用来协助应用间的交互与通讯,Intent负责对应用中一次操作的动作、动作涉及的数据、附加数据进行表述,Android则根据此Intent的描述,负责找到对应的组件,将Intent传递给调用的组件,并完成组件的调用。

Intent不仅可以用于应用程序之间,也可用于应用程序内部的Activity/Service之间的交互。因此,可以将Intent理解为不同组件之间通信的“媒介”专门提供组件互相调用的相关信息。

Intent大致可以分为两种:显式Intent隐式Intent

Intent作用

Intent是一个将要执行的动作的抽象描述,一般来说是作为参数来使用,由Intent来协助完成android各个组件之间的通讯。比如说调用startActivity()来启动一个activity,或者用broadcaseIntent()来传递给所有感兴趣的BroadcaseReceiver,再或者由startService()/bindservice()来启动一个后台的service。所以可以看出来,intent主要是用来启动其他的activity或者service,所以可以将intent理解成activity之间的粘合剂

使用显式Intent

Intent一般可被用于启动活动、启动服务以及发送广播等场景,但目前来说,因为只了解活动的使用,所以暂且学习如何通过Intent启动活动。具体使用如下:

首先,我们新建一个活动,叫SecondActivity,然后编辑SecondActivity的布局文件,将里面的代码替换如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button2"
        />
LinearLayout>

SecondActivity中的代码则保持默认即可。

在AndroidManifest.xml中,我们可以看到,AS已经帮我们注册了相关活动。因为SecondActivity并不是主活动,因此不需要配置标签里的内容。

紧接着,我们就需要使用Intent将两个活动来联系起来,我们需要修改FirstActivity中按钮的点击事件(FirstActivity为探究活动①当中的项目,在这个项目的基础上进行修改),代码如下:

button1.setOnClickListener(new View.OnClickListener()){
      @Override  
    protected void onCreate(View v) {
        /*
            通过这个构造函数可以构建出Intent的“意图”
            再使用startActivity()方法启动活动
        */
        Intent intent = new Intent(FirstActicity.this,SecondActivity.class);
        startActivity(intent);
    }
}

这样,我们就实现了活动之间的跳转了,当我们点击FirstActivity中的button按钮中就可以跳转到SecondActivity这个活动中了。

使用隐式Intent

隐式Intent,它并不明确的指出我们想要启动哪一个活动,而是指定了一系列更为抽象的action和category等信息,然后交由系统去分析这个Intent,并帮我们找出合适的活动去启动。

首先,我们修改AndroidManifest.xml文件,修改代码如下:

<activity  
    android:name=".SecondActivity"  
    <intent-filter>  
        <action android:name="com.example.activitytest.ACTION_START" />  
        <category android:name="android.intent.category.DEFAULT" />  
    intent-filter>  
activity> 

在action标签中我们指明了当前活动可以响应com.example.activitytest.ACTION_START这个action,而category标签则包含了一些附加信息,更精确地指明了当前的活动能够响应的Intent中还可能带有的category。只有action和category中的内容同时能够匹配上Intent中指定的action和category时,这个活动才能响应该Intent.

修改FirstActivity中按钮的点击事件,代码如下:

button1.setOnClickListener(new View.OnClickListener()){
      @Override  
    protected void onCreate(View v) {
        Intent intent = new Intent("com.example.activitytest.ACTION_START");
        startActivity(intent);
    }
}

这里,我们使用了Intent的另一个构造函数,直接将action的字符串传了进去,表明我们想要启动能够响应com.example.activitytest.ACTION_START这个action的活动。

这里不需要指定category是因为:android.intent.category.DEFAULT是一种默认的category,在调用startActivity()方法的时候会自动将这个category添加到Intent中。

重新运行程序,这时我们同样可以启动SecondActivity。不同的是,这次使用了隐式Intent。

每个Intent中只能指定一个action,但却能指定多个category。修改FirstAcitivity中按钮的代码,尝试再添加一个category。

button1.setOnClickListener(new View.OnClickListener()){
      @Override  
    protected void onCreate(View v) {
        Intent intent = new Intent("com.example.activitytest.ACTION_START");
        intent.addCategory("com.example.activitytest.MY_CATERGORY");
        startActivity(intent);
    }
}

这里,我们调用了Intent中的addcategory()来添加一个category,这里制定了一个自定义的category,值为com.example.activitytest.MY_CATERGORY。

因为新添了一个category,所以我们需要在SecondActivity的intent-filter标签中添加可以响应这个category的声明,否则程序将会奔溃,修改代码如下:

<activity  
    android:name=".SecondActivity"  
    <intent-filter>  
        <action android:name="com.example.activitytest.ACTION_START" />  
        <category android:name="android.intent.category.DEFAULT" />  
        category android:name="com.example.activitytest.MY_CATERGORY" />  
    intent-filter>  
activity> 

再次运行程序,可以正常跳转。

通过上面两个例子,我学习了使用Intent在不同活动中进行跳转,需要注意的是隐式调用中要留意更多的细节,就如action和category两者需要同时能够正常想要Intent这点就需要我们多多留意了。

更多隐式Intent的用法

使用Intent并不仅仅可以启动自己程序内的活动,还可以启动其他程序的活动,这可以让Android中多个应用程序之间的功能共享成为了可能。

例如:

  1. 在应用程序中展示一个网页

修改FirstActivity中按钮的点击事件,代码如下:

button1.setOnClickListener(new View.OnClickListener()){
      @Override  
    protected void onCreate(View v) {
        Intent intent = new Intent(Intent.View);
        intent.setData(Uri.parse("http://www.baidu.com"));
        startActivity(intent);
    }
}

程序中,首先制定了Intent的action是Intent.View,这是一个Android系统内置的动作,其常量值为android.intent.action.View。

然后通过Uri.parse()方法,将一个网址字符串解析成一个Uri对象,在调用Intent的setData()方法将这个Uri对象传递进去。

setData():接收一个Uri对象,主要用于指定当前Intent正在操作的数据。

这时候,重新运行程序,就可以通过FirstActivity中的点击按钮打开系统浏览器了。

与此对应,还可以在intent-filter标签中再配置一个data标签,用于更精确地指定当前活动能够响应什么类型的数据。data标签中主要可以配置以下内容。

  • android:scheme。用于指定数据的协议部分,如:上例中的http部分。
  • android:host。用于指定数据的主机名部分,如:上例中的www.baidu.com部分。
  • android:port。用于指定数据的端口部分,一般紧随在主机名之后。
  • android:path。用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容。
  • android:mimeType。用于指定可以处理的数据类型,允许使用通配符的方式进行指定。

只有data标签中指定的内容和Intent中携带的Data完全一致时,当前活动才能够响应该Intent。不过一般在data标签中都不会指定过多的内容,如:上面浏览器示例中,只需要指定android:scheme为http就可以响应所有http协议的Intent了。

例如:

首先,创建一个新的活动ThirdActivity,布局文件起名为third_layout,编辑里面的代码替换成如下内容:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button3"
        />
LinearLayout>

最后,修改AndroidManifest.xml中ThirdActivity中的注册信息:

<activity  
    android:name=".ThirdActivity"  
    <intent-filter>  
        <action android:name="android.intent.action.VIEW" />  
        <category android:name="android.intent.category.DEFAULT" />  
        <data android:scheme="http" />
    intent-filter>  
activity> 

运行结果如下:

【Android笔记】探究活动②使用Intent在活动之间穿梭_第1张图片

这时,系统显示了目前能够响应这个Intent 的所有程序。若选择Brower打开浏览器;选择ActivityTest则会启动ThirdActivity。

  1. 在程序中调用系统拨号界面

修改FirstActivity中按钮的点击事件,代码如下:

button1.setOnClickListener(new View.OnClickListener()){
      @Override  
    protected void onCreate(View v) {
        Intent intent = new Intent(Intent.ACTION_DIAL);
        intent.setData(Uri.parse("tal:10086"));
        startActivity(intent);
    }
}

显示结果如下:

【Android笔记】探究活动②使用Intent在活动之间穿梭_第2张图片

向下一个活动传递数据

Intent不单单能够简单的启动一个活动,还可以在启动活动的时候传递数据。

**思路:**Intent中提供了一系列putExtra()方法的重载,可以把我们想要传递的数据暂存在Intent中,启动活动后,只需把这些数据再从Intent中取出即可。

例子如下:

首先,修改FirstActivity中按钮的点击事件,代码如下:

button1.setOnClickListener(new View.OnClickListener() {  
    @Override  
    public void onClick(View v) {
        String data = "Hello SecondActivity";
        Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
        intent.putExtra("extra_data",data);
        startActivity(intent);
    }
}

此处显式使用Intent启动SecondActivity,并通过putExtra()方法传递了一个字符串。此处putExtra()方法接收两个参数,第一个参数是键,用于后面从Intent中取值,第二个参数才是真正要传递的数据。

然后,在SecondActivity中间传递的数据取出,并打印出来,代码如下:

public class SecondActivity extends AppCompatActivity{
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_second);  
        Intent intent = getIntent();  
        String data=intent.getStringExtra("extra_data");  
        Log.d("SecondActivity", data);
    }
}

这里,通过getIntent()方法获取用于启动SecondActivity的Intent,然后调用getStringExtra(),传入对应的键值,就可以得到传递的数据。

由于我们传递的是字符串,所以使用getStringExtra()方法来获取传递的数据,如果传递的是整型数据,则使用getIntExtra()方法,传递的是布尔型数据,则使用getBoolExtra()方法,以此类推。

重新运行程序,点击Button1,查看logcat打印信息。这时我们可以看到SecondAcitivy成功得到了从FirstActivity传递过来的数据。

返回数据给上一个活动

返回上一个活动只需要按一下Back键就可以了,并没有一个用于启动活动Intent来传递数据。

Activity中还有一个startActivityForResult()方法用于启动活动的,但这个方法期望在活动销毁的时候能够返回一个结果给上一个活动。

startActivityForResult()方法接收两个参数,第一个参数还是Intent,第二个参数是请求码(requestCode),用于在之后的回调中判断数据的来源。请求码只要是一个唯一值就可以了。

例子如下:

修改FirstActivity中按钮的点击事件,代码如下:

 button1.setOnClickListener(new View.OnClickListener() {  
        @Override  
        public void onClick(View v) {  
            Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
            startActivityForResult(intent,1);
        }
}

这里使用了startActivityForResult()方法来启动SecondActivity,请求码传入了1。

接着,在SecondActivity中给按钮注册点击事件,并在点击事件中添加返回数据的逻辑,代码如下:

public class SecondActivity extends AppCompatActivity{
    @Override  
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_second);  
    }
    Button button2 = (Button)findViewById(R.id.button_2);  
    button2.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                Intent intent = new Intent();  
                intent.putExtra("data_return", "Hello MainActivity");  
                setResult(RESULT_OK, intent);  
                finish();  
            }  
        }); 
    }
}

在代码中,构建一个了Intent,用于传递数据。

然后调用setResult(),它专门用于向上一个活动返回数据。

setResult()方法接收两个参数,第一个参数用于向上一个活动返回处理结果,一般只是用RESULT_OK/RESULT_CANCELED这两个值;第二个参数则把带有数据的Intent传递回去,然后调用finish()方法销毁当前活动。

在SecondActivity被销毁之后会回调上一个活动的onActivityResult()方法,因此需要在FirstActivity中重写这个方法来得到返回的数据,如下所示:

@Override  
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
     switch (requestCode) {  
         case 1:  
             if (resultCode == RESULT_OK) {  
                 String returnData = data.getStringExtra("data_return");  
                 Log.d("MainActivity", returnData);  
             }  
             break;  
         default:  
     }  
 }  

onActivityResult()方法带有三个参数,第一个参数requestCode,即我们在启动活动时传入的请求码;第二个参数resultCode,即我们在返回数据时传入的处理结果;第三个参数data,即携带着返回数据的Intent。

由于在一个活动中很有可能调用startActivityForResult()方法调用很多不一样的活动,因此首先要做的就是检查requestCode的值来判断数据来源

确定数据是从SecondActivity返回后,再通过resultCode的值来判断处理是否成功。最后从data中取值并打印,这样就会完成了向上一个活动返回数据的工作了。

当然,用户也可能并不是通过点击按钮,而是通过Back键返回FirstActivity,这时就需要通过在SecondActivity中重写onBackPressed()方法来解决这个问题,代入如下:

@Override  
public void onBackPressed() {  
    Intent intent=new Intent();  
    intent.putExtra("data_return", "~~Hello FirstActivity");  
    setResult(RESULT_OK, intent);  
    finish();  
} 

这样,按下Back就会执行上述代码了,这里就可以处理添加返回数据的逻辑了。

总结:

这里主要是学习了Intent在活动当中的各种使用方法,例如:在不同的活动的跳转、传递数据,打开浏览器,拨号等等,通过这一小节的学习,对Intent可以有一个初步的印象和认识。

当然,它的作用并不止于此,但目前暂未尝试,希望通过日后的学习可以不断对Intent的知识点进行完善,最终形成一个完整的知识网络。

你可能感兴趣的:(Android)