`
寻梦者
  • 浏览: 637286 次
  • 性别: 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有两种主要方式:显式启动和隐式启动,这两种方式各有特点,适用于不同的场景。 **显式启动(Explicit Intent)** 显式启动是最常见的启动Activity的方式,它明确指定了要启动的Activity类名。在创建...

    显示Intent和隐式Intent启动Activity的示例

    本示例主要关注如何使用显示Intent和隐式Intent来启动Activity。 1. **显示Intent**: 显示Intent是明确指定目标Activity的Intent,通常在我们知道确切要启动的组件(Activity)时使用。创建显示Intent的代码如下...

    Android利用Intent启动和关闭Activity

    ### 一、Intent启动Activity #### 1. 显式启动 显式启动是通过Intent明确指定要启动的Activity的类名。创建Intent时,你需要在构造函数中传入当前Activity(`this`)和目标Activity的Class对象,如下所示: ```...

    Android中使用隐式方式打开一个新的Activity

    当需要在不同Activity之间跳转时,Android提供了两种Intent类型:显式Intent和隐式Intent。本篇将深入探讨如何使用隐式Intent在Android中打开一个新的Activity。 **隐式Intent** 的主要特点是不直接指定目标...

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

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

    隐式意图跳转Activity

    3. 使用startActivity(Intent)或startActivityForResult(Intent, int)启动Activity。 ```java startActivity(intent); ``` **匹配隐式意图** 系统通过比较Intent的参数与AndroidManifest.xml中&lt;activity&gt;标签中的来...

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

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

    隐式启动

    在Android开发领域,"隐式启动"是一种启动Activity或Service的方式,它与显式启动相对。显式启动通常通过指定组件的完整类名来完成,而隐式启动则是通过发送一个包含特定Intent过滤器的动作、数据、类别等信息来启动...

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

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

    activity显式隐式跳转

    在AndroidManifest.xml文件中,我们需要为每个可被隐式启动的Activity定义Intent Filter,比如: ```xml &lt;activity android:name=".TargetActivity"&gt; &lt;action android:name="android.intent.action.VIEW" /&gt; ...

    隐式意图启动系统各种功能

    在Android开发中,隐式意图(Implicit Intents)是一种强大的机制,它允许应用程序与系统或其它应用程序进行交互,而无需预先知道具体的目标组件。通过隐式意图,开发者可以调用系统提供的各种服务,如打开地图、...

    Android review 显示意图激活与隐式意图激活

    可能包含一个Activity发送显示意图启动另一个Activity,以及创建和解析隐式意图进行文件分享或启动地图应用等操作的示例。 总结来说,Android的意图机制是其灵活性和模块化设计的关键。显示意图提供了内部组件间的...

    android 利用intent调用activity 简明精炼的例子

    总之,Intent是Android中实现组件间通信的关键,通过它可以灵活地启动Activity并传递数据。理解和熟练使用Intent对于Android开发者来说至关重要。在实际项目中,根据需求调整Intent的构造和使用方式,可以实现丰富的...

    Android基础系列的Activity

    显式Intent通过指定目标Activity的类名来启动,而隐式Intent则依赖于AndroidManifest.xml中定义的Intent过滤器来寻找能够处理特定动作和数据类型的Activity。 在AndroidManifest.xml中,必须声明所有的Activity。这...

    android Activity 详述 demo

    Intent是Android中用于在组件间通信的工具,它可以启动Activity、Service,甚至发送广播。Intent分为显式和隐式两种: 1. 显式Intent:明确指定要启动的Activity,通过类名或组件名指定。 2. 隐式Intent:不指定...

    android之activity跳转 窗口跳转

    总结来说,Android中的Activity跳转是通过Intent进行的,可以显式或隐式启动,传递数据,选择不同的启动模式,同时还需要理解Activity的生命周期和返回栈管理,以便构建高效、用户体验良好的应用。在实际开发中,应...

    035_android_Activity入门和跳转

    在Android中,启动Activity通常通过Intent对象完成。Intent是一个意图对象,表示一种操作的意图,它可以携带数据。使用startActivity()或startActivityForResult()方法启动新Activity。 5. Intent的种类: - 显式...

Global site tag (gtag.js) - Google Analytics