如果过滤器仅指定了一个scheme
,所有该scheme
的URIs
都能够和这个过滤器相匹配;
如果过滤器指定了一个scheme
、主机名但没有路经部分,所有具有相同scheme
和主机名的URIs都可以和这个过滤器相匹配,而不管它们的路经;
如果过滤器指定了一个scheme
、主机名和路经,只有具有相同scheme、主机名和路经的URIs才可以和这个过滤器相匹配。当然,一个过滤器中的路径规格可以包含通配符,这样只需要部分匹配即可。
比较规则如下:
- 一个既不包含URI也不包含数据类型的意图对象,仅在过滤器也同样没有指定任何URI和数据类型的情况下才能通过测试。
- 一个包含URI但没有数据类型的意图对象,仅在它的URI和一个同样没有指定数据类型的,过滤器里的URI匹配时才能通过测试。这通常发生在类似于mailto:和tel:这样的URIs上:它们并不引用实际数据。
- 一个包含数据类型但不包含URI的意图对象,仅在这个过滤器列举了同样的数据类型,而且也没有指定一个URI的情况下才能通过测试。
- 一个同时包含URI和数据类型(或者可从URI推断出数据类型)的意图对象可以通过测试,如果它的类型和过滤器中列举的类型相匹配的话。如果它的URI和这个过滤器中的一个URI相匹配或者它有一个内容
content:
或者文件file: URI
,而且这个过滤器没有指定一个URI,那么它也能通过测试。换句话说,一个组件被假定为支持”content: 数据“ 和 “file: 数据”,如果它的过滤器仅列举了一个数据类型。
例如AndroidManifest.xml
(AndroidManifest.xml
是安卓开发中主配置文件,程序执行首先浏览这个文件的内容)中有:
对于<intent-filter>
中的action
项可以有多个只要匹配其中一个就可以了
intent.setAction("com.nanlove.wangshiming");//中的action也可以为wangshiming
intent.addCategory("wangshiming.intent.category")// 代码中的addCategory并不用写因为android他有默认的category 只要配置清单中存在<category android:name="android.intent.category.DEFAULT" />就可以了.
没有 “数据参数” 的情况下只要意图对象中的设置动作和类别都出现在intent-filter
就能跟filter匹配,但是有数据<data android:scheme="love" android:host="hao123.com" android:port="888" android:path="/MM" />
数据项一定要完全匹配。
当数据和数据类型 android:mimeType="text/plain"
同时存在的时候,不能使用intent.setData(Uri.parse("love://hao123.com:888/MM")) ;
因为setData
的方法会自动清除前面的数据类型:This method automatically clears any type that was previously set by setType;
所以后面的setType
就无法匹配,应该使用intent.setDataAndType(Uri.parse("love://hao123.com:888/MM"), "text/plain");
提示:在同一个应用内,能使用显示意图,就尽量使用显示意图,增加程序的效率,理论上隐式意图匹配规则是需要花时间寻找的。
三、IntentFilter 实践
3.1 从一个APP跳转到另外一个目标APP
假设由应用A跳转到应用B。前提是应用B存在,可以使用getPackageManager().getPackageInfo("应用B的包名", 0);
方法判断应用B是否存在。
当前APP启动另外一个目标APP(非覆盖原来APP的方式),可以按照如下方案实施:
3.1.1 系统包管理器方式
- 当前APP加入获取权限声明:(不加入权限检查,没法启动目标app)
<uses-permission android:name="android.permission.QUERY\_ALL\_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
<uses-permission android:name="android.permission.LAUNCH\_APP" />
- 执行APP跳转
String packageName = "com.target.package"; // 目标应用的包名
PackageManager packageManager = getPackageManager();
Intent intent=new Intent();
intent = packageManager.getLaunchIntentForPackage(packageName);
if(intent==null){
Toast.makeText(MainActivity.this, "未安装", Toast.LENGTH\_LONG).show();
}else{
startActivity(intent);
}
- 目标APP处理
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE\_NO\_TITLE);
initWindows(this);
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if (intent != null && intent.hasExtra("message")) {
String message = intent.getStringExtra("message");
IntentModule.message = message;
IntentModule.getMessage();
}
}
3.1.2 Intent隐式调起方式
当前APP做如下处理:
Intent intent2 = new Intent();
intent2.setAction("定义的action,要与后面B中使用的保持一致");
intent2.putExtra("data","传递的数据");
startActivity(intent2);
目标APP AndroidManifest.xml
配置文件做如下处理:
<activity android:name="要跳转的指定类">
<intent-filter>
<action android:name="定义的action,要与前面A中的保持一致"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
目标APP参数处理逻辑如下:
Intent intent = this.getIntent();
if(null != intent.getStringExtra("data")){
//处理数据
}
3.1.3 通过 ComponentName 类实现
当前APP做如下处理:
Intent intent1 = new Intent();
ComponentName name = new ComponentName("应用B的包名","应用B中跳转到的activity的全路径");
intent1.setComponent(name);
intent1.putExtra("data","传递的数据");
startActivity(intent1);
目标APP AndroidManifest.xml
配置文件对应的Activity
下添加 android:exported="true"
表示允许其它应用调用当前组件;
目标APP参数处理逻辑如下:
Intent intent=this.getIntent();
if(null != intent.getStringExtra("data")){
//处理数据
}
3.2 从一个APP跳转到另外一个目标APP,并传参
- 执行APP
AndroidManifest.xml
设置。
android:exported="true"
- 执行APP跳转
Intent intent = new Intent(Intent.ACTION\_MAIN);
/\*\*知道要跳转应用的包命与目标Activity\*/
ComponentName componentName = new ComponentName("com.demo.demo", "com.demo.ui.main.DemoActivity");
intent.setComponent(componentName);
intent.putExtra("salesNo", "参数1");
intent.putExtra("code", "参数2");
startActivity(intent);
- 目标APP
AndroidManifest.xml
设置。
android:exported="true"
android:launchMode="singleInstance"
- 目标APP在
onCreate
方法中接收传值:
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
String salesNo = "";
String code = "";
if (bundle != null) {
salesNo = bundle.getString("salesNo");
code = bundle.getString("code");
}
3.2.1 为什么 intent.getStringExtra() 总是返回 null ?
实操过程中,有的同学可能会遇到应用intent.getStringExtra()
返回null
的情形。出现返回null
的原因可能有以下几种:
- 没有正确设置
Intent
传递的数据
可能使用putExtra
方法将数据存放到Intent
中,而接收方在处理数据时没有正确取出来。也有可能是Intent
中并没有存放所需要的数据。
- 在使用
intent.getStringExtra()
之前没有使用intent.hasExtra()
检查是否存在所需的值。
在使用getStringExtra()
方法之前,应该先通过hasExtra()
方法检查是否存在所需的值。没有检查是否存在这个值时,就可能会出现返回null
的情况。
- 使用键值不正确
在从Intent
中取出数据时,需要用到getStringExtra()
方法的参数键值(key
),而有可能使用了错误的键值。需要确保键值正确,才能从Intent
中正确取出所需的数据。
- 数据类型不匹配
在存放数据时,使用了一个错误的数据类型。当使用getStringExtra()
方法去取出时,就会出现返回null
的情况。需要检查所存放的数据的类型是否与要取出的类型一致。
3.2.2 Intent 对象被重用
多次使用同一个PendingIntent
发送广播时,可能会出现Intent
对象被重用的情况,导致获取到的数据不正确。
更多面试题
**《350页前端校招面试题精编解析大全》**内容大纲主要包括 HTML,CSS,前端基础,前端核心,前端进阶,移动端开发,计算机基础,算法与数据结构,项目,职业发展等等
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
能会出现Intent
对象被重用的情况,导致获取到的数据不正确。
更多面试题
**《350页前端校招面试题精编解析大全》**内容大纲主要包括 HTML,CSS,前端基础,前端核心,前端进阶,移动端开发,计算机基础,算法与数据结构,项目,职业发展等等
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
[外链图片转存中…(img-HhHA1oZK-1714136862708)]