Android本地广播和全局广播的区别及实现原理

迷茫时该如何选择?

1.本地广播和全局广播

1.1本地广播:

         广播事件的发送和接收都在本应用,不影响其他应用也不受其他应用影响,只能被动态注册,不能静态注册,主要用法都在LocalBroadcastManager类中。

1.2全局广播:

         可以接收其他应用发的广播,也可以发送广播让其他应用接收,全局广播既可以动态注册,也可以静态注册,接受其他应用和系统广播是全局广播的一个重要应用点。总体来说两者应用场景不同。

全局广播发送和接收限制设置:

(1)不让别的应用收到自己发送的广播

在Androidmanifest.xml中为BroadcastReceiver添加权限,如果是自定义权限记得先声明:

<permission android:name = "com.android.permission.quanxian"/>

发送广播是传入:

public void sendOrderedBroadcast(Intent intent, String receiverPermission)

sendBroadcast(intent, "com.android.permission.quanxian ");

只有具有permission权限的Receiver才能接收此广播要接收该广播,在Receiver应用的AndroidManifest.xml中要添加对应的相应的权限。 

(2)过滤掉自己不愿接收的广播。

android:exported  此broadcastReceiver能否接收其他App的发出的广播,这个属性默认值有点意思,其默认值是由receiver中有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false。

android:permission设置之后,只有具有相应权限的广播发送方发送的广播才能被此broadcastReceiver所接收;

        上述设置也可以达到接收或者不接收的目的,但是全局广播其实原理是利用binder机制和AMS进行交互如果只是应用内使用,资源耗费或者说延时还是可以优化的。

2 本地广播使用

public class Demo3 extends AppCompatActivity {
    private MyBroadcastReceiver mBroadcastReceiver;
    private TextView mTv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTv = findViewById(R.id.clicke);
        initEvent();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.ldx.demo");
        LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, intentFilter);
    }

    private void initEvent() {
        mTv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setAction("com.ldx.demo");
                LocalBroadcastManager.getInstance(Demo3.this).sendBroadcast(intent);
            }
        });
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
    }

    class MyBroadcastReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {

        }
    }
}

3 本地广播的实现原理

单例LocalBroadcastManager

全部逻辑都在LocalBroadcastManager中,LocalBroadcastManager提供了单例获取的getInstance:

@NonNull
public static LocalBroadcastManager getInstance(@NonNull Context context) {
    synchronized (mLock) {
        if (mInstance == null) {
            mInstance = new LocalBroadcastManager(context.getApplicationContext());
        }
        return mInstance;
    }
}

同时初始化了一个Handler:

private LocalBroadcastManager(Context context) {
    mAppContext = context;

       //利用主线程looper构造handler
    mHandler = new Handler(context.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_EXEC_PENDING_BROADCASTS:

                    //执行发送任务
                    executePendingBroadcasts();
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    };
}

所以猜测是利用Handler向Receiver发送信息。

两个静态final内部类:

static final class ReceiverRecord

static final class BroadcastRecord 

ReceiverRecord

ReceiverRecord:用来标识注册的单个广播,包括intentFilter和receiver,每次注册就会生成一个ReceiverRecord。

private static final class ReceiverRecord {

     //记录intentFilter,意图过滤
    final IntentFilter filter;

     //记录广播接收者
    final BroadcastReceiver receiver;
    boolean broadcasting;
    boolean dead;

    ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver) {
        filter = _filter;
        receiver = _receiver;
    }
}

BroadcastRecord

BroadcastRecord记录一个意图对应的多个接收者,发送回复信息给Receiver时可以通过这个结构查找接收者。

private static final class BroadcastRecord {

//记录当前意图   
 final Intent intent;
//符合意图的ReceiverRecord

    final ArrayList<ReceiverRecord> receivers;

    BroadcastRecord(Intent _intent, ArrayList<ReceiverRecord> _receivers) {

        intent = _intent;

        receivers = _receivers;

    }

}

LocalBroadcastManager中变量

//当前所有注册广播

private final HashMap<BroadcastReceiver, ArrayList<ReceiverRecord>> mReceivers
        = new HashMap<>();

//有特定意图的广播
private final HashMap<String, ArrayList<ReceiverRecord>> mActions = new HashMap<>();
//待发送的广播
private final ArrayList<BroadcastRecord> mPendingBroadcasts = new ArrayList<>();

static final int MSG_EXEC_PENDING_BROADCASTS = 1;

private final Handler mHandler;

注册广播:

