Intent是Android程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent一般可被用于启动活动、启动服务、以及发送广告等场景。
Intent的用法分为显式Intent和隐式Intent两种。接下来详细解析。
1.了解Intent的构造方法
Intent的方法有很多,通过认识构造方法,我们能够窥探到Intent的不同用法。
1.空构造方法:
public Intent() {
}
2.根据另一个Intent创建的构造方法
public Intent(Intent o) {
this.mAction = o.mAction;
this.mData = o.mData;
this.mType = o.mType;
this.mPackage = o.mPackage;
this.mComponent = o.mComponent;
this.mFlags = o.mFlags;
this.mContentUserHint = o.mContentUserHint;
if (o.mCategories != null) {
this.mCategories = new ArraySet<String>(o.mCategories);
}
if (o.mExtras != null) {
this.mExtras = new Bundle(o.mExtras);
}
if (o.mSourceBounds != null) {
this.mSourceBounds = new Rect(o.mSourceBounds);
}
if (o.mSelector != null) {
this.mSelector = new Intent(o.mSelector);
}
if (o.mClipData != null) {
this.mClipData = new ClipData(o.mClipData);
}
}
3.由一条Action创建的构造方法
public Intent(String action) {
setAction(action);
}
其中的setAction()方法如下:
public Intent setAction(String action) {
mAction = action != null ? action.intern() : null;
return this;
}
4.通过Action和Uri共同创建的构造方法
public Intent(String action, Uri uri) {
setAction(action);
mData = uri;
}
5.通过Context和Class文件创建的构造方法
public Intent(Context packageContext, Class<?> cls) {
mComponent = new ComponentName(packageContext, cls);
}
6.大杂烩,通过Action、Uri、Context还有Class文件创建的构造方法
public Intent(String action, Uri uri,
Context packageContext, Class<?> cls) {
setAction(action);
mData = uri;
mComponent = new ComponentName(packageContext, cls);
}
通过这些构造方法,我们需要从中学习到,不同构造方法的Intent,其作用是不同的。
1.参数要求为Context以及Class的
接下来会在构造方法中会创建出ComponentName对象,这个是Android的组件,是可以具体到某个具体的组件的,这种就是显式的使用方法。
2.参数要求为Action的
接下来会在构造方法中调用setAction()方法,也就是给mAction赋值,对应到AndroidManifest文件中的<intent-filter><action>标签,在启动时,如果配置了相同action和category的Activity都可能被启动起来,如果匹配到多个,会弹出对话框让用户手动选,这种就是隐式的使用方法。
2.隐式使用Intent的注意事项
-
每个Intent中只能指定一个action,但是可以指定多个category。
-
startActivity()方法中会自动将"android.intent.category.DEFAULT"这个默认的category添加到Intent中,如果被启动的Activity声明的category正好就是默认的话,可以不用写。
-
在AndroidManifest文件中声明Activity的时候,如果希望这个Activity是用隐式的方式被启动,那么在<intent-filter>标签中,必须要添加上这一条:
<category android:name="android.intent.category.DEFAULT"/>
如果AndroidManifest文件中没有这一条,那么即使Action能够匹配上依然会崩溃。
如下:
<intent-filter>
<action android:name="com.company.windmajor.JUMP"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
代码调用:
Intent intent = new Intent();
intent.setAction("com.company.windmajor.JUMP");
startActivity(intent);
- 如果有自己限定category的需求,那么可以先添加上面一点中提到的DEFAULT的category,然后再定义自己的category。然后在java代码中添加自己定义的category。如下:
<intent-filter>
<action android:name="com.company.windmajor.JUMP"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="com.company.windmajor.category.JUMP"/>
</intent-filter>
代码中的调用:
Intent intent = new Intent();
intent.setAction("com.company.windmajor.JUMP");
intent.addCategory("com.company.windmajor.category.JUMP");
startActivity(intent);
3.更多隐式Intent的用法
使用Intent,还可以启动其他App的Activity,这将使得Android多个应用程序之间的功能共享成为了可能。
这里介绍几个用法:Intent.ACTION_VIEW和Intent.ACTION_DIAL
(1)Intent.ACTION_VIEW
这个Action是系统定义的Action,可以将带有浏览器功能的App给打开,使用代码如下:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
}
});
这段代码的效果就是打开浏览器,然后访问百度网。
setData()的方法接受Uri对象,主要用于指定当前Intent正在操作的数据,而这些数据通常都是以字符串的形式传入到Uri.parse()方法中解析产生的。
与此对应,我们还可以在<intnet-filter>标签中再配置一个<data>标签,用于更精确的指定当前活动能够相应什么类型的数据。<data>标签中,主要可以配置以下内容。
- android:scheme 指定数据的协议部分,如上面代码里的http部分
- android:host 指定数据的主机名部分,如上面代码里的www.baidu.com部分
- android:port 指定数据的端口部分,一般紧随在主机名之后
- android:path 指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容
- android:mimeType 指定可以处理的数据类型,允许使用通配符的方式进行指定。
只有<data>标签中指定的内容和Intent中携带的Data完全一致是,当前Activity才能响应该Intent。
那么如何自己创建一个可以响应系统需求的Activity呢?
首先创建一个布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/text_view_two"
android:text="Activity Two"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
然后创建一个新的Activity:
public class TwoActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_two);
}
}
最后非常重要的是一定要在AndroidManifest文件中注册新的Activity
<activity android:name=".TwoActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
</intent-filter>
</activity>
这样运行起来之后,点击刚才的那个按钮,就可以看到选择启动程序的一个列表,列表中包括浏览器还包括我们刚刚创建新Activity的这个程序。当然只有打开浏览器,我们才能看到百度网页面的各种广告,点击我们自己的程序是不能看到的,因为我们的程序也没有写处理浏览登陆的代码。
(1).Intent.ACTION_DIAL
使用代码如下:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
}
});
4.Activity之间的数据互传
Intent可以用来启动Activity,当然也是可以传递数据的,为了方便Activity之间的数据通信,Activity提供了putExtra()方法的重载,可以传递许多中类型的数据。
使用代码如下:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, TwoActivity.class);
intent.putExtra("EXTRA_DATA","Hello SecondActivity");
startActivity(intent);
}
});
这里putExtra()方法的第一个参数是“键”,第二个参数是真正的“值”,键通常都是String类型的,值可以有很多种类型。那么这个地方传递了,别的地方如何取呢?
Intent intent = getIntent();
String data = intent.getStringExtra("EXTRA_DATA");
只需要在被启动的Activity里面使用如上的代码即可。当然要知道传的时候是什么类型,取的时候必须要能类型匹配上。不然不行。
当上一个Activity传递数据给下一个Activity,那么下一个Activity如何将数据结果传递回给上一个Activity呢?这里需要介绍一下startActivityForResult()方法。
这个方法需要两个参数,第一个参数是启动Intent,第二个参数是启动的请求码,只要是唯一的整型数字即可。
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, TwoActivity.class);
intent.putExtra("EXTRA_DATA", "Hello SecondActivity");
startActivityForResult(intent, 1);
}
});
当用户在界面TwoActivity完成了相应的操作,得到了想要的数据,需要将这个数据返回给第一个MainActivity,只需要下面这么做:
twoButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.putExtra("EXTRA_RETURN", "This is the result...");
setResult(RESULT_OK, intent);
finish();
}
});
我们看到上面的Intent仅仅只是用来传递数据,setResult()方法很重要,第一个参数用于向前一个Activity返回处理结果,一般只使用RESULT_OK或RESULT_CANCELED这两个系统定义好的值表示成功与失败,第二个参数是把带有数据结果的Intent对象传递回去。最后使用finish()方法将当前的Activity销毁。
由于我们是使用startActivityForResult()方法来启动的第二个Activity,这种启动方法需要实现一个特殊的方法才可以使用第二个Activity返还回来的数据。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 1:
if (resultCode == RESULT_OK) {
String returnedData = data.getStringExtra("EXTRA_RETURN");
Log.i("MainActivity", returnedData);
}
break;
default:
break;
}
}
这个方法有三个参数,第一个参数requestCode是启动第二个Activity时的启动码,我们设置的是1,第二个参数resultCode是从第二个Activity返还回来时的结果码,一般有两种RESULT_OK和RESULT_CANCELED,第三个参数data就是带着数据的Intent对象。
以上就是Intent的一些简单的特性和使用方法,希望共同勉励。
案例和知识点都来源于郭霖的《第一个行代码》,在此特别感谢郭老师,希望大家看完本篇文章后,希望全面了解的可以购买郭老师的书。
网友评论