学习路线

image-20220509185308214

Intent

Intent原理及分类

  • Intent是Android应用内不同组件之间的通讯载体

  • 使用Intent可以激活Android的三个核心组件:

    • Activity

    • Service

    • BroadcastReceiver

image-20220509185900217

  • Intent启动Activity、Service方法:

    • 启动Activity:调用startActivity(Intent intent)或startActivityForResult(Intent intent,int requestCode)方法
    • 启动Service:调用startService(Intent intent)或bindService(Intent intent,ServiceConnection conn ,int flags)方法
  • 触发BroadcastReceiver的方法:

    • 触发BroadcastReceiver:调用sendBroadcast(Intent intent)方法
  • Intent分为以下两类:

    • 显式Intent

    • 隐式Intent

Intent属性

  • Intent对象中包含以下几种属性:
    • Component组件
    • Action动作
    • Category类别
    • Data数据
    • Type数据类型
    • Extras扩展信息
    • Flags标志位

Component组件

  • Component组件为目标组件,需要接受一个ComponentName对象

  • ComponentName对象的构造方法有以下几种方式:

    • ComponentName(String pkg,String className)
    • ComponentName(Context context,String className)
    • ComponentName(Context context,Class<?> className)
  • Intent还可以指定待启动组件的包名和类名:
    • setClass(Context ctx,Class<?> cls)
    • setClassName(Context ctx,String className)
    • setClassName(String pkg,String className)

Action动作

  • Action是一个字符串,用于描述一个Android应用程序的组件
  • 启动Activity的系统标准Action
Action常量 字符串 描述
ACTION_SEND android.intent.action.SEND 启动一个Activity,该Activity会发送Intent中指定的数据。接收人需要由解析的Activity来选择。
ACTION_SENDTO android.intent.action.SENDTO 启动一个Activity来向Intent的数据URI所指定的联系人发送一条消息。
ACTION_ANSWER android.intent.action.ANSWER 打开一个处理来电的Activity,通常这个动作是由本地电话拨号程序处理
ACTION_INSERT android.intent.action.INSERT 打开一个子Activity能在Intent的数据URI指定的游标处插入新项的Activity。当作为子Activity调用时,应该返回一个指向新插入项的URI
ACTION_DELETE android.intent.action.DELETE 启动一个Activity,允许删除Intent的数据URI中指定的数据
ACTION_ALL_APPS android.intent.action. ACTION_ALL_APPS 打开一个列出所有已安装应用程序的Activity,通常此操作由启动器处理
ACTION_SEARCH android.intent.action.SEARCH 通常用于启动特定的搜索Activity。

Category类别

  • Category属性用来描述动作的类别
Category常量 字符串 描述
CATEGORY_DEFAULT android.intent.category.DEFAULT 默认的Category
CATEGORY_BROWSABLE android.intent.category.BROWSABLE 指定Activity能被浏览器安全调用
CATEGORY_TAB android.intent.category.TAB 指定Activity能作为TabActivity的Tab页
CATEGORY_LAUNCHER android.intent.category.LAUNCHER Activity显示顶级程序列表中
CATEGORY_INFO android.intent.category.INFO 用于提供包信息
CATEGORY_HOME android.intent.category.HOME 设置该Activity随系统启动而运行
CATEGORY_PREFERENCE android.intent.category.PREFERENCE 该Activity是参数面板
CATEGORY_TEST android.intent.category.TEST 该Activity是一个测试
CATEGORY_CAR_DOCK android.intent.category.ANSWER 指定手机被插入汽车底座时运行该Activity
CATEGORY_DESK_DOCK android.intent.category.CAR_DOCK 指定手机被插入桌面底座时运行该Activity
CATEGORY_CAR_MODE android.intent.category.CAR_MODE 设置该Activity可以在车载环境下使用

Extras扩展信息

