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的时候,只知道它可以用于在活动之间进行跳转,但并不理解它具体是做什么的,只知道在android中它的使用频率很高,经常用到。
在Android中Intent机制是用来协助应用间的交互与通讯,Intent负责对应用中一次操作的动作、动作涉及的数据、附加数据进行表述,Android则根据此Intent的描述,负责找到对应的组件,将Intent传递给调用的组件,并完成组件的调用。
Intent不仅可以用于应用程序之间,也可用于应用程序内部的Activity/Service之间的交互。因此,可以将Intent理解为不同组件之间通信的“媒介”专门提供组件互相调用的相关信息。
Intent大致可以分为两种:显式Intent和隐式Intent
Intent是一个将要执行的动作的抽象描述,一般来说是作为参数来使用,由Intent来协助完成android各个组件之间的通讯。比如说调用startActivity()来启动一个activity,或者用broadcaseIntent()来传递给所有感兴趣的BroadcaseReceiver,再或者由startService()/bindservice()来启动一个后台的service。所以可以看出来,intent主要是用来启动其他的activity或者service,所以可以将intent理解成activity之间的粘合剂。
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,它并不明确的指出我们想要启动哪一个活动,而是指定了一系列更为抽象的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并不仅仅可以启动自己程序内的活动,还可以启动其他程序的活动,这可以让Android中多个应用程序之间的功能共享成为了可能。
例如:
修改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标签中主要可以配置以下内容。
只有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>
运行结果如下:
这时,系统显示了目前能够响应这个Intent 的所有程序。若选择Brower打开浏览器;选择ActivityTest则会启动ThirdActivity。
修改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);
}
}
显示结果如下:
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的知识点进行完善,最终形成一个完整的知识网络。