BroadCast 是android提供的跨进程通讯的有一利器。

1.异步执行onReceiver

    @Nullable
public abstract Intent registerReceiver(BroadcastReceiver receiver,
IntentFilter filter, @Nullable String broadcastPermission,
@Nullable Handler scheduler);

这是context里面注册广播的API,duplex2个我们不常用的东东。

我们分别来讨论这2个东西。

先讨论异步handler。

如果我们传入一个handler,会怎样?我们所有的onReceiver是运行在主线程吗?

package com.joyfulmath.samples.broadcastsample;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message; import com.joyfulmath.servicesample.R;
import com.joyfulmath.servicesample.TraceLog; import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EActivity; /**
* Created by Administrator on 2016/10/23 0023.
*/
@EActivity(R.layout.activity_main)
public class BcSampleActivity extends Activity { HandlerThread mThread = null;
Handler nHandler = null;
BroadCastAAA aReceiver = new BroadCastAAA(); @Override
protected void onResume() {
super.onResume();
TraceLog.i(); } @Override
protected void onPause() {
super.onPause();
TraceLog.i();
unregisterReceiver(aReceiver);
} @Override
protected void onDestroy() {
super.onDestroy();
aReceiver = null;
} @AfterViews
void initViews() {
TraceLog.i();
mThread = new HandlerThread("samples") {
@Override
protected void onLooperPrepared() {
nHandler = new Handler(getLooper()) {
@Override
public void dispatchMessage(Message msg) {
TraceLog.i(msg.toString());
super.dispatchMessage(msg);
} @Override
public void handleMessage(Message msg) {
TraceLog.i();
dispatchMsg(msg);
}
};
IntentFilter filter = new IntentFilter("com.joyfulmath.sample.broadcast.action");
registerReceiver(aReceiver, filter, null, nHandler);
}
};
mThread.start();
} @Click(R.id.btn_connect)
void onBtnClick() {
TraceLog.i();
// nHandler.sendEmptyMessage(0x01);
sendBroadcast(new Intent("com.joyfulmath.sample.broadcast.action"));
} void dispatchMsg(Message msg) {
switch (msg.what) {
case 0x1:
TraceLog.i();
break;
}
TraceLog.i();
} public class BroadCastAAA extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
TraceLog.i();
}
}
}

broadcastsample

通过上述代码,我们添加了一个运行在handlerThread里面的nHandler。

log如下:

10-22 22:32:21.332 16889-16889/com.joyfulmath.servicesample I/BcSampleActivity$override: onBtnClick:  [at (BcSampleActivity.java:79)]
10-22 22:32:21.347 16889-21599/com.joyfulmath.servicesample I/BcSampleActivity$1$1$override: dispatchMessage: { when=-2ms callback=android.app.LoadedApk$ReceiverDispatcher$Args target=com.joyfulmath.samples.broadcastsample.BcSampleActivity$1$1 } [at (BcSampleActivity.java:59)]
10-22 22:32:21.348 16889-21599/com.joyfulmath.servicesample I/BcSampleActivity$BroadCastAAA: onReceive: [at (BcSampleActivity.java:100)]

可以看到,onReceive没有运行在主线程,运行在哪里?就是nHandler的线程。

还有一个:callback=android.app.LoadedApk$ReceiverDispatcher$Args 这个是什么,看名字可以猜测,这个就是分发Receiver的东西。

可以看这个registerReceiver的注释:

Handler identifying the thread that will receive
* the Intent. If null, the main thread of the process will be used.

所以onReceiver 是可以运行在子线程的。这里有个问题:public class BroadCastAAA extends BroadcastReceiver

是内部类,如果运行在子线程,会不会导致内存泄露?

这些问题后续在分析.

2.Permission

权限管理分2块:

public abstract void sendBroadcast(Intent intent,
@Nullable String receiverPermission);

这里有个permission

还有就是上一节提到的permission。

第一种:

        sendBroadcast(new Intent("com.joyfulmath.sample.broadcast.action"), Contants.BROADCAST_ACTION);
Permission Denial: receiving Intent { act=com.joyfulmath.sample.broadcast.action flg=0x10 } to ProcessRecord{39c0edf1 2286:com.joyfulmath.servicesample/u0a62} (pid=2286, uid=10062) requires com.joyfulmath.samples.broadcast.action due to sender com.joyfulmath.servicesample (uid 10062)

可以看到报permission denial。就是没有权限。报的错误是基于进程的。

permission定义在发送app,接受app需要userpermission。

当然解决这个错误就是在manifest里面use这条permission。

第二种:

