Intent的使用
Activity基本设计理念是:
减少组件间的耦合;因此在Android中提供了Intent来实现在应用程序组件与组件之间交互。
负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述;
Android根据此Intent的描述,负责找到对应的组件,将Intent传递给调用的组件,并完成组件的调用。
作用:
使用Intent启用三大核心组件。
活动(Activity)、服务(Service)和广播接收器(BroadcastReceiver),
都是通过Intent来启动或激活的。
-
使用Intent启动Activity
方法名称 描述 Context.startActivity() 启动新的Activity Context.startActivityForResult() 启动新的Activity(并获得相应信息) -
使用Intent启动Service,不会立即销毁
方法名称 描述 Context.startService() 启动新的Service Context.bindService() 在调用组件和目标Service间建立连接 -
使用Intent启动BroadcastReceiver
方法名称 描述 Context.sendBroadcast() 普通的发送广播 Context.sendOrderedBroadcast() 有序的发送广播(有优先级顺序) Context.sendStickyBroadcast() 粘性的发送广播
一般在Android中有两种形式的Intent使用方法:
-
显式Intent对象:
直接指明Intent的目的组件
-
隐式Intent对象:
没有直接指明Intent目的组件,而是通过Intent其它属性来隐式指出Intent待加载的组件类
Intent由以下各个组成部分:
显式:
Component(组件):目的组件。
Extras (扩展信息):扩展信息。
Flags (标志位):期望这个意图的运行模式。
隐式:
Action (动作):用来表现意图的行动。
Category (类别):用来表现动作的类别。
Data (数据):表示与动作要操纵的数据。
Type (数据类型):对于data范例的描写。
(data和type对外不能同时使用,后面设置的那个值会把前面的值覆盖)
显式Intent
-
显式Intent:明确指定了当前Intent应该传递给哪个组件的Intent。
-
显式Intent使用的基本方法:
setClass(Context packageContext, Class<?> cls) setClassName(Context packageContext, String className) setClassName(String packageName, String className)
-
Component(组件):
目的组件,明确指定Intent的目标组件的类名称,Component属性需要接受一个ComponentName对象。
setComponent(ComponentName component)
-
ComponentName对象的构造器如下:
ComponentName(String pkg, String cls) ComponentName(Context pkg, String cls) ComponentName(Context pkg, Class<?> cls)
-
当需要为Intent设置Component属性时,Intent已经提供了一个简化的构造器,这样可以方便指定启动其他组件。
Intent(Context packageContext, Class<?> cls)
-
在组件中可以使用如下方法获取Intent,并且通过Intent获取组件包名及组件类名。
类 方法名称 描述 Activity getIntent() 获取当前Intent Activity getComponentName() 获取ComponentName Intent getComponent() 获取ComponentName ComponentName getPackageName() 获取组件包名 ComponentName getClassName() 获取组件类名
隐式Intent
-
未明确指明待加载的组件类,但是在Intent属性中给出了待加载组件需要满足的特征。那么对应被启动的组件中接受此种属性。
-
组件的特征取决于在Activity配置中<intent-filter…/>元素的配置。
<intent-filter…/>就是用于描述Intent的各种属性, <intent-filter…/>元素通常可包含如下子元素。
0~N个 <action…/> 子元素
0~N个 <category…/> 子元素
0~1个 <data…/> 子元素 -
Action和Category属性都是普通的字符串,Action代表想要完成的一个“动作”,Category代表此动作的额外信息。
被启动的组件是不明确的,取决于Activity的<intent-filter…/>属性。例如:我提供的Action是=“com.example.intent.AAA”,那么就启动指定intent-filter的组件。Action和Category属性要结合使用。
例子:
1.用Andoird Studio
软件为例,在java文件夹下右击选择Activity->empty Activity创建新的Activity2
2.在Manifest
文件夹下的AndroidManifest.xml
中会自动生成注册信息
<activity
android:name=".MainActivity2"
android:exported="false" >
<intent-filter>
<action android:name="custom.TESTACTION" />
<action android:name="custom.TEST" />
<category android:name="custom.TESTCATEGORY" />
<category android:name="android.intent.category.DEFAULT" />
<!-- 如果要设置action自定义的话,要设置DEFAULT -->
</intent-filter>
</activity>
在Activity中可以设置多个Action和category,并且随意组合,但是建议设置 <category android:name=“android.intent.category.DEFAULT”
通过Action设置启动意图,如果去除 会报错,所以必须加上
3.在activity_main.xml
中设置一个Button用来作为跳转按钮
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_jmp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="跳转"/>
</LinearLayout>
4.MainActivity.java
文件
public class MainActivity extends AppCompatActivity {
private Button btnJmp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取控件
btnJmp = findViewById(R.id.btn_jmp);
//设置监听器
btnJmp.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//隐式启动Activity2
startActivityByAction();
}
});
}
private void startActivityByAction() {
//实例化inter对象
Intent intent = new Intent();
// 如果设置了data属性,必须使用,不然会报错,如果没有在Manifest中设置不需要进行设置
intent.setAction("custom.TESTACTION");
// intent.setAction("custom.TEST");不会报错,但是会替代上一行代码
//设置Category
intent.addCategory("custom.TESTCATEGORY");
//使用Action方式启动Activity
startActivity(intent);
}
}
Data和Type
-
Data属性通常用于向Action属性提供操作的数据,Data属性接受一个Uri对象,Uri对象通过如下形式的字符串表示:
scheme://host:port/path
例如:content://com.android.contacts/contacts/1
scheme部分是content
host部分是com.android.contacts
port部分被省略了
path部分是/contacts/1 -
Type属性用于指定Data属性的MIME类型,这种MIME类型可以是任何自定义的类型,只要符合abc/xyz格式的字符串即可。
添加data属性使用setData( )方法
设置type属性使用setType( )方法
data和type属性一般只需要一个,通过setData方法会把type属性设置为null,相反设置setType方法会把data设置为null,如果想要两个属性同时设置,要使用setDataAndType()方法。
1.AndroidManifest.xml
<activity
android:name=".MainActivity3"
android:exported="false" >
<intent-filter>
<action android:name="custom.lww.TEST"/>
<category android:name="android.intent.category.DEFAULT"/>
<data
android:host="china"
android:mimeType="history/yyh"
android:path="/no1"
android:port="5000"
android:scheme="beauty" />
</intent-filter>
</activity>
- scheme接收uri
mimeType的内容是type,规则需要用/分为两个部分的格式(可以没有)
path(可以没有),port,host(必须有),scheme(必须有)是data
在启动的时候data被分为两个部分type和data
1.data和type在给Activity设置的时候,都放在data标签中,data有且只有一个
2.在启动Activity的时候,data和type相矛盾,后设置谁谁生效
3.当data和type同时存在的时候,使用setDataAndType进行设置
4.当注册Activity时设置了data,则隐式启动Activity必须使用Data
当Data有但是其他的没有时出现了报错,但是加上了以后不报错了,所以可能是当设置data时必须有其他两个。
2.activity_main
<Button
android:id="@+id/btn_jmp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="跳转"/>
3.activity_main3.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity3">
<TextView
android:id="@+id/textView"
android:layout_width="404dp"
android:layout_height="35dp"
android:text="Activity3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:layout_editor_absoluteY="357dp"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
4.MainActivity.java
public class MainActivity extends AppCompatActivity {
private Button btnJmp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnJmp = findViewById(R.id.btn_jmp);
btnJmp.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//隐式启动Activity3
startActivityByDataAndType();
}
});
}
private void startActivityByDataAndType() {
Intent intent = new Intent();
//设置data(通过uri方式)
Uri uri = Uri.parse("beauty://china:5000/no1");
intent.setDataAndType(uri,"history/yyh");
//如果分开设置data和type,后设置的会替换先设置的,所以需要用setDataAndType同时设置
/* 分开设置的方法 intent.setData(uri);
// 和type
intent.setType("history/yyh");*/
startActivity(intent);
}
}