`
寻梦者
  • 浏览: 625046 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

关于Android隐式启动Activity

阅读更多

关于Android隐式启动Activity【原创】

更多例子请参考:http://hi.baidu.com/wishwingliao/blog/item/0a38ccfce06f39e8fc037f85.html

 

隐式启动Activity的intent到底发给哪个activity,需要进行三个匹配,一个是action,一个是category,一个是data,可以是全部或部分匹配

同样适用于Service和BroadcastReceiver,下面是以Activity为例

 

 

MainActivity.java --主Activity

TestActivity.java --需要隐式启动的Activity

 

 

(1) 根据Action和Category来进行匹配

 

         <activity android:name=".TestActivity"  android:label="TestActivity">

        <intent-filter >

         <action android:name="cc.android/myaction.leo"/>

         <category android:name="android.intent.category.DEFAULT"/>

        </intent-filter>

        </activity>

 

在MainActivity.java里启动它:

intent.setAction( "cc.android/myaction.leo");

//不加下面这行也行,因为intent的这个属性默认值即系Intent.CATEGORY_DEFAULT

intent.addCategory(Intent.CATEGORY_DEFAULT);

startActivity( intent );

 

总结:

a.在某个Activity里用startActivity()方法发送一个intent,这个intent设定了一些条件,比如用方法setAction(),addCategory()设定了两个属性,

  发送了这个intent之后,android会去系统里保存的MainManifest.xml清单(假设这个系统存放全部apk清单的文件为MainManifest.xml)里查找符合这两个属性的activity,然后启动它。

  查找过程是怎样的呢?

  我猜测:在安装某个apk的时候,android系统会把这个apk的清单文件里内容复制一份至系统的某个清单文件里(假如这个系统存放全部apk清单的文件为MainManifest.xml)

  当某个Activity用startActivity(intentOther)方法向系统发送了一个intent(假如为intentOther),那么android系统会去查找这个MainManifest.xml里注册的<intent-filter >属性,

  查找到符合这个 intentOther 的就启动这个Activity,如果有多个这样的Activity符合条件的话,就跳出一个对话框让用户选择究竟要启动哪一个

 

  上面那个自定义的Action字符串("cc.android/myaction.leo",当然也可以写成这样"cc.android.myaction.leo",同时AndroidManifest.xml里也要写成这样)是系统唯一的,

  所以系统很容易就能匹配到。

 

 

 

b.任何一个需要隐式启动的Activity都必须要有这项:<category android:name="android.intent.category.DEFAULT"/>

例外情况是:android.intent.category.MAIN和android.intent.category.LAUNCHER的filter中没有必要加入android.intent.category.DEFAULT,当然加入也没有问题

 

c.假如有两个Activity,它们的在AndroidManifest.xml里配置如下:

<activity android:name="MyActivityOne" android:label="@string/activityOne">

<intent-filter>

<action android:name="hello.leo.liao" />

<action android:name="hello.leo.leo" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

 

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

<action android:name="hello.leo.liao" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

 

在MainActivity.java里发送一个intent:

intent.setAction( "hello.leo.liao");

//不加下面这行也行,因为intent的这个属性默认值即系Intent.CATEGORY_DEFAULT

intent.addCategory(Intent.CATEGORY_DEFAULT);

startActivity( intent );

 

这样的话,android系统会跳出一个对话框让你选择启动哪一个Activity(MyActivityOne还是MyActivityTwo)

如果把上面的intent.setAction( "hello.leo.liao");改为intent.setAction( "hello.leo.leo");的话,就自动匹配到MyActivityOne

就是说如果category和action都相同的话,会跳出一个对话框让用户选择要启动哪一个activity;

如果category相同,而action不相同,就可以匹配到相应的activity

 

d.单单靠添加addCategory属性不能匹配,如:

Intent intent = new Intent();

intent.addCategory(Intent.CATEGORY_DEFAULT);

intent.addCategory("android.intent.category.hello");

startActivity(intent);

 

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

<category android:name="android.intent.category.DEFAULT" />

<category android:name="android.intent.category.hello"></category>

</intent-filter>

</activity>

 

e.当匹配不上任何Activity的话,会发生异常,跳出对话框:很抱歉...某某应用程序意外停止,请重试。

 

f.Service和BroadcastReceiver 同理

 

 

(2) 根据Action和Data匹配

 

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

             <action android:name="android.intent.action.leo"></action>

                <category android:name="android.intent.category.DEFAULT"></category>

                <data android:scheme="x-id"></data>

</intent-filter>

</activity>

 

//Uri uri = Uri.parse("x-id://www.google.com/getDetails?id=123");//这个也可以

//Uri uri = Uri.parse("x-id");//这个不行

//Uri uri = Uri.parse("x-id://");这个可以

Uri uri = Uri.parse("x-id:");//这个可以

            Intent in = new Intent();

            in.setAction("android.intent.action.leo");//去掉这行不行,单靠data不能匹配

            in.addCategory(Intent.CATEGORY_DEFAULT);//可以去掉这行,因为intent的默认category值即系Intent.CATEGORY_DEFAULT

            in.setData(uri);//去掉这行不行

            startActivity(in);

 

总结:如果在AndroidManifest.xml里面指定了<data>这行,那么,需要匹配到它的话,在代码里必须要设置intent的data,如上面的in.setData(uri)    

Data的语法:

<data android:host="string"

      android:mimeType="string"

      android:path="string"

      android:pathPattern="string"

      android:pathPrefix="string"

      android:port="string"

      android:scheme="string" />

 

Uri的格式:scheme://host:port/path or pathPrefix or pathPattern

 

如果scheme没有指定,那其它的属性均无效;

如果host没有指定,那么port,path,pathPrefix,pathPattern均无效;

 

如果在manifest里这样写:<data android:scheme="something" android:host="project.example.com" />

那么Uri uri = Uri.parse("something://project.example.com"); 才可以匹配

 

再如:

<data android:scheme="something" android:host="project.example.com" android:port="80"/>

等同于这样写:

<data android:scheme="something"/>

<data android:host="project.example.com"/>

<data android:port="80"/>

那么Uri uri = Uri.parse("something://project.example.com:80"); 才可以匹配

 

不知为何,下面这个不行:

<data android:scheme="content" android:host="com.example.project" android:port="200" android:path="folder/subfolder/etc"/>

Uri uri = Uri.parse("content://com.example.project:200/folder/subfolder/etc")

下面这样也不行

<data android:scheme="content" android:host="com.example.project" android:port="200" android:path="folder"/>

Uri uri = Uri.parse("content://com.example.project:200/folder")

 

 

可以有多个data,只需匹配其中一个即可

 

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

             <action android:name="android.intent.action.leo"></action>

                <category android:name="android.intent.category.DEFAULT"></category>

                <data android:scheme="x-id"/>

                <data android:scheme="something"/>

</intent-filter>

</activity>

 

           Intent in = new Intent();

            in.setAction("android.intent.action.leo");

            in.addCategory(Intent.CATEGORY_DEFAULT);

            in.setData(Uri.parse("something:"));//或者用这个亦可in.setData(Uri.parse("x-id:"));            

            startActivity(in);      

 

(3)  根据action和data的mimeType属性匹配          

 

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

<action android:name="android.intent.action.VIEW"></action>

<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />

<category android:name="android.intent.category.DEFAULT"></category>

</intent-filter>

</activity>

在java代码里这样写就可以匹配到这个activity:

            Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因为Category默认值即系Intent.CATEGORY_DEFAULT

            in.setType("vnd.android.cursor.dir/vnd.google.note");

            startActivity(in); 

 

  单靠data的mimeType属性不能匹配,就算这个mimeType是唯一的也不行(比如in.setType("leo.android.cursor.dir/vnd.google.leo");),需要有一个action配合   

 

  可以有多个mimeType,在java代码里只需匹配其中一个即可:

  <activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

  <intent-filter>

<action android:name="android.intent.action.VIEW"></action>

<data android:mimeType="leo.android.cursor.dir/vnd.google.leo" />

<data android:mimeType="leo.android.cursor.dir/vnd.google.liao" />

<category android:name="android.intent.category.DEFAULT"></category>

</intent-filter>

</activity>

 

 

这样可以启动MyActivityTwo这个Activity:

Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因为Category默认值即系Intent.CATEGORY_DEFAULT

            in.setType("leo.android.cursor.dir/vnd.google.liao");

            startActivity(in);

      或者这样也可以启动MyActivityTwo这个Activity:   

      Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因为Category默认值即系Intent.CATEGORY_DEFAULT

            in.setType("leo.android.cursor.dir/vnd.google.leo");

            startActivity(in);

 

 

  scheme和mimeType只能有其中一个,下面这样通不过

  AndroidManifest.xml里:

  <data android:scheme="something" android:host="project.example.com"

android:port="80"

android:mimeType="leo.android.cursor.dir/vnd.google.leo" />  

 

<data android:scheme="something" android:host="project.example.com"

android:port="80" />

<data android:mimeType="leo.android.cursor.dir/vnd.google.leo" />

 

java代码里:

匹配不上:

Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            Uri uri = Uri.parse("something://project.example.com:80");

            in.setData(uri);

            in.setType("leo.android.cursor.dir/vnd.google.leo");

            startActivity(in);                  

 

            这样还是匹配不上:

            Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

//            Uri uri = Uri.parse("something://project.example.com:80");

//            in.setData(uri);

            in.setType("leo.android.cursor.dir/vnd.google.leo");

            startActivity(in);

 

            这样还是匹配不上:

            Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            Uri uri = Uri.parse("something://project.example.com:80");

            in.setData(uri);

//            in.setType("leo.android.cursor.dir/vnd.google.leo");

            startActivity(in);

 

 

 

(4)   一个Activity里可以有多对<intent-filter></intent-filter>  只要匹配其中一对,即可启动这个Activity

 

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

<action android:name="android.intent.action.VIEW"></action>

<data android:scheme="something" android:host="project.example.com"

android:port="80" />

<category android:name="android.intent.category.DEFAULT"></category>

</intent-filter>

 

<intent-filter>

<action android:name="android.intent.action.VIEW"></action>

<data android:mimeType="leo.android.cursor.dir/vnd.google.leo" />

<category android:name="android.intent.category.DEFAULT"></category>

</intent-filter>

 

<intent-filter>

<action android:name="hello.hi.liao"></action>

<category android:name="android.intent.category.DEFAULT"></category>

</intent-filter>

 

</activity>

 

java代码里:

匹配第一对<intent-filter> 可以启动MyActivityTwo这个Activity:

Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因为Category默认值即系Intent.CATEGORY_DEFAULT

            Uri uri = Uri.parse("something://project.example.com:80");

            in.setData(uri);

            startActivity(in);

   匹配第二对<intent-filter> 也可以启动MyActivityTwo这个Activity:    

   Intent in = new Intent();

   in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因为Category默认值即系Intent.CATEGORY_DEFAULT

            in.setAction("android.intent.action.VIEW");

            in.setType("leo.android.cursor.dir/vnd.google.leo");

            startActivity(in);    

 

  匹配第三对<intent-filter> 也可以启动MyActivityTwo这个Activity:      

  Intent in = new Intent();

            in.setAction("hello.hi.liao");

            in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因为Category默认值即系Intent.CATEGORY_DEFAULT

            startActivity(in);      

 

 

 

全部总结:

1.  <action/>包含在 <intent-filter></intent-filter> 标签对里,而且是必不可少的!不管以哪一种方式来匹配,都不可缺少这个<action/> ,可以有多个,至少要有一个。

如有多个的,话只需要匹配其中一个即可找到这个activity

<action>里的属性值大多数是在Intent里定义的,比如<action android:name="android.intent.action.VIEW"/>里的属性值就等于 Intent.ACTION_VIEW,

在这个Intent类里以ACTION开头定义的常量都是。当然,也可以自定义。  

 

 

 

2.  任何一个需要隐式启动的Activity都必须要有这项:<category android:name="android.intent.category.DEFAULT"/>

例外情况是:android.intent.category.MAIN和android.intent.category.LAUNCHER的filter中没有必要加入android.intent.category.DEFAULT,当然加入也没有问题  

<category>里的属性值大多数是在Intent里定义的,比如  <category android:name="android.intent.category.DEFAULT"/>里的属性值就等于 Intent.CATEGORY_DEFAULT,

在这个Intent类里以CATEGORY开头定义的常量都是。当然,也可以自定义。  

 

 

 

3.一个Activity里可以有多对<intent-filter></intent-filter>  只要匹配其中一对,即可启动这个Activity

 

 

 

4.在<intent-filter></intent-filter>里可以有多个<data android:mimeType="xxxx"/>,只需匹配其中一个即可.注意:不可以同时出现第5点的标签对,即下面这条。

 

 

 

 

5.在<intent-filter></intent-filter>里可以有多个<data android:scheme="xxxx" android:host="yyyy" android:port="uuu"/>,只需匹配其中一个即可。

语法:

<data android:host="string"

      android:mimeType="string"

      android:path="string"

      android:pathPattern="string"

      android:pathPrefix="string"

      android:port="string"

      android:scheme="string" />

      可以分开写,如:

      <data android:scheme="something" android:host="project.example.com" android:port="80"/>

等同于这样写:

<data android:scheme="something"/>

<data android:host="project.example.com"/>

<data android:port="80"/>

 

在java代码里,Uri的格式:scheme://host:port/path or pathPrefix or pathPattern

注意:不可以同时出现第4点的标签对,即上面那条。

 

 

 

 

6.在<intent-filter></intent-filter>里可以有多个<action android:name="xxxx"> ,只需匹配其中一个即可。

 

 

 

7.当匹配不上任何Activity的话,会发生异常,跳出对话框:很抱歉...某某应用程序意外停止,请重试。

 

 

 

8.上面所说的全部适用于Service和BroadcastReceiver,只需把<activity ...></activity>换成<service ...></service>或<receiver ...></receiver>即可。

 

9.刚参考了一下packages\apps\HTMLViewer\AndroidManifest.xml,第4和第5条应该是不冲突才对,但是实际测试中却是冲突,暂时未到找原因。匹配方式请看:用于打开HTML文件的intent

 

 

 

 在被启动的Activity(本例为MyActivityTwo)里接收数据:

Intent intent = getIntent();

String intentCategories = intent.getCategories()

String intentType = intent.getType();

Uri uri = intent.getData();

String uriScheme = uri.getScheme();

String uriPath = uri.getPath();

String uriHost = uri.getHost();

String uriEncodedPath = uri.getEncodedPath();

 

请参考:packages\apps\HTMLViewer\src\com\android\htmlviewer\HTMLViewerActivity.java

 

 

 

 

分享到:
评论
2 楼 luo_ganlin 2015-01-07  
别的不多说,点个赞!
1 楼 Will.Du 2012-03-02  
挺好的,解决了问题~~

相关推荐

    Android显式启动与隐式启动Activity的区别介绍

    为什么要写显式启动与隐式启动Activity,Android的Acitivity启动大致有两种方式:显式启动与隐式启动,下面分别介绍

    android 学习笔记7-页面跳转 Activity启动 生命周期 activity数据传递

    2、启动activity-显示启动和隐式启动: 3、隐式启动自己的activity 4、获取隐启动传递过来的data数据 5、显示启动传递数据 6、禁用掉横竖屏切换 7、开启activity获取返回值-startActivityForResult:

    Android程序技术:Activity启动模式与跳转.pptx

    Android 程序技术 本节课程内容:Activity启动模式与跳转 ...隐式意图则是通过指定action和category等属性,由系统根据这些信息进行分析后寻找目标Activity . 跳转实例 Jump instance THANK YOU 谢谢观看

    Android Studio Intent隐式启动,发短信,拨号,打电话,访问网页等实例代码

    Android Studio Intent隐式启动,发短信,拨号,打电话,访问网页等实例代码 功能 创建5个按钮,隐式启动、发短信、拨号按钮、电话按钮、打开网页按钮。通过使用Intent来完成各自按钮下的功能 代码目录如下 详细代码...

    上海建桥学院-移动应用开发-实验报告2-Activity组件通信

    点击“使用显示启动”按钮和“使用隐式启动”按钮,均能跳转至界面2,如图2所示,前者使用显示启动方式,后者使用隐式启动方式,两种启动方式均将界面1中的数据传递至界面2中。 2、 点击界面1中的按钮后,跳转至...

    Android利用Intent启动和关闭Activity

    一、简介 Android应用程序中一般都有多个Activity,...l 隐式启动:安卓系统根据Intent的动作和数据决定应该启动哪个Activity。 1、显式启动Activity 通过Intent显式启动一个Activity时,必须先创建一个Intent对象,并

    实验四、自定义WebView验证隐式Intent的使用

    1.获取URL地址并启动隐式Intent的调用 实验效果: MainActivity.java public class MainActivity extends AppCompatActivity { private EditText urlEditText; private Button button; @Override protected ...

    Android跨应用启动实例详解

    即——使用 隐式Intent方式 启动应用B的某个组件。 一、在开始之前,先来梳理一下跨应用启动的2种方式: 第一种:在Activity中,启动另一个app的组件。 第二种:在Service中,启动另一个app的组件。 从所周知,...

    Android提高之Activity+Intent用法示例

    熟悉Android程序设计的人都知道Android有三个基础组件Activity,Service和BroadcastReceiver,他们都是依赖Intent来启动。本文所要介绍的是Activity的生命周期以及针对Activity的Intent使用。 之前的例子一直都是使用...

    android 后台服务.ppt

    了解Service的原理和用途 掌握进程内服务的管理方法 掌握服务的隐式启动和显式启动方法 了解线程的启动、挂起和停止方法 了解跨线程的界面更新方法 掌握跨进程服务的绑定和调用方法 了解AIDL语言的用途和语法

    Android自主学习项目报告(一).doc

    自主学习项目报告(一) 1. 自主学习项目要求 1....显式Intent(指定启动名称): 明确指出目标组件名称的Intent 告诉Android系统,我要"找谁",Android平台将目标组件启动起来 常用于APP内部组件间启动 隐式Inten

    Activity Schema例子demo

    android 隐式跳转的例子 包含了两个app之间启动页面 栈之间的关系

    Android开发案例驱动教程 配套代码

    9.2.2 隐式Intent 186 9.2.3 匹配组件 186 9.3 多Activity之间跳转 188 9.3.1 多个Activity之间数据传递 189 9.3.2 跳转与返回 192 9.3.3 任务与标志 196 9.4 Android系统内置Intent 199 本章小结 201 第10...

    分享实现Android图片选择的两种方式

    通过隐式启动activity,跳转到相册选择一张返回结果 关键代码如下: 发送请求: private static final int PICTURE = 10086; //requestcode Intent intent = new Intent(); if (Build.VERSION.SDK_INT &lt; 19) {//...

    Activity&Intent的使用-移动平台开发技术-gddrxy

    而隐式Intent则是指定了一系列更为抽象的action和category等信息,然后交由系统去分析这个Intent,并帮我们找出合适的活动去启动。 实验内容: 1. Activity基本使用:手动创建活动、加载布局、控件点击事件、弹出...

    Android基础——Activity基础

    二、通过隐式意图跳转,这种方式的跳转需要我们在AndroidManifest.xml文件中为目的Activity配置Action和Category 模拟账号登录,分别使用俩种方式跳转 这是启动的Activity package ...

    android开发秘籍

    2.3.3 秘诀8:将语音转换成文本并启动activity 显示结果 32 2.3.4 秘诀9:实现选择列表 34 2.3.5 秘诀10:使用隐式intent 创建activity 35 2.3.6 秘诀11:在activity 间传递基本数据类型 37 第3 章 线程、服务、...

    Android Activity与Intent详解及示例代码

    Android有三个基础组件Activity,Service和BroadcastReceiver,他们都是依赖Intent来启动。本文介绍的是Activity的生命周期以及针对Activity的Intent使用。  之前的例子一直都是使用Activity,在一个Layout XML与一...

    Android adb命令运行结果图.png

    配置特定Activity的隐式启动条件,包括 action、data、category等属性。 使用adb调试 通过链接启动一个Activity,

Global site tag (gtag.js) - Google Analytics