registerReceiver(aReceiver, filter, "com.joyfulmath.samples.broadcast.permission", nHandler);

静态注册也一样。

这条语句的意思是:只有含有permisson的progress发送的广播才能被收到。

permission定义在receiver中,发送app需要userpermission才能收到。

3.Local Broadcast:App应用内广播(此处的App应用以App应用进程为界)

相比于全局广播,App应用内广播优势体现在:

1.安全性更高;

2.更加高效。

为此,Android v4兼容包中给出了封装好的LocalBroadcastManager类,用于统一处理App应用内的广播问题,使用方式上与通常的全局广播几乎相同,只是注册/取消注册广播接收器和发送广播时将主调context变成了LocalBroadcastManager的单一实例。

4.不同注册方式的广播接收器回调onReceive(context, intent)中的context具体类型

1).对于静态注册的ContextReceiver,回调onReceive(context, intent)中的context具体指的是ReceiverRestrictedContext;

2).对于全局广播的动态注册的ContextReceiver,回调onReceive(context, intent)中的context具体指的是Activity Context;

3).对于通过LocalBroadcastManager动态注册的ContextReceiver,回调onReceive(context, intent)中的context具体指的是Application Context。

注:对于LocalBroadcastManager方式发送的应用内广播,只能通过LocalBroadcastManager动态注册的ContextReceiver才有可能接收到(静态注册或其他方式动态注册的ContextReceiver是接收不到的)。

5.不同Android API版本中广播机制相关API重要变迁

1).Android5.0/API level 21开始粘滞广播和有序粘滞广播过期,以后不再建议使用;

2).”静态注册的广播接收器即使app已经退出,主要有相应的广播发出,依然可以接收到,但此种描述自Android 3.1开始有可能不再成立“

Android 3.1开始系统在Intent与广播相关的flag增加了参数,分别是FLAG_INCLUDE_STOPPED_PACKAGES和FLAG_EXCLUDE_STOPPED_PACKAGES。

FLAG_INCLUDE_STOPPED_PACKAGES:包含已经停止的包(停止:即包所在的进程已经退出)

FLAG_EXCLUDE_STOPPED_PACKAGES:不包含已经停止的包

主要原因如下:

自Android3.1开始,系统本身则增加了对所有app当前是否处于运行状态的跟踪。在发送广播时,不管是什么广播类型,系统默认直接增加了值为FLAG_EXCLUDE_STOPPED_PACKAGES的flag,导致即使是静态注册的广播接收器,对于其所在进程已经退出的app,同样无法接收到广播。

详情参加Android官方文档:http://developer.android.com/about/versions/android-3.1.html#launchcontrols

由此,对于系统广播,由于是系统内部直接发出,无法更改此intent flag值,因此,3.1开始对于静态注册的接收系统广播的BroadcastReceiver,如果App进程已经退出,将不能接收到广播。

但是对于自定义的广播,可以通过复写此flag为FLAG_INCLUDE_STOPPED_PACKAGES,使得静态注册的BroadcastReceiver,即使所在App进程已经退出,也能能接收到广播,并会启动应用进程,但此时的BroadcastReceiver是重新新建的。

1 Intent intent = new Intent();
2 intent.setAction(BROADCAST_ACTION);
3 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
4 intent.putExtra("name", "qqyumidi");
5 sendBroadcast(intent);

注1:对于动态注册类型的BroadcastReceiver,由于此注册和取消注册实在其他组件(如Activity)中进行,因此,不受此改变影响。

注2:在3.1以前,相信不少app可能通过静态注册方式监听各种系统广播,以此进行一些业务上的处理(如即时app已经退出,仍然能接收到,可以启动service等..),3.1后,静态注册接受广播方式的改变,将直接导致此类方案不再可行。于是,通过将Service与App本身设置成不同的进程已经成为实现此类需求的可行替代方案。

 