Extras属性是一个Bundle对象

  • 用于在多个Activity之间交换数据
  • Extras属性的使用过程
  1. 使用Extras属性
1
2
3
4
5
Bundle bundle= new Bundle();
bundle.putString("test", "this is a test");
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
intent.putExtras(bundle);
startActivity(intent);
  1. 通过getExtras()方法获得Bundle对象并进行取值
1
2
Bundle bundle = this.getIntent().getExtras();
String test = bundle.getString("test");

使用Intent启动Activity

  • 通过调用Context的startActivity()方法可以创建并显示目标Activity

    • startActivity(myIntent);
  • startActivity()方法会查找并启动一个与Intent参数相匹配的Activity

  • startActivityForResult()方法启动Activity并跟踪子Activity的反馈

显式Intent启动Activity

  • 通过Intent来显式地指定要打开的Activity
  • 显式Intent启动Activity
1
2
Intent intent = new Intent(MyActivity.this, MyOtherActivity.class);
startActivity(intent);

隐式Intent启动Activity

  • 使匿名的应用程序组件响应动作请求
  • 隐式Intent启动Activity
1
2
Intent intent =new Intent(Intent.ACTION_DIAL, Uri.parse("tel:555-2368"));
startActivity(intent);
  • 构建一个隐式的Intent时,需要指定一个所要执行的动作
  • 通过向Intent添加Extra的方式来向目标Activity发送额外的数据
  • 当多个Activity都能够执行指定的动作时,会向用户呈现各种选项供用户手动选择

  • 常见的使用Intent来启动内置应用程序有四种:

  1. 启动浏览器
1
2
Intent i=new Intent(Intent.ACTION_VIEW,Uri.parse("http://www.sohu.com"));
startActivity(i);
  1. 启动地图
1
2
3
4
Intent i=new Intent(Intent.ACTION_VIEW,
Uri.parse("geo:25.04692437135412,121.5161783959678"));
startActivity(i);

  1. 打电话
1
2
Intent i=new Intent(Intent.ACTION_DIAL,Uri.parse("tel:+1234567"));
startActivity(i);
  1. 发送电子邮件
1
2
Intent i=new Intent(Intent.ACTION_SENDTO,Uri.parse("mailto:qst@163.com"));
startActivity(i);

传递数据给其他Activity

  • 通过Intent的putExtra()或putExtras()方法可以向目标Activity传递数据隐

  • 使用putExtras()方法批量传递数据

1
2
3
4
5
Intent intent = new Intent();
Bundle bundle = new Bundle();//该类用作携带数据
bundle.putString("name","中华文明");
bundle.putString("address","青岛");
intent.putExtras(bundle);
  • 使用putExtra()方法单个传递数据
1
2
Intent intent = new Intent();
intent.putExtra("name", "中华文明");

从Activity返回数据

  • 使用startActivityForResult()方法启动一个Activity,新启动的Activity在关闭时可以原Activity返回数据

  • 启动一个目标Activity

  1. 显示启动Activity
1
2
Intent intent = new Intent(this, MyOtherActivity.class);
startActivityForResult(intent, 1);
  1. 隐式启动Activity
1
2
3
Uri uri = Uri.parse("content://contacts/people");
Intent intent = new Intent(Intent.ACTION_PICK, uri);
startActivityForResult(intent, 2);
  • 从目标Activity中返回数据

    • 在目标Activity中调用finish()方法之前,通过setResult()方法向原Activity返回一个结果

    • setResult()方法是一个重载方法,其形式如下:

  1. setResult(int resultCode)——设置传递到上一个界面的数据

    1
    setResult(Activity.RESULT_CANCELED);
  2. setResult(int resultCode, Intent data) ——设置传递到上一个界面的数据

1
2
Intent result = new Intent(Intent.ACTION_PICK, selectedHorse);
setResult(Activity.RESULT_OK, result);

处理从目标Activity返回的数据

  • 重写onActivityResult()方法处理从目标Activity返回的结果
