回顾Android中的隐式Intent的相关知识点。

      • 概述
      • 使用
        • action标签
        • category标签
        • data标签
          • mimeType
          • scheme
          • host
          • port
          • path
          • pathPrefix
          • pathPattern
        • data总结
      • 从网页启动app

概述

隐式启动主要解决了界面间的跳转解耦,主要涉及intent-filter中的三个标签:

  • category
  • action
  • data

    它们构成了隐式启动的匹配项,通过不同的配置完成不同的路由跳转。

使用

列一个例子,新建一个APP有两个界面,一为MainActivity,一个为ActionActivityMainActivity中有一个按钮,通过按钮启动隐式Intent来启动ActionActivity
布局和代码非常简单:
MainActivity的布局和代码:

//布局中只有一个按钮<?xml version="1.0" encoding="utf-8"?>"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">    

ActionActivity的布局和代码:

//布局中就是一行文字说明<?xml version="1.0" encoding="utf-8"?>"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=".ActionActivity">"我是跳转的页面"    android:layout_width="match_parent"    android:layout_height="wrap_content" />//代码public class ActionActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_action);    }}

action标签

MainActiity的按钮添加代码,如果找不到的话会抛出异常,因此捕获并打印启动失败的信息:

btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {          try{                //Intent action1 = new Intent("action1");//可以使用构造传入action参数                Intent action1 = new Intent();                action1.setAction("action1");                startActivity(action1);            }catch (Exception e){                    Toast.makeText(MainActivity.this,"启动失败",Toast.LENGTH_LONG).show();                    e.printStackTrace();                }        });

清单文件中的ActionActivity的配置,可以看到只使用了action标签:

        <activity android:name=".ActionActivity">            <intent-filter>                <action android:name="action1"/>            intent-filter>        activity>

启动MainActivity,点击按钮,结果抛出异常:

异常结果为:

android.content.ActivityNotFoundException: No Activity found to handle Intent { act=action1 }

所以实际上ActionActivity只配置action标签是不够的。

category标签

增加默认的android.intent.category.DEFAULT

<activity android:name=".ActionActivity">            <intent-filter>                <category android:name="android.intent.category.DEFAULT"/>                <action android:name="action1"/>            intent-filter>        activity>

intent的代码不做变动,这时点击按钮可以正常跳转:

说明这里category 是必须要配置的,Intent虽然没有设置category,但是默认就是这个android.intent.category.DEFAULT,所以能够匹配到。
再增加一个action试试:

        <activity android:name=".ActionActivity">            <intent-filter>                <category android:name="android.intent.category.DEFAULT"/>                <action android:name="action1"/>                <action android:name="action2"/>            intent-filter>        activity>

intent的代码不做变动,点击按钮依旧可以正常跳转,效果不再贴出。
如果给Intent增加一个intent-filter标签中没有的action试试:

 Intent action1 = new Intent();                action1.setAction("action1");                action1.setAction("action3");                startActivity(action1);

点击抛出ActivityNotFoundException异常,,效果不再贴出。
通过上面的测试说明intent设置的action必须为目标页面intent-filteraction的子集才能正常跳转,并且是区分大小写的。

测试完了action,更换下category为自定义的category1试试:

<activity android:name=".ActionActivity">            <intent-filter>                <category android:name="category1"/>                <action android:name="action1"/>            intent-filter>        activity>

代码中:

                Intent action1 = new Intent();                action1.setAction("action1");                action1.addCategory("category1");                startActivity(action1);

运行点击抛出ActivityNotFoundException异常,效果不再贴出。
然后增加android.intent.category.DEFAULT这个默认的action在测试:

         <activity android:name=".ActionActivity">            <intent-filter>                <category android:name="android.intent.category.DEFAULT"/>                <category android:name="category1"/>                <action android:name="action1"/>            intent-filter>        activity>

运行点击按钮可以正常跳转,效果不再贴出。
说明android.intent.category.DEFAULT这个默认的action是必须要在intent-filter标签中声明的。
如果存在多个action匹配的页面,那么启动后会弹出选择对话框,比如编写一个新的界面为Action2Activity,它也接受action1的动作:
布局:

<?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"    tools:context=".Action2Activity">    <TextView        android:text="我也是跳转的页面!"        android:textSize="32dp"        android:layout_width="match_parent"        android:layout_height="wrap_content" />LinearLayout>

清单文件:

 <activity android:name=".Action2Activity">            <intent-filter>                <category android:name="android.intent.category.DEFAULT" />                <action android:name="action1" />            intent-filter>        activity>

代码只设置action1

                    Intent action1 = new Intent();                    action1.setAction("action1");                    startActivity(action1);

运行效果:

如果再增加一个自定义的category2试试:

 <activity android:name=".ActionActivity">            <intent-filter>                <category android:name="android.intent.category.DEFAULT"/>                <category android:name="category1"/>                <category android:name="category2"/>                <action android:name="action1" />            intent-filter>        activity>

代码不做变动,点击按钮可以正常跳转。
如果在代码中增加一个category3试试:

 Intent action1 = new Intent();                action1.addCategory("category1");                action1.addCategory("category3");                action1.setAction("action1");                startActivity(action1);

运行点击抛出ActivityNotFoundException异常,效果不再贴出。
同样说明intent中的category,必须为目标页面intent-filtercategory的子集才能正常跳转,和action的匹配规则是一样的。
另外说明下,只使用category而不添加任何action也是无法匹配的,说明intent中的action是必须要设置的。而且如果配置了多个intent-filter标签也是按照一组一组进行匹配的,直到与其中一组匹配成功。

data标签

data标签自然不是必须的,主要为URL的表现形式,它的格式如下:

                <data android:mimeType=""/>//媒体类型 例如 "image/*"就是匹配图片类型                <data android:scheme=""/>//例如: http,https                <data android:host=""/>//例如:www.csdn.net                <data android:port=""/>//例如:8080                <data android:path=""/> // 路径:如 /nav/blockchain                <data android:pathPrefix=""/>                <data android:pathPattern=""/>// 正则表达式标识的路径                <data android:ssp=""/>                <data android:sspPrefix=""/>                <data android:sspPattern=""/>

data的属性比较多:

  • mimeType 媒体类型 例如 image/*就是匹配图片类型,mimeType类型比较多 ,这里不再列出;
  • scheme类似如 http,https
  • host类似www.csnd.com
  • port类似 8080
  • path 路径:/nav/blockchain
  • pathPrefix 路径前缀:/nav
  • pathPattern 路径的正则表达式方式
  • ssp //可以匹配系统特定intent 相关文章通过android:ssp高效过滤Android Intents
  • sspPrefix//可以匹配系统特定intent
  • sspPattern//可以匹配系统特定intent

    类似这样://:[||]
    例如action://action1:44/abc/xyz

mimeType

改动下上面的例子:

        <activity android:name=".ActionActivity">            <intent-filter>                <category android:name="android.intent.category.DEFAULT"/>                <action android:name="action1"/>                <data android:mimeType="image/*"/>//指定媒体类型为图片的类型            intent-filter>        activity>

代码中不设置action,只设置mimeType

                    Intent action1 = new Intent();                    action1.setType("image/png");//指定了媒体类型为png的图片类型                    startActivity(action1);

运行效果:

这里可以看到只要有任何能够匹配的mimeTypeimage/png的应用都会在底部的列表弹出,但是如果Intent不设置mimeType而只设置action,那么是无法匹配的,说明mimeType的需要优先匹配的。
如果actionmimeType完全匹配,就可以更为精准的匹配。
需要注意的是清单文件中设置了mimeType而不设置scheme的话,intent中的默认的schemecontent或者file才能进行匹配(在API 24以后只能对应contentscheme了),意味着mimeType其实对应了默认的scheme
看下代码实现:

                    Intent action1 = new Intent();                    action1.setDataAndType(Uri.parse("content://action1"),"image/png");                    action1.setAction("action1");                    startActivity(action1);

这里setDataAndType方法才能同时设置datamimeType,单独使用setData或者setType两者都会将对方清空。
同样如果清单文件中指定了多个mimeType那么,只要Intent匹配到一个就可以。

scheme

在上面的例子中scheme就是content://action1中的content了,更改个自定义的scheme测试:

 <activity android:name=".ActionActivity">            <intent-filter>                <category android:name="android.intent.category.DEFAULT" />                <action android:name="action1" />                <data android:mimeType="image/*"/>                <data android:scheme="action"/>            intent-filter>        activity>
 Intent action1 = new Intent();  action1.setDataAndType(Uri.parse("action://action1"),"image/png");  action1.setAction("action1");  startActivity(action1);

运行可以正常启动的,这里不再帖效果。当然清单文件不设置mimeType的话,Intent就可以使用setData方法来设置URL的。

host

上面例子的action://action1action1就是host了,需要注意的是如果清单文件中没有指定host的话, portpathpathPrefixpathPattern都不会生效。

port

port需要和host放在同一个data标签内才能生效:

 <activity android:name=".ActionActivity">            <intent-filter>                <category android:name="android.intent.category.DEFAULT" />                <action android:name="action1" />                <data android:scheme="action"/>                <data android:host="action1" android:port="44"/>                <data />            intent-filter>        activity>

代码:

 Intent action1 = new Intent(); action1.setData(Uri.parse("action://action1:44")); action1.setAction("action1"); startActivity(action1);

可以正常跳转。

path

代码增加/abc/xyz

 Intent action1 = new Intent(); action1.setData(Uri.parse("action://action1:44/abc/xyz")); action1.setAction("action1"); startActivity(action1);

清单文件:

 <activity android:name=".ActionActivity">            <intent-filter>                <category android:name="android.intent.category.DEFAULT" />                <action android:name="action1" />                <data android:scheme="action"/>                <data android:host="action1" android:port="44"/>                <data android:path="/abc/xyz"/>//必须以/开头                <data />            intent-filter>        activity>

这样完全匹配。

pathPrefix

匹配path的前缀,上面例子中就是/abc

 <activity android:name=".ActionActivity">            <intent-filter>                <category android:name="android.intent.category.DEFAULT" />                <action android:name="action1" />                <data android:scheme="action"/>                <data android:host="action1" android:port="44"/>                <data android:pathPrefix="/abc"/>                <data />            intent-filter>        activity>
pathPattern

利用正则表达式/.*匹配/abc:

 <activity android:name=".ActionActivity">            <intent-filter>                <category android:name="android.intent.category.DEFAULT" />                <action android:name="action1" />                <data android:scheme="action"/>                <data android:host="action1" android:port="44"/>                <data android:pathPattern="/.*/xyz"/>            intent-filter>        activity>

.*就是表示匹配任意字符,这样也能够灵活匹配,需要注意正则表达式中的符号如果当做字符处理需要进行转义。

data总结

比如要匹配action://action1:44/abc/xyz这样的URL的话,清单文件中至少需要写到scheme:

   <data android:scheme="action"/>

其实也就是说Intent中的data应该为清单文件中data的子集。

从网页启动app

隐式Intent也可以从网页中启动Activity,比如有一个远程网页内容如下:

<html lang="en"><head>    <meta charset="UTF-8">    <title>Titletitle>head><body><a href="action://action1:44/abc/xyz?m=1&n=2">启动页面a>body>html>

a标签中的href为自定义链接,对应的在清单文件中做出改动:

        <activity android:name=".ActionActivity">            <intent-filter>                <category android:name="android.intent.category.DEFAULT" />                <category android:name="android.intent.category.BROWSABLE" />                <action android:name="android.intent.action.VIEW" />                <data                    android:scheme="action"                    android:host="action1"                    android:port="44"                    android:path="/abc/xyz"                   />            intent-filter>        activity>

ActionActivity中可以获取各种数据:

public class ActionActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_action);        Uri data = getIntent().getData();        if (data != null){            Log.d("url",data.toString());            String scheme = data.getScheme();            Log.e("scheme", scheme);            String host = data.getHost();            Log.e("host", host);            int port = data.getPort();            Log.e("port", port+"");            String path = data.getPath();            Log.e("path", path);            List<String> pathSegments = data.getPathSegments();//路径分割            String params = data.getQuery();            Log.e("params", params);            String value = data.getQueryParameter("m");            Log.e("m值", value);        }    }}

如果从浏览器中打开页面,点击a标签链接,可以成功跳转并看到打印结果:

08-20 11:33:01.181 4491-4491/cn.franky.test E/scheme: action08-20 11:33:01.182 4491-4491/cn.franky.test E/host: action108-20 11:33:01.182 4491-4491/cn.franky.test E/port: 4408-20 11:33:01.182 4491-4491/cn.franky.test E/path: /abc/xyz08-20 11:33:01.182 4491-4491/cn.franky.test E/params: m=1&n=208-20 11:33:01.182 4491-4491/cn.franky.test E/m值: 1

隐式Intent总结到此。

更多相关文章

  1. android 关掉Eclipse的自动代码提示
  2. 学习android笔记1 之工具篇
  3. 简单音乐播放实例的实现,Android(安卓)Service AIDL 远程调用服
  4. Android(安卓)混淆 以及 java代码方式实现混淆配置
  5. android 之访问WebService显示手机号码归属地
  6. Android积累之《Android(安卓)strings.xml文件定义字符串中的标
  7. android 使用ContentProvider共享数据
  8. Android(安卓)两个Activity之间信息的交互
  9. android 打包时报错解决

随机推荐

  1. Android的OpenGL学习笔记(2)
  2. Android 完美的水平方向滑动ListView
  3. 利用android_ndk以及OpenGLES开发动态壁
  4. Android(安卓)实现轮播图效果(二) 底部圆点
  5. 总体把握Android中的触摸事件处理
  6. 《Android》Lesson01-环境配置
  7. 索尼爱立信:今年推出Android智能机将升至
  8. 利用Android studio开发JNI工程
  9. 关于android 字体
  10. Android中Application、静态变量和Shared