Intent ---> 一个万能的信使

Intent的奥秘

Intent称为信使简直在形象不过了。
随着Android开发经验的增长,慢慢随着时间的积累,我们会很自然的发现一些让人佩服的东西,Intent就是其中一个。
我现在看见这个关键字,脑子里立马浮现出古代的信鸽、钦差。传递信息、传递动作。
今天我们就根据它的特性延伸一下,来解决项目中的需求。

Intent的应用详解

这块是本文最关键,也是最基本的知识
不太明白的朋友我推荐一篇很详细的博文

万能信使的诞生

那现在就进入主题吧。为什么这么叫呢?
先卖个关子!在这个产品横行的时代,在他们的’督促‘下,我们程序员不停的在进化。至少我们知
一下几点:

  1. 代码不能写死,随时准备着改;
  2. 客户端的功能最好能让服务端控制;
  3. 随时准备重构别人的代码(已经被产品送走了)

好了言归正传,我也是因为上面的第二个原因做了这个事情。
直接用需求来说:这个界面用native去写,不用h5,但是我还要能在服务端控制这个页面上的某些View的’行为’。
也就是说有一个按钮,我可以在服务端去控制它打开一个新Activity,还是一个网页,还是预先定义好的某种行为。

也就是在这个时候我发现了万能的信使Intent,正好能解决这种问题。
同时我也说明一下,今天我只是讲这种实现的方式,只是取其中的原理性东西来说。更多的idea,更多的需求,只希望你看完后能有所启示吧。

Demo源码

项目在Github上:GitHub
顺便简单介绍一下Demo:一次偶然的机会,扔物线的推荐下开始了使用Rxjava + Retrofit网络库,深深地迷上了它(我指的是它,而不是这个胖子,哈哈~~)
这些代码是我从整个项目里面摘出来的,可能会有一些残留,见谅哈!我尽量处理干净。

万能的Intent

先介绍Intent的跳转规则:

/** 
 * 打电话
 * @param view 
 */
public void call(View view) {  
    Intent intent = new Intent(Intent.ACTION_CALL);  
    intent.setData(Uri.parse("tel:1234567890"));  
    startActivity(intent);  
} 
/** 
 * 打开指定网页 
 * @param view 
 */  
public void invokeWebBrowser(View view) {  
    Intent intent = new Intent(Intent.ACTION_VIEW);  
    intent.setData(Uri.parse("http://www.google.com.hk"));  
    startActivity(intent);  
}

就上面这段代码中intent.setData()的方法,里面需求传入各种系统规定好的标签,按照这种规则去通过Uri.parse去按照规则解析,从而获得这种行为动作。
那么我们如何知道目标是否接受这种前缀呢?这就需要看一下目标中<data/>元素的匹配规则了。
在目标<data/>标签中包含了以下几种子元素,他们定义了url的匹配规则:
android:scheme 匹配url中的前缀,除了“http”、“https”、“tel”...之外,我们可以定义自己的前缀
android:host 匹配url中的主机名部分,如“google.com”,如果定义为“*”则表示任意主机名
android:port 匹配url中的端口
android:path 匹配url中的路径
我们看下面的这两块代码,这是和Android浏览器之间交互的规则

<activity android:name=".TestActivity">  
    <intent-filter>  
        <action android:name="com.scott.intent.action.TARGET"/>  
        <category android:name="android.intent.category.DEFAULT"/>  
        <data android:scheme="scott" android:host="com.scott.intent.data" android:port="9090" android:path="/test"/>  
    </intent-filter>  
</activity> 
public void gotoTestActivity(View view) {  
    Intent intent = new Intent("com.scott.intent.action.TARGET");  
    intent.setData(Uri.parse("scott://com.scott.intent.data:9090/test"));  
    startActivity(intent);  
} 

我们用Intent调系统打电话为例:

顺序图

这些信息的中的标签都是系统自己定义的,那么我们需要解决自己的需求,就要定义自己的规则。
下面我们一起来一步一定义我们自己的规则,来满足我们的需求。如果上面的系统规则不明白,没事。接着往下走,串起来就都明白了。

自定义规则

直接打开一个Activity