Android 四大组件之再论BroadCast的更多相关文章

  1. Android 四大组件之service与Broadcast

    Android 四大组件之一:service: Service有五个生命周期:onCreat,onStartCommand, onBind,onUnbind, onDestroy 主要有绑定和非绑定两 ...

  2. Android 四大组件之再论service

    service常见的有2种方式,本地service以及remote service. 这2种的生命周期,同activity的通信方式等,都不相同. 关于这2种service如何使用,这里不做介绍,只是 ...

  3. android四大组件之Broadcast

    广播的概念 现实中:我们常常使用电台通过发送广播发布消息,买个收音机,就能收听 Android:系统在产生某个事件时发送广播,应用程序使用广播接收者接收这个广播,就知道系统产生了什么事件.Androi ...

  4. 【Android开发日记】之入门篇(六)——Android四大组件之Broadcast Receiver

    广播接受者是作为系统的监听者存在着的,它可以监听系统或系统中其他应用发生的事件来做出响应.如设备开机时,应用要检查数据的变化状况,此时就可以通过广播来把消息通知给用户.又如网络状态改变时,电量变化时都 ...

  5. [Android基础]Android四大组件之BroadCast

    BroadCast的定义: 广播是一种订阅--通知 事件,广播接收者向Android系统 register (订阅广播),广播发送者向Adnroid系统 sendBroadCast(发送广播),然后A ...

  6. Android四大组件之一“广播”

    前言 Android四大组件重要性已经不言而喻了,今天谈谈的是Android中的广播机制.在我们上学的时候,每个班级的教室里都会装有一个喇叭,这些喇叭都是接入到学校的广播室的,一旦有什么重要的通知,就 ...

  7. android四大组件学习总结以及各个组件示例(1)

    android四大组件分别为activity.service.content provider.broadcast receiver. 一.android四大组件详解 1.activity (1)一个 ...

  8. Android 四大组件之“ BroadcastReceiver ”

    前言 Android四大组件重要性已经不言而喻了,今天谈谈的是Android中的广播机制.在我们上学的时候,每个班级的教室里都会装有一个喇叭,这些喇叭都是接入到学校的广播室的,一旦有什么重要的通知,就 ...

  9. android四大组件--ContentProvider具体解释

    一.相关ContentProvider概念解析: 1.ContentProvider简单介绍 在Android官方指出的Android的数据存储方式总共同拥有五种,各自是:Shared Prefere ...

随机推荐

  1. angular开发者吐槽react+redux的复杂:“一个demo证明你的开发效率低下”

    曾经看到一篇文章,写的是jquery开发者吐槽angular的复杂.作为一个angular开发者,我来吐槽一下react+redux的复杂. 例子 为了让大家看得舒服,我用最简单的一个demo来展示r ...

  2. Oracle常用函数

    前一段时间学习Oracle 时做的学习笔记,整理了一下,下面是分享的Oracle常用函数的部分笔记,以后还会分享其他部分的笔记,请大家批评指正. 1.Oracle 数据库中的to_date()函数的使 ...

  3. 排名前 8 的 PHP 调试工具

    Web 开发并不是一项轻松的任务,有超级多服务端脚本语言提供给开发者,但是当前 PHP 因为具有额外的一些强大的功能而越来越流行.PHP 是最强大的服务端脚本语言之一,同时也是 web 开发者和设计者 ...

  4. 如何做优化,UITabelView才能更加顺滑 (转载)

    这篇文章是前两周@叶孤城叶大在微信群里面的分享,一直到这两天才翻出来研究.很多实用的东西,不过由于水平有限,有些地方没能翻译好,还请大家指正. 我已经在iOS这个最好的移动平台上有几年的开发经验了.在 ...

  5. opendaylight的Beryllium安装

    1.首先安装jdk  #sudo apt-get install openjdk-7-jdk 2.安装vim编辑工具   #sudo apt-get install vim 3.编辑~/.bashrc ...

  6. jQuery-1.9.1源码分析系列(五) 回调对象

    jQuery.Callbacks()提供的回调函数队列管理本来是延时回调处理的一部分,但是后面将其独立出来作为一个模块.jQuery就是这样,各个模块间的代码耦合度是处理的比较好的,值得学习.虽然是从 ...

  7. 原来css中的border还可以这样玩

    原来css中的border还可以这样玩 前面的话: 在看这篇文章之前你可能会觉得border只是简单的绘制边框,看了这篇文章,我相信你也会跟我一样说一句"我靠,原来css中的border还可 ...

  8. Python_Day_02 str内部方法总结

    刚开始学习Python,看了一天的字符串内部方法,现在来总结一下. capitalize(self) 将一句话的首字母变大写,其他字母都变小 name = "love PyThon" ...

  9. Nancy之Cache的简单使用

    一.前言 说起缓存,或许大家都不陌生,甚至是天天都在用!当然缓存也被分的越来越细,页面缓存.数据缓存.文件缓存等等. 其实呢,我个人觉得,主要还是两大类:数据的缓存和页面的缓存.数据缓存的话就包括所有 ...

  10. 【转】asp.net(c#)加密解密算法之sha1、md5、des、aes实现源码详解

    原文地址:http://docode.top/Article/Detail/10003 目录: 1..Net(C#)平台下Des加密解密源代码 2..Net(C#)平台下Aes加密解密源代码 3..N ...