1
onActivityResult(int requestCode, int resultCode, Intent data));
  1. requestCode是在启动目标Activity时所使用的请求码
  2. resultCode表示从目标Activity返回的状态码
  3. data是状态码对应的返回数据

Intent Filter过滤器

  • Intent Filter过滤器用于描述指定的组件可以处理哪些意图
  • 在Intent Filter中可以包含Intent对象的三个属性:
    • ACTION
    • DATA
    • CATEGORY
  • 在AndroidManifest.xml中配置<intent-filter>元素
1
2
3
4
5
6
<intent-filter>
<action android:name="com.example.project.SHOW_CURRENT" />
<action android:name="com.example.project.SHOW_RECENT" />
<action android:name="com.example.project.SHOW_PENDING" />
......
</intent-filter>
  • 当Intent对象或者过滤器没有指定<action>时:

    • 如果一个Intent过滤器没有指定任何<action>,则不会匹配任何Intent;
    • 如果一个Intent对象没有指定任何<action>,无法匹配。
  • Category测试

1
2
3
4
5
<intent-filter> 
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
......
</intent-filter>

代码实现

显式使用intent的7种方式

显式指定intent方法统计:

  • intent构造函数 +
  • setComponent +++
  • setClass +
  • setClassName ++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//显式使用intent的7种方式
//1.intent构造函数
// Intent intent=new Intent(this,LoginActivity.class);
//2.setComponent ComponentName(Context context,String className) context+类名.class 构造
// Intent intent=new Intent();
// intent.setComponent(new ComponentName(this,LoginActivity.class));
//3.setComponent ComponentName(Context context,Class<?> className) context+完整类名字符串 构造
// Intent intent=new Intent();
// intent.setComponent(new ComponentName(this,"com.gallifrey.todayapplication.webview.LoginActivity.class"));
//4.setComponent ComponentName(String pkg,String className) 包路径字符串+完整类名字符串 构造
// Intent intent=new Intent();
// intent.setComponent(new ComponentName("com.gallifrey.todayapplication.webview","com.gallifrey.todayapplication.webview.LoginActivity.class"));
//5.setClass context+类名.class
// Intent intent=new Intent();
// intent.setClass(this,LoginActivity.class);
//6.setClassName context+完整类名字符串
// Intent intent=new Intent();
// intent.setClassName(this,"com.gallifrey.todayapplication.webview.LoginActivity.class");
//7.setClassName 包名字符串+完整类名字符串
Intent intent=new Intent();
intent.setClassName("com.gallifrey.todayapplication.webview","com.gallifrey.todayapplication.webview.LoginActivity.class");

隐式使用intent

隐式使用intent不会指定某个通讯对象,通过Intent Filter过滤器来匹配action和category,data来决定如哪些组件去处理intent

  • intent写法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 隐式使用intent
Intent intent=new Intent();

//下面三行代码的是匹配action和data
/ intent.setAction("intent.login");//先匹配action
// intent.addCategory("intent.category.login");//再匹配category
// intent.addCategory("intent.category.e2");//都匹配上,这个intent才能启动

//这里是测试data,浏览器打开,所以不需要匹配指定组件
// intent.setAction(Intent.ACTION_VIEW);//启动浏览器
// intent.setDataAndType(Uri.parse("http://gallifrey.asia"),"text/html");

// startActivityForResult(intent,0);//方法已弃用 ,请在onCreate方法中使用registerForActivityResult()方法代替
mLauncher.launch(intent);
  • 组件匹配(在AndroidManifest.xml中修改)
1
2
3
4
5
6
7
8
9
10
<activity
android:name=".webview.LoginActivity"
android:exported="false" >
<intent-filter>
<action android:name="intent.login"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="intent.category.login"/>
<category android:name="intent.category.e2"/>
</intent-filter>
</activity>

BroadCastReceiver