安卓013Intent


一、 Intent  详解
1.1.  概念
Intent (意图)的概念:表示我们要执行的某个操作。例如:查看某联系人的详细资料,
发邮件给某人并传送一个文件,打电话给某人说某事。
Intent 是 Android 程序中传输数据的核心对象,在 Android 官方文档中,对 Intent 的定义是
执行某操作的一个抽象描述,
一个 Android 程序主要是由 3 种组件组成,这 3 种组件是独立的,它们之间可以互相调用,
协调工作,最终组成一个真正的 Android 程序.这些组件之间的通信主要是由 Intent 协助完成
的. Intent 负责对应用中一次操作的动作,支作涉及数据.附加数据进行描述.Android 则根据此
Intent 描述,负责找到对应的组件,将 Intent 传递给调用的组件,并完成组件的调用. 因此 Intent
在这起着一个中介的作用, 专门提供组件互相调用的相关信息, 实现调用者与被调用者之
间的解藕.
Intent 对象主要用来在 Android 程序的 Activity,Servie 和 BroadcastReceiver 这 3 大组件之
间传输数据,而针对这 3 大组件,有独立的 Intent 传输机制,分别如下:
1 、启动 Activity :
startActivity()
startActivtyForResult()
2 、启动 Service :【后面详细讲】
ComponetName startService()
boolean bindService()
3 、启动 BroadcastReceiver :【后面详细讲】
sendBroadcast()
sendOrderedBroadcast ()
sendStickyBroadcast()
sendStickyOrderedBroadcast()
说明: 在每种传输机制下,Android 的 程序会自动查找合适的 Activity,Service  或者
BroadcastReceiver  来响应 Intent( 意图)
这些消息系统之间没有重叠, 即广播意图只会传递给广播接收者, 而不会传递活动或服
务, 反之亦然
1.2.  Intent  对象的组成
1、component(目标组件):目标组件。
2、Action(动作):用来表示意图的动作,如:查看,发邮件,打电话
3、category(类别):用来表示动作的类别, 从 android 上启动 Activity 有多种方式,比如 程
序列表、桌面图标、点击 Home 激活的桌面等等,Category 则用来标识这些 Activity 的图标
会出现在哪些启动的上下文环境里
4、data(数据):保存需要传递的数据格式。如:查看 联系人 tel://
5、type(数据类型):对 data 类型的描述。
6、extras(附件信息):保存需要传递的额外数据。
7、Flags(标记标识)
1.2.1 Component
指定了ComponentName属性的Intent已经明确了它将要启动哪个组件,因此这种Intent
被称为显式 Intent,没有指定 ComponentName 属性的 Intent 被称为隐式 Intent。隐式 Intent
没有明确要启动哪个组件,应用会根据 Intent 指定的规则去启动符合条件的组件。
常用方法
public Intent setComponent(ComponentName component)参数为要设置的组件的名称
public Intent setClass(Context packageContext, Class<?> cls)第一个参数不当前 Activity 的 class
对象
public Intent setClassName(Context packageContext, String className)第二个参数为设置要打
开的 Activity 的名称
public Component getComponent()返回与 Intent 相前的组件名称
代码
Intent intent = new Intent();
ComponentName cName = new ComponentName(MainActivity.this,NextActivity.class);
intent.setComponent(cName);
startActivity(intent);
//实际上,以上的写法都被简化为以下写法:
Intent intent = new Intent(MainActivity.this,NextActivity.class);
startActivity(intent);
//也就是说,平时我们最常用的 Intent 页面跳转的写法就调用的是显式 Intent。
, 此外,ComponentName 属性可以实现一个 app 跳转到另一个 app。
Intent intent = new Intent();
ComponentName cName = new ComponentName(
"com.steven.testasyncloader.sqlitedata","com.steven.testasyncloader.sqliteda
ta.MainActivity");
//其中两个参数的含义:第一个是要跳转到的 app 的包名,第二个参数是该包中的要跳转
到 app 的页面的 class
intent.setComponent(cName);
startActivity(intent);
1.2.2 Action
, 通常,Action、 、Category 属性结合使用 ,定义这两个属性都是在配置文件的<intent-filter>
节点中。Intent 通过定义 Action 属性(其实就是一段 自定义的字符串 ),这样就可以把 Intent
与具体的某个 Activity 分离,实现了 解耦 。否则,每次跳转,都要写成类似 new
Intent(MainActivity.this,NextActivity.class) 这样的形式,也就是说必须将要跳转的目标
Activity 的名字写出来,这样的编码其实是“硬编码”,并没有实现 松耦合 。调用 Intent 对象
的 setAction()方法实现页面跳转虽然略微复杂(需要在 AndroidManifest.xml 文件中配置),
但是实现了解耦。
setAction(String action)用来设置 Intent 的动作,参数可以为常量
getAction 方法用来获取 Intent 动作名称
示例代码
Intent intent = new Intent();
intent.setAction("com.example.android06lifecycle.nextactivity");
startActivity(intent);
//在配置文件中注册 Activity 的时候需要声明:
<activity android:name="com.steven.android06lifecycle.NextActivity">
<intent-filter>
<action android:name="com.example.android06lifecycle.nextactivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
//当某个页面是默认启动页面时,需要定义 Action、Category 的属性必须为以下字符串:【设
置任务入口】
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
常用 Action  属性常量:
Intent 对象不仅可以启动本应用内的程序组件,也可以启动 Android 系统的其他应用的
组件,包括系统内置的程序组件(需要设置权限)。
ACTION_MAIN:(android.intent.action.MAIN)Android 程序入口。
每个 Android 应用必须且只能包含一个此类型的 Action 声明。【如果设置多个,则哪个在前,
执行哪个。】
ACTION_VIEW: (android.intent.action.VIEW) 显示指定数据。
ACTION_EDIT: (android.intent.action.EDIT) 编辑指定数据。
ACTION_DIAL: (android.intent.action.DIAL) 显示拨号面板。
ACTION_CALL: (android.intent.action.CALL) 直接呼叫 Data 中所带的号码。
ACTION_ANSWER: (android.intent.action.ANSWER) 接听来电。
ACTION_SEND: (android.intent.action.SEND) 向其他人发送数据(例如:彩信/email)。
ACTION_SENDTO: (android.intent.action.SENDTO) 向其他人发送短信。
ACTION_SEARCH: (android.intent.action.SEARCH) 执行搜索。
ACTION_GET_CONTENT: (android.intent.action.GET_CONTENT) 让用户选择数据,并返
回所选数据。
1.2.3 Category
Category 属性为 Action 增加额外的附加类别信息。CATEGORY_LAUNCHER 意味着在加载程序
的时候 Acticity 出现在最上面,而 CATEGORY_HOME 表示页面跳转到 HOME 界面。
1 、实现页面跳转到 HOME  界面的代码:【记忆】
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGOTY_HOME);
startActivity(intent);
2 、常用 Category  属性常量:
  CATEGORY_DEFAULT: (android.intent.category.DEFAULT) Android 系统中默认的
