今天全国大范围有雨,我也连续扯了三天,今天屯干货。
- Intent是个好东西,我申请专利的软件产品,当时为了加速申请,写的代码很潦草。忘记了解决Activity声明周期,还好鄙人逻辑思维不差,要不然跳来跳去,非疯掉不可。这个图片大家随意看看就好,不用记,踩过一次坑,保证你终身难忘。编程有啥可背东西吗?你疯狂的踩坑,疯狂的积累,倒逼自己长脑子,长见识,岂不是人生乐事(我疯了,哈哈,别理我)
- 上面提到Activity直接的切换可以调用startActivity实现,而且这货可以带数据过去,带数据的时候,要调用startActivityForResult(),这方法你直接翻译就好了,不扯多了,这里分开说,只讲Intent。
- 四大组件我都知道,Service是唯一一个不使用用户界面,在后台吃流量的鬼。你要开启一个服务,跟上面一样,不过方法是startService(),Intent是要提供启动服务的描述,就像你在Activity之间做跳转(显式Intent)的时候,总得提供两个Activity吧。注意啊,不管你调用了多少次startService(),一次stopService(Intent)就足够了,不要手欠。
boolean bindService (Intent service,
ServiceConnection conn,
int flags)
看好这个代码,bindService()是布尔型的,还有里面的三个参数都是啥,绑定服务的时候,请参照:当应用组件通过调用 bindService() 绑定到服务时,服务即处于“绑定”状态。绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至是利用进程间通信 (IPC) 跨进程执行这些操作。 仅当与另一个应用组件绑定时,绑定服务才会运行。 多个组件可以同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。
- 广播是我玩的最少的组件,但我还是做过一个Demo,是一个静态广播和Toast组合实现的开机启动问候,不过有的手机并不能实现,毕竟用户未必喜欢的,就是各大手机厂商所抵触的。广播是任何应用均可接收的消息。系统将针对系统事件(例如:系统启动或设备开始充电时)传递各种广播。通过将 Intent 传递给 sendBroadcast()、sendOrderedBroadcast() 或 sendStickyBroadcast(),您可以将广播传递给其他应用。
void sendStickyOrderedBroadcast (Intent intent,
BroadcastReceiver resultReceiver,
Handler scheduler,
int initialCode,
String initialData,
Bundle initialExtras)
这个方法很有意思,粘性有序广播,API21 的时候因为安全性的问题被打入冷宫,我一开始不知道,放在这儿碍碍眼。
早听说Intent有两种类型,显式和隐式。
- 显式 Intent:按名称(完全限定类名)指定要启动的组件。 通常,您会在自己的应用中使用显式 Intent 来启动组件,这是因为您知道要启动的 Activity 或服务的类名。例如,启动新 Activity 以响应用户操作,或者启动服务以在后台下载文件。
- 隐式 Intent :不会指定特定的组件,而是声明要执行的常规操作,从而允许其他应用中的组件来处理它。 例如,如需在地图上向用户显示位置,则可以使用隐式 Intent,请求另一具有此功能的应用在地图上显示指定的位置。
- 显式Intent不难理解,来说说隐式把,假如你手机上下载过几款不一样的美颜相机(B612),或者几个不同浏览器时,如果你从一款应用调用了相机,就会有弹窗,询问你选择原生相机,还是其他。或者你写的程序用到了WebView的话,就会有个对话框问你选择自带浏览器还是其他。这就是隐式Intent的表现形式。人家官文是这么说的,感受下:创建隐式 Intent 时,Android 系统通过将 Intent 的内容与在设备上其他应用的清单文件中声明的 Intent 过滤器进行比较,从而找到要启动的相应组件。 如果 Intent 与 Intent 过滤器匹配,则系统将启动该组件,并向其传递 Intent 对象。 如果多个 Intent 过滤器兼容,则系统会显示一个对话框,支持用户选取要使用的应用。也是为了确保安全性问题,API21以后,隐式调用bindService(),程序报错。
- 当你想指定要启动的组件,请切记写上要启动的组件名称。启动 Service 时,您应始终指定组件名称。 否则,您无法确定哪项服务会响应 Intent,且用户无法看到哪项服务已启动。
- Intent 的这一字段是一个 ComponentName 对象,您可以使用目标组件的完全限定类名指定此对象,其中包括应用的软件包名称。 例如, com.example.ExampleActivity。您可以使用 setComponent()、setClass()、setClassName() 或 Intent 构造函数设置组件名称。
- 可以使用各种 putExtra() 方法添加 extra 数据,每种方法均接受两个参数:键名和值。您还可以创建一个包含所有 extra 数据的 Bundle 对象,然后使用 putExtras() 将Bundle 插入 Intent 中。
- 显式Intent官方示例:
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);
- 用户可能没有任何应用处理您发送到 startActivity() 的隐式 Intent。如果出现这种情况,则调用将会失败,且应用会崩溃。要验证 Activity 是否会接收 Intent,请对 Intent 对象调用 resolveActivity()。如果结果为非空,则至少有一个应用能够处理该 Intent,且可以安全调用 startActivity()。 如果结果为空,则不应使用该 Intent。如有可能,您应停用发出该 Intent 的功能。、
// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");
// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(sendIntent);
}
调用 startActivity() 时,系统将检查已安装的所有应用,确定哪些应用能够处理这种 Intent(即:含 ACTION_SEND 操作并携带“text/plain”数据的 Intent )。 如果只有一个应用能够处理,则该应用将立即打开并为其提供 Intent。 如果多个 Activity 接受 Intent,则系统将显示一个对话框,使用户能够选取要使用的应用。
- 如果有多个应用响应隐式 Intent,则用户可以选择要使用的应用,并将其设置为该操作的默认选项。 如果用户可能希望今后一直使用相同的应用执行某项操作(例如,打开网页时,用户往往倾向于仅使用一种网络浏览器),则这一点十分有用。
但是,如果多个应用可以响应 Intent,且用户可能希望每次使用不同的应用,则应采用显式方式显示选择器对话框。 选择器对话框每次都会要求用户选择用于操作的应用(用户无法为该操作选择默认应用)。 例如,当应用使用 ACTION_SEND 操作执行“共享”时,用户根据目前的状况可能需要使用另一不同的应用,因此应当始终使用选择器对话框,如图 2 中所示。
要显示选择器,请使用 createChooser() 创建 Intent,并将其传递给 startActivity()。例如:
Intent sendIntent = new Intent(Intent.ACTION_SEND);
...
// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show the chooser dialog
Intent chooser = Intent.createChooser(sendIntent, title);
// Verify the original intent will resolve to at least one activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
}
这将显示一个对话框,其中有响应传递给 createChooser() 方法的 Intent 的应用列表,并且将提供的文本用作对话框标题。
- 要公布应用可以接收哪些隐式 Intent,请在清单文件中使用
<intent-filter>
元素为每个应用组件声明一个或多个 Intent 过滤器。每个 Intent 过滤器均根据 Intent 的操作、数据和类别指定自身接受的 Intent 类型。 仅当隐式 Intent 可以通过 Intent 过滤器之一传递时,系统才会将该 Intent 传递给应用组件。
-为了接收隐式 Intent,必须将 CATEGORY_DEFAULT 类别包括在 Intent 过滤器中。 方法 startActivity() 和 startActivityForResult() 将按照已申明 CATEGORY_DEFAULT 类别的方式处理所有 Intent。 如果未在 Intent 过滤器中声明此类别,则隐式 Intent 不会解析为您的 Activity。例如,以下是一个使用包含 Intent 过滤器的 Activity 声明,当数据类型为文本时,系统将接收 ACTION_SEND Intent :
<activity android:name="ShareActivity">
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
- 为了更好地了解一些 Intent 过滤器的行为,我们一起来看看从社交共享应用的清单文件中截取的以下片段。
<activity android:name="MainActivity">
<!-- This activity is the main entry, should appear in app launcher -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="ShareActivity">
<!-- This activity handles "SEND" actions with text data -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<action android:name="android.intent.action.SEND_MULTIPLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/vnd.google.panorama360+jpg"/>
<data android:mimeType="image/*"/>
<data android:mimeType="video/*"/>
</intent-filter>
</activity>
- PendingIntent 对象是 Intent 对象的包装器。PendingIntent 的主要目的是授权外部应用使用包含的 Intent,就像是它从您应用本身的进程中执行的一样。