首先,我们看一下Intent的源码,其中有一个parseUri方法。
里面写的很清楚,系统定义的规则开头是以android-app开头的,并且是以end结尾

     *     <tr><td><code>android-app://com.example.app/http/example.com/foo?1234<br/>#Intent;action=com.example.MY_ACTION;end</code></td>
     *         <td><table style="margin:0;border:0;cellpadding:0;cellspacing:0">
     *             <tr><td>Action: </td><td><code>com.example.MY_ACTION</code></td></tr>
     *             <tr><td>Data: </td><td><code>http://example.com/foo?1234</code></td></tr>
     *             <tr><td>Package: </td><td><code>com.example.app</code></td></tr>
     *         </table></td>
     *     </tr>

这是源码中的一条规则

android-app://com.example.app/http/example.com/foo?1234#Intent;action=com.example.MY_ACTION;end

android-app:这部分表示系统规则的前缀,所以在我们自己定义规则时需要将系统的屏蔽掉,以免冲突,所以我们现在用intent做以区分,并且表明这个规则是要生成Intent
#Intent而这一句则是规则真正的开始,源码中的一句i = uri.lastIndexOf("#");也就是从#开始到end才是我们需要自己定义的规则
Action就是我们要做的事,但是我们今天的需求是跳转行为,所以这个用component

好了,介绍完系统的规则,来看一下打开我们定义的某个Activity的规则

"intent:#Intent;component=com.alex.alexintentdemo/.ui.TestActivity;end"

component=com.alex.alexintentdemo/.ui.TestActivity这个我相信大家看了绝对眼熟,没错,这个就是系统的规则,在New IntentsetComponent然后startActivity时,需要填写的,告诉系统我要打开那个Activity

好了,既然规则写好了,那么接下来我们再根据规则生成Intent,去调用

刚才讲的这一整体部分最好结合代码去看,UriUtils解析自定义Uri的类

直接打开一个接受参数的Activity

这种直接打开Activity有点太low了,接下来,我们要解决怎么打开一个接受参数的Activity
首先,我们看一下系统的支持参数的源代码

String key = Uri.decode(uri.substring(i + 2, eq));
if (uri.startsWith("S.", i)) {
        intent.putExtra(key, value);
  } else if (uri.startsWith("B.", i)) {
      intent.putExtra(key, Boolean.parseBoolean(value));
  } else if (uri.startsWith("b.", i)) {
      intent.putExtra(key, Byte.parseByte(value));
  } else if (uri.startsWith("c.", i)) {
      intent.putExtra(key, value.charAt(0));
  } else if (uri.startsWith("d.", i)) {
      intent.putExtra(key, Double.parseDouble(value));
  } else if (uri.startsWith("f.", i)) {
      intent.putExtra(key, Float.parseFloat(value));
  } else if (uri.startsWith("i.", i)) {
      intent.putExtra(key, Integer.parseInt(value));
  } else if (uri.startsWith("l.", i)) {
      intent.putExtra(key, Long.parseLong(value));
  } else if (uri.startsWith("s.", i)) {
      intent.putExtra(key, Short.parseShort(value));
    } else throw new URISyntaxException(uri, "unknown EXTRA type", i);

这样我们可以看出,所有的基本类型都支持,并且有一套完整的书写规则:
我们常用的有下面三个,其他的都支持

 S.xxx=[string];//字符串类型
 B.xxx=[boolean];//布尔型
 i.xxx=[int];//整型

所以我们传参数的规则如下:

intent:#Intent;component=com.alex.alexintentdemo/.ui.Test2Activity;B.flag=true;S.name=大家好;i.code=1221;end

特别提示:每一条指令之间用区分

直接打开Http/Https链接

这个就相对简单了,看源码,只是在Uri解析的时候区分一下http/https的前缀。
规则直接下发链接就可以了。

服务端控制行为

只要在init或者开发App的时候从服务端取下这些规则,在点击按钮,或者需要出发的时候调一下CommonUtils.jumpWithUri()就可以了

CommonUtils.jumpWithUri(MainActivity.this,“rule”);

可扩展的需求

今天在这里只是自定义了打开Activity。其实,其余的方式都是一样的,只要明白了这一点就能相通了。
我在这里先列出几个:

  1. 打开Fragment;
  2. WebView传参数;
  3. 弹出Toseat;
  4. 等等,太多了,只要你想的到,只要你的规则能写好,一切都不是事。

后续我会慢慢给Demo里完善这些东西

结束

很感谢大家能阅读完这篇博文,写的不合理、不行清楚、有错误,请评论指出,我们共同学习成长。

版权声明:本文为博主原创文章,转载请注明出处。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容