执行方式,按照普通 Activity 的执行方式执行。
  CATEGORY_HOME: (android.intent.category.HOME) 设置该组件为 Home Activity。
  CATEGORY_PREFERENCE: (android.intent.category.PREFERENCE) 设置该组件为
Preference。
  CATEGORY_LAUNCHER: (android.intent.category.LAUNCHER) 设置该组件为在当
前应用程序启动器中优先级最高的 Activity,通常与入口 ACTION_MAIN 配合使用。
  CATEGORY_BROWSABLE: (android.intent.category.BROWSABLE) 设置该组件可以
使用浏览器启动。
1.2.4 Data
Data 属性通常用于向 Action 属性提供操作的数据。Data 属性的值是个 Uri 对象。
Uri 的格式如下:scheme://host:port/path 不同的动作有不同的数据类型,如打电话是电
话号码,发信息是字符串
说明:当匹配一个 Intent 到一个能够处理数据的组件时,明确其数据类型(它的 MIME 类
型)和 URI 很重要,例如,一个用于显示图像数据的组件,不应该被调用去播放一个音频文件
设置方式
setData(Uri data)方法用来为 Intent 设置 URI 数据,
setType(String type)方法用来为 Intent 设置数据的 MIME 类型
setDataAndType(Uri data,String type)方法用来为 Intent 设置数据及其 MIME 类型,其语法格式
如下:
getData()方法用来获取与 Intent 相关的数据
getType()方法用来获取与 Intent 相关的数据的 MIME 类型
系统内置的几个 Data  属性常量:
  tel://:号码数据格式,后跟电话号码。
  mailto://:邮件数据格式,后跟邮件收件人地址。
  smsto://:短息数据格式,后跟短信接收号码。
  content://:内容数据格式,后跟需要读取的内容。
  file://:文件数据格式,后跟文件路径。
  market://search?q=pname:pkgname:市场数据格式,在 Google Market 里搜索包名