public void registerReceiver(@NonNull BroadcastReceiver receiver,

        @NonNull IntentFilter filter) {

    synchronized (mReceivers) {
       // 新的注册,生成ReceiverRecord

        ReceiverRecord entry = new ReceiverRecord(filter, receiver);

        ArrayList<ReceiverRecord> filters = mReceivers.get(receiver);
       //     最终添加到mReceivers中,一个广播接受者可能有多个意图过滤,场景类似对同一个BroadcastReceiver多次调用registerReceiver,每次意图过滤都不相同。

        if (filters == null) {

            filters = new ArrayList<>(1);

            mReceivers.put(receiver, filters);

        }

        filters.add(entry);
       //遍历意图过滤,获取action,每个action 对应多个ReceiverRecord,也就是一个Action对应多个接收者

        for (int i=0; i<filter.countActions(); i++) {

            String action = filter.getAction(i);

            ArrayList<ReceiverRecord> entries = mActions.get(action);

            if (entries == null) {

                entries = new ArrayList<ReceiverRecord>(1);

                mActions.put(action, entries);

            }

            entries.add(entry);

        }

    }

}

解除注册广播:

public void unregisterReceiver(@NonNull BroadcastReceiver receiver) {

    synchronized (mReceivers) {
       //从mReceivers中删除注册的广播,返回它的意图过滤列表

        final ArrayList<ReceiverRecord> filters = mReceivers.remove(receiver);

        if (filters == null) {

            return;

        }

       //遍历意图过滤列表
 for (int i=filters.size()-1; i>=0; i--) {
              //通过意图找到对应的ReceiverRecord

            final ReceiverRecord filter = filters.get(i);

            filter.dead = true;
              //找到所有对应的Action

            for (int j=0; j<filter.filter.countActions(); j++) {

                final String action = filter.filter.getAction(j);

               //从mActions中获取ReceiverRecord,因为一个Action对应多个ReceiverRecord,解注册之后需要删除对应的RR
 final ArrayList<ReceiverRecord> receivers = mActions.get(action);

                if (receivers != null) {

                    for (int k=receivers.size()-1; k>=0; k--) {

                        final ReceiverRecord rec = receivers.get(k);

                        if (rec.receiver == receiver) {

                            rec.dead = true;

                            receivers.remove(k);

                        }

                    }
                    //删除之后如果当前Action对应的RR没有了,就直接删除,应为不需要此Action对应RR了

                    if (receivers.size() <= 0) {

                        mActions.remove(action);

                    }

                }

            }

        }

    }

}

发送广播:

public boolean sendBroadcast(@NonNull Intent intent) {

    synchronized (mReceivers) {

       //首先获取Action及其他参数
 final String action = intent.getAction();

        final String type = intent.resolveTypeIfNeeded(

                mAppContext.getContentResolver());

        final Uri data = intent.getData();

        final String scheme = intent.getScheme();

        final Set<String> categories = intent.getCategories();



        final boolean debug = DEBUG ||

                ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
//获取Action对应的ReceiverRecord

        ArrayList<ReceiverRecord> entries = mActions.get(intent.getAction());

        if (entries != null) {

            if (debug) Log.v(TAG, "Action list: " + entries);



            ArrayList<ReceiverRecord> receivers = null;

            for (int i=0; i<entries.size(); i++) {

                ReceiverRecord receiver = entries.get(i);

                if (debug) Log.v(TAG, "Matching against filter " + receiver.filter);



                if (receiver.broadcasting) {

                    continue;

                }



                int match = receiver.filter.match(action, type, scheme, data,

                        categories, "LocalBroadcastManager");

                if (match >= 0) {

                    if (debug) Log.v(TAG, "  Filter matched!  match=0x" +

                            Integer.toHexString(match));

                    if (receivers == null) {

                        receivers = new ArrayList<ReceiverRecord>();

                    }
       //符合条件,修改状态为true,receivers为需要接受的列表

                    receivers.add(receiver);

                    receiver.broadcasting = true;

                } else {

                    if (debug) {

                        String reason;

                        switch (match) {

                            case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;

                            case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;

                            case IntentFilter.NO_MATCH_DATA: reason = "data"; break;

                            case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;

                            default: reason = "unknown reason"; break;

                        }

                        Log.v(TAG, "  Filter did not match: " + reason);

                    }

                }

            }



            if (receivers != null) {
              //修改状态

                for (int i=0; i<receivers.size(); i++) {

                    receivers.get(i).broadcasting = false;

                }
              //加入到发送列表中,等待发送

                mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));

                if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {

                    mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);

                }

                return true;

            }

        }

    }

    return false;

}

 

课程设计-基于C51单片机的音乐喷泉控制系统设计:摘 要随着人们生活水平的提高建立绿色城市的向往,音乐喷泉以其独特的魅力特殊的功能,愈来愈成为休闲娱乐产业中的一项重要产品,音乐喷泉的兴建也越来越多。根据目前音乐喷泉的发展现状,介绍了一个以AT89C51单片机为核心的小型音乐喷泉控制系统。给出了一个简洁的单片机控制电路,分析了输出地址,描述了不同类型的输出电路输入电路;介绍了从特定构造的喷池中获得决定喷池动作的喷池数据的原理;给出了主程序框图看门狗子程序。采用程序控制来控制花型。音频信号还影响灯光色彩灯光光线明暗的变化。从而使灯光色彩、灯光的闪烁喷泉水姿随音乐节奏而变化。关键词:音乐喷泉;单片机;单片机控制;喷池数据目录摘 要I目录II第1章 绪 论11.1课题背景11.2 音乐喷泉的发展现状1第2章 音乐喷泉控制系统硬件设计32.1 控制系统硬件总体设计方案32.2音乐信号的采集32.2.1 音频放大电路的设计32.2.2 采样定理52.3 单片机电路62.3.1 单片机的概述62.3.2 时钟电路的设计72.4 AD转换电路72.4.1 ADC0809与单片机89C51的连接82.4.2输入电路92.5潜水泵调速硬件方案设计102.6灯光硬件方案设计112.7解决系统时间滞后硬件电路设计11第3章 喷泉控制系统软件设计133.1喷池数据133.2主程序框图143.3 控制潜水泵软件设计模块143.3.1 潜水泵开关调速的原理153.3.2潜水泵开关调速的软件设计163.4控制电磁阀软件设计模块173.5 歌曲存储模块173.5.1音频脉冲的产生173.5.2音乐程序193.6灯光控制模块223.7看门狗子程序233.8实验仿真23结 论25参考文献26附 录27附录127附录228 第1章 绪 论1.1课题背景随着人们生活水平的提高,人们对环境的要求越来越高,城市环境建设日益为人们所重视。喷泉作为一种观赏性较高的艺术水景,不断的出现在城市的广场、公园及其它公共场所,早些的喷泉都是固定不可调的,显得有些单调,随着科技的发展音乐喷泉也进入了我们的城市。音乐喷泉是现代科技与艺术的综合,音乐喷泉将喷水图形、彩色灯光及音乐旋律构成一个有机的整体,随着乐曲旋律节奏的变化,各种不同的喷水花形相应的配合变换,在五彩绚丽的变幻灯光照耀下,构成一幅幅奇妙无比的景观、令人赏心悦目,叹为观止,在视听上获得极大的享受。音乐喷泉的起源于1930年,德国人首先带出喷泉的概念,此后经过多年的发展,其音乐喷泉的设计及构造已变得更大型及复杂。随着我国改革开放政策的不断实施,80年代中,我国也相继引进自行设计建造了多座音乐喷泉,为美化环境,活跃人民的文化生活起了良好的作用。通过学习引进国外先进技术,加上自行研究开发,喷泉的面貌不断更新,各种新水型层出不穷,音乐喷泉还可以同水幕电影、激光表演舞台表演相结合,产生令人难忘的艺术效果。我国现有上百家喷泉水景设备制造厂,经过市场竞争、优胜劣汰,我国已经出现了几家综合实力较强的大型喷泉水景工程公司,能够独立建设投资上千万元的特大型喷泉水景工程,并创造了一些世界之最的新记录。总体上说,我国的喷泉水景技术已经达到了国际先进水平,其建设规模市场需求更是其他国家所难以相比的。 1.2 音乐喷泉的发展现状 北京石景山古城公园的音乐喷泉,在悠扬动听的音乐声中,喷水可产生五六种变化,时而转动如银伞,时而飘忽如玉带,时而如金蛇狂舞,时而旋转飞溅···喷出的花形有昙花、菊花、扶桑花、百合花曼陀罗花,这是在80年代初期中国较早建设的一个音乐喷泉。南昌的秋水广场是由“落霞与孤鹜齐飞,秋水共长天一色”的意境得名,秋水广场就是以喷泉为主题,集旅游、观光、购物的大型休闲广场。他的音乐喷泉最吸引人注目,是国内最大的音乐喷泉群,泉水面积1.2万平方米,主喷高达128米,是南昌的一俏丽景观,人们可以一边欣赏音乐,一边观看滕王阁的美景。新加坡圣淘沙旅游区的音乐的设计与效果也是值得参考的,它布置在一个空旷而略有坡度的空间,面积很大,与圣淘沙车站前的长形喷水池共同组成为一个长达数百米的综合系列喷泉,音乐喷泉位于系列喷泉的顶端。舞台为一假山堆叠的西洋式半圆柱廊组成,共分3层。白天,假山瀑布及两侧的喷泉群与3层水池形成一处动静结合的较为文雅悠扬的水景园,入夜则有五光十色,优美动听的喷泉景观,整个舞台区域东西面阔近百米,南北深度约40m,成为目前亚洲最大的音乐喷泉之一。表现出壮阔、绚丽的水景之美。 以上几处音乐喷泉从
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lidongxiu0714

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值