在 Android - Intent与IntentFilter 一文的开头,我们提到,一个Intent是对将要被执行的一个操作的一种抽象的描述,结合Context类中定义的下列几个方法 ——
- public abstract void startActivity(Intent intent);
- public abstract void sendBroadcast(Intent intent);
- public abstract ComponentName startService(Intent service);
- public abstract boolean bindService(Intent service, ServiceConnection conn, int flags);
Intent被用作一种组件之间进行通信的媒介。
public abstract void startActivity(Intent intent)方法是根据指定的intent开启对应的Activity,
public abstract ComponentName startService(Intent service)方法是根据指定的intent开启对应的Service,
那么,
public abstract void sendBroadcast(Intent intent)方法呢?
一般来说,Intent主要是用作Activity和Service之间通信的媒介,在Activity(Service)中通过Intent开启一个Service(Activity)。
那么,如果我们需要在应用中根据一个Intent来做某些具体的操作(不一定是开启一个Activity或Service)呢?在Context类中可没有什么方法能满足我们的需要,这种情况下,就可以考虑使用广播接收者了。上文中提到的public abstract void sendBroadcast(Intent intent)方法就是用于发送intent的,广播接收者则用于处理intent。
正如startActivity(Intent intent)和startService(Intent service)这两个方法都需要它们所传递的intent先通过IntentFilter的过滤才能开启对应的Activity和Service一样,广播接收者并不会处理所有通过sendBroadcast(Intent intent)方法发送来的intent,它同样需要先声明自己能处理哪些intent。
本文也按照 创建广播接收者--订阅感兴趣的广播intent--发送广播intent--处理广播intent 的顺序来写。
一、创建广播接收者
创建一个广播接收者只需要继承BroadcastReceiver,并重写onReceive()方法,如:
- public class myBroadcastReceiver extends BroadcastReceiver{
- @Override
- public void onReceive(Context context, Intent intent) {
-
- ... ...
- }
- }
二、订阅感兴趣的广播Intent
订阅的方法有两种:
第一种:使用代码进行订阅(动态订阅):
- public void registerStorageChangeReceiver() {
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_MEDIA_SHARED);
- filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
- filter.addAction(UPDATE_LISTVIEW_STRING);
- filter.addDataScheme("file");
- storageChangeReceiver = new StorageChangeReceiver();
- getActivity().registerReceiver(storageChangeReceiver, filter);
- }
第二种:在AndroidManifest.xml文件中的<application>节点里进行订阅(
静态订阅):
- <receiver android:name=".autotask.AutoTaskReceiver">
- <intent-filter>
- <action android:name="android.intent.action.BOOT_COMPLETED" />
- </intent-filter>
- <intent-filter>
- <action android:name="android.intent.action.DATE_CHANGED" />
- </intent-filter>
- </receiver>
两种订阅方式的区别:
静态订阅广播又叫常驻型广播,当应用程序关闭了,如果有广播intent到来,广播接收者同样能接收到。
动态订阅广播又叫非常驻型广播,当应用程序结束了,广播接收者也就被销毁了。
三、发送广播
发送广播的方法定义在Context类中,主要有:
- public abstract void sendBroadcast(Intent intent);
- public abstract void sendBroadcast(Intent intent, String receiverPermission);
-
- public abstract void sendOrderedBroadcast(Intent intent, String receiverPermission);
- public abstract void sendOrderedBroadcast(Intent intent, String receiverPermission, BroadcastReceiver resultReceiver,
- Handler scheduler, int initialCode, String initialData, Bundle initialExtras);
sendBroadcast()用来发送“普通广播(Normal broadcasts)”
sendOrderedBroadcast()用来发送“有序广播(Ordered broadcasts)”。
普通广播(Normal broadcasts)是完全异步的,可以在同一时刻(逻辑上)被所有接收者接收到,消息传递的效率比较高,但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播。
有序广播(Ordered broadcasts)则按照接收者声明的优先级别被依次接收。如:A的级别高于B的级别高于C的级别,那么,广播先传给A,再传给B,最后传给C 。 优先级别声明在 intent-filter 元素的 android:priority 属性中,数值越大优先级别越高,取值范围:-1000到1000,优先级别也可以调用IntentFilter对象的setPriority()进行设置。
有序广播的接收者可以终止广播Intent的传播(BroadcastReceiver.abortBroadcast()),广播Intent的传播一旦终止,后面的接收者就无法接收到广播。
另外,有序广播的接收者可以通过setResultExtras(Bundle)方法将数据存放进结果对象,然后将数据传递给下一个接收者,下一个接收者通过代码:Bundle bundle = getResultExtras(true))可以获取上一个接收者存入在结果对象中的数据。如:A得到广播后,可以往它的结果对象中存入数据,当广播传给B时,B可以从A的结果对象中得到A存入的数据。
四、处理广播Intent
每次广播消息到来时都会创建BroadcastReceiver实例并执行onReceive() 方法,
onReceive() 方法执行完后,BroadcastReceiver 的实例就会被销毁。
当onReceive() 方法在10秒内没有执行完毕,Android会认为该程序无响应。所以在BroadcastReceiver里不能做一些比较耗时的操作,否侧会弹出ANR(Application No Response)对话框。
如果需要完成一项比较耗时的工作,应该通过发送Intent给Service,由Service来完成。这里不能使用子线程来解决,因为 BroadcastReceiver 的生命周期很短,子线程可能还没有结束BroadcastReceiver就先结束了。
BroadcastReceiver一旦结束,此时BroadcastReceiver所在的进程很容易在系统需要内存时被优先杀死,因为它属于空进程(没有任何活动组件的进程)。如果它的宿主进程被杀死,那么正在工作的子线程也会被杀死。所以采用子线程来解决是不可靠的。
Android将进程分为6个等级,它们按优先级顺序由高到低依次是:
1.前台进程( FOREGROUND_APP)
2.可视进程(VISIBLE_APP )
3. 次要服务进程(SECONDARY_SERVER )
4.后台进程 (HIDDEN_APP)
5.内容供应节点(CONTENT_PROVIDER)
6.空进程(EMPTY_APP)
所以,Intent是组件(主要是Activity和Service)之间进行通信的媒介。广播接收者通过订阅并处理Intent则是组件(主要是Activity和Service)间进行通信的一种方式。
... ... (未完待续)