为 pkgname 的应用。
  geo://latitude, longitude:经纬数据格式,在地图上显示经纬度所指定的位置。
Intent 利用 Action 属性和 Data 属性启动 Android 系统内置组件的代码:【不需要记忆,用到
的时候查找资料】
(一)、拨打电话:
Intent intent=new Intent();
intent.setAction(Intent.ACTION_CALL);
//intent.setAction("android.intent.action.CALL"); //以下各项皆如此,都有两种写法。
intent.setData(Uri.parse("tel:1320010001"));
startActivity(intent);
//调用拨号面板:
Intent intent=new Intent();
intent.setAction(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:1320010001"));
startActivity(intent);
//调用拨号面板:
Intent intent=new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("tel:1320010001"));
startActivity(intent);
(二)、利用 Uri 打开浏览器、打开地图等:
Uri uri = Uri.parse("http://www.google.com"); //浏览器
Uri uri=Uri.parse("geo:39.899533,116.036476"); //打开地图定位
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(uri);
startActivity(intent);
1.2.5 Type
1、Type 属性用于指定 Data 所指定的 Uri 对应的 MIME 类型。MIME 只要符合“abc/xyz”
这样的字符串格式即可。
2 、 Intent  利用 Action 、Data 和 和 Type  属性启动 Android  系统内置组
件的代码:
播放视频:
Intent intent = new Intent();
Uri uri = Uri.parse("file:///sdcard/media.mp4");
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "video/*");
startActivity(intent);
1.2.6 Extras
通过 intent. putExtra (键, 值)的形式在多个 Activity 之间进行数据交换
系统内置的几个 Extra  常量:
EXTRA_BCC:存放邮件密送人地址的字符串数组。
EXTRA_CC:存放邮件抄送人地址的字符串数组。
EXTRA_EMAIL:存放邮件地址的字符串数组。
EXTRA_SUBJECT:存放邮件主题字符串。
EXTRA_TEXT:存放邮件内容。
EXTRA_KEY_EVENT:以 KeyEvent 对象方式存放触发 Intent 的按键。
EXTRA_PHONE_NUMBER:存放调用 ACTION_CALL 时的电话号码。
3 、 Intent  利用 Action 、Data 和 和 Type 、Extra  属性启动 Android  系
统内置组件的代码:
调用发送短信的程序
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setType("vnd.android-dir/mms-sms");
intent.putExtra("sms_body", "信息内容...");
startActivity(intent);
//发送短信息
Uri uri = Uri.parse("smsto:13200100001");
Intent intent = new Intent();
intent.setAction(Intent. ACTION_SENDTO );
intent.setData(uri);
intent.putExtra("sms_body", "信息内容...");
startActivity( intent );
//发送彩信,设备会提示选择合适的程序发送
Uri uri = Uri.parse("content://media/external/images/media/23"); //设备中的资源(图像或其
他资源)
Intent intent = new Intent();
intent.setAction(Intent. ACTION_SEND );
intent.setType("image/png");
intent.putExtra("sms_body", "内容");
intent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(it);
发送 Email:
Intent intent=new Intent();
intent.setAction(Intent. ACTION_SEND );
String[] tos={"[email protected]"};
String[] ccs={"[email protected]"};
intent.putExtra(Intent.EXTRA_EMAIL, tos);
intent.putExtra(Intent.EXTRA_CC, ccs);
intent.putExtra(Intent.EXTRA_TEXT, "The email body text");
intent.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");
intent.setType("message/rfc822");
startActivity(Intent.createChooser(intent, "Choose Email Client"));
Intent intent = new Intent(Intent.ACTION_SEND);
String[] tos = { "[email protected]" };
intent.putExtra(Intent.EXTRA_EMAIL, tos);
intent.putExtra(Intent.EXTRA_TEXT, getPhoneParameter());
intent.putExtra(Intent.EXTRA_SUBJECT, "Android 日志");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(cacheDir));
intent.setType("message/rfc882");
intent.setType("plain/text");
Intent.createChooser(intent, "请选择邮件发送软件");
startActivity(intent);
intent.setAction(android.provider.Settings.ACTION_SETTINGS);
Intent  利用 Action  属性中的 ACTION_GET_CONTENT  获取返回值:
//选择图片 requestCode 返回的标识
Intent intent = new Intent();
intent.setAction(Intent. ACTION_GET_CONTENT );
intent.setType( "image/*" );
Intent wrapperIntent = Intent.createChooser(intent, null);
startActivityForResult(wrapperIntent, requestCode);
//添加音频
Intent intent = new Intent();
intent.setAction(Intent. ACTION_GET_CONTENT );
intent.setType( "video/*" );
Intent wrapperIntent = Intent.createChooser(intent, null);
startActivityForResult(wrapperIntent, requestCode);
//视频
Intent intent = new Intent();
intent.setAction(Intent. ACTION_GET_CONTENT );
intent.setType( "video/*" );
Intent wrapperIntent = Intent.createChooser(intent, null);
startActivityForResult(wrapperIntent, requestCode);
//录音
Intent intent = new Intent();
intent.setAction(Intent. ACTION_GET_CONTENT );
intent.setType( "audio/amr" );
intent.setClassName("com.android.soundrecorder","com.android.soundrecorder.SoundR
ecorder");
startActivityForResult(intent, requestCode);
1.2.7 Flags
Intent 可调用 addFlags()方法来为 Intent 添加控制标记。【重要】
1、FLAG_ACTIVITY_CLEAR_TOP:(效果同 Activity LaunchMode 的 singleTask)
如果在栈中已经有该 Activity 的实例,就重用该实例。重用时,会让该实例回到栈
顶,因此在它上面的实例将会被移除栈。如果栈中不存在该实例,将会创建新的实例放入栈
中。
2、FLAG_ACTIVITY_SINGLE_TOP:(效果同 Activity LaunchMode 的 singleTop)
如果在任务的栈顶正好存在该 Activity 的实例, 就重用该实例,而不会创建新的
Activity 对象。
3、FLAG_ACTIVITY_NEW_TASK:(效果如果 Activity LaunchMode 的 standard)默认
【备注】 】 : 以下几个为了解。
4、FLAG_ACTIVITY_MULTIPLE_TASK:
5、FLAG_ACTIVITY_BROUGHT_TO_FRONT:
6、FLAG_ACTIVITY_RESET_TASK_IF_NEEDED:
示例代码
Intent intent = new Intent(this, MainActivity.class);
//将 Activity 栈中处于 MainActivity 主页面之上的 Activity 都弹出。
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
1.2.8  补充 【 重点,需要认真理解 】
如果依次启动了四个 Activity:A、B、C、D。
在 D Activity 里,跳到 B Activity,同时希望 D 和 C 都 finish 掉,可以在 startActivity(intent)
里的 intent 里添加 flags 标记,如下所示:
Intent intent = new Intent(this, B.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
这样启动 B Activity 的同时,就会把 D、C 都 finished 掉。
如果 B Activity 的 launchMode 是默认的“standard”,则 B Activity 会首先 finished 掉旧的 B
页面,再启动一个新的 Activity B。 如果不想重新再创建一个新的 B Activity,而是重用之
前的 B Activity,可以将 B Activity 的 launchMode 设置为“singleTask”。【特别需要注意的是:
在部分手机中,如三星手机。即便是 singleTask 也会产生新的页面,而不是重用之前的页面。】
二、 Activity  四种启动模式
2.1.  设置方式
2.2.  standard( 系统默认的启动模式)
标准启动模式,每次激活 Activity 时都会创建 Activity,并放入任务栈中。
如果启动此 Activity 的 Intent 中没有设置 FLAG_ACTIVITY_NEW_TASK 标志, 则这个 Activity
与启动他的 Activity 在同一个 Task 中,如果设置了 Activity 请参考上面
FLAG_ACTIVITY_NEW_TASK 的详细说明,"launchMode"设置为"standard"的 Activity 可以被实例
化多次, 可以在 Task 中的任何位置, 对于一个新的 Intent 请求就会实例化一次.
2.3.  singleTop
如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,而不会创建新的Activity
对象,不过它会调用 onNewIntent()方法。如果栈顶部不存在就会创建新的实例并放入栈顶(即
使栈中已经存在该 Activity 实例,只要不在栈顶,都会创建实例)。
如果启动此 Activity 的 Intent 中没有设置 FLAG_ACTIVITY_NEW_TASK 标志, 则这个 Activity
与启动他的 Activity 在同一个 Task 中,如果设置了 Activity 请参考上面
FLAG_ACTIVITY_NEW_TASK的详细说明,"launchMode"设置为"singleTop"的Activity可以被实例
化多次, 可以在 Task 中的任何位置, 对于一个新的 Intent 请求如果在 Task 栈顶, 则会用栈
顶的 Activity 响影 Intent 请求,而不会重新实例化对象接收请求, 如果没有在栈顶, 则会实例
化一个新的对象接收 Intent 请求.
2.4.  singleTask
如果在栈中已经有该 Activity 的实例,就重用该实例(会调用实例的 onNewIntent())。重
用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。如果栈中不存在该实例,
将会创建新的实例放入栈中。
和 singleTop 在名字上即可看出区别,即 singleTop 每次只检测当前栈顶的 Activity 是否
是我们需要请求创建的,而 singleTask 则会检测栈中全部的 Activity 对象,从上向下,如果
检测到是我们所请求的则会消灭此 Activity 对象上面的对象,直接把检测到的我们需要的
Activity 置为栈顶。
"launchMode"设置为"singleTask"的 Activity 总是在栈底, 只能被实例化一次, 它允许其它
Activity 压入"singleTask"的 Activity 所在的 Task 栈,如果有新的 Intent 请求有此标志的 Activity,
则系统会清除有此标志的 Task 栈中的全部 Activity,并把此 Activity 显示出来.
2.5.  singleInstance
在一个新栈中创建该 Activity 实例,并让多个应用共享该 Activity 实例。一旦这种模式
的 Activity 实例存在于某个栈中,任何应用再激活这个 Activity 时都会重用该栈中的实例,
其效果相当于多个应用程序共享一个应用,不管谁激活该 Activity 都会进入同一个应用中。
此启动模式和我们使用的浏览器工作原理类似,在多个程序中访问浏览器时,如果当前浏览
器没有打开,则打开浏览器,否则会在当前打开的浏览器中访问。此模式会节省大量的系统
资源,因为他能保证要请求的 Activity 对象在当前的栈中只存在一个。
"launchMode"设置为"singleInstance"的 Activity 总是在栈底, 只能被实例化一次, 不允
许其它的 Activity 压入"singleInstance"的 Activity 所在 Task 栈, 即整个 Task 栈中只能有这么
一个 Activity.

你可能感兴趣的:(android)