zoukankan      html  css  js  c++  java
  • Android 四大组件之broadcast的理解

    Android广播的两种类型:

    1.静态广播

    2.动态广播

    静态注册广播:

    Manifeast中的代码块:

    <receiver
           android:name=".broadcast.MyStaticReceiver"
           android:enabled="true"
           android:exported="true">
           <intent-filter>
                <action android:name="husanity"/>
           </intent-filter>
    </receiver>
    MyStaticReceiver这个类里面很简单,只做了打印收到的信息:
    package com.hxc.supreme.broadcast;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.util.Log;
    import android.widget.Toast;
    
    import com.hxc.supreme.utils.ToastUtil;
    
    public class MyStaticReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i("MyStaticReceiver", "onReceive: "+intent.getStringExtra("info"));
        }
    }

    然后就是主界面一个点击按钮,布局文件很简单:

    package com.hxc.supreme.activity;
    
    import android.content.Intent;
    import android.os.Bundle;
    import android.support.annotation.Nullable;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    import com.hxc.supreme.R;
    
    
    /**
     * created by huxc  on 2017/9/28.
     * func:Android广播详解
     * email: hxc242313@qq.com
     */
    
    public class BroadcastActivity extends AppCompatActivity implements View.OnClickListener {
    
        private TextView tvStaticBroadcast;
        private TextView tvDynamicBroadcast;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_broadcast);
            tvStaticBroadcast = findViewById(R.id.tv_static_broadcast);
            tvDynamicBroadcast = findViewById(R.id.tv_dynamic_broadcast);
            tvStaticBroadcast.setOnClickListener(this);
            tvDynamicBroadcast.setOnClickListener(this);
        }
    
    
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.tv_static_broadcast:
                    sendBroadcast();
                    break;
                case R.id.tv_dynamic_broadcast:
                    break;
            }
        }
    
        private void sendBroadcast() {
            Intent intent = new Intent();
            intent.setAction("husanity");
            intent.putExtra("info", "这是一条静态广播");
            sendBroadcast(intent);
        }
    
    
    }
    View Code

    然后看一下logcat中的日志输出:

    02-15 15:33:14.300 15384-15384/com.hxc.supreme I/MyStaticReceiver: onReceive: 这是一条静态广播

    然而,在Android8.0及以上的系统中,收不到静态广播!Google了一下发现,谷歌在8.0后为了提高效率,删除了静态注册,防止关闭App后广播还在, 造成内存泄漏, 现在静态注册的广播需要指定包名!!!

    意思就是在8.0以后Google官方推荐用动态注册替换静态注册,那我们就指定一下包名看看是否管用:

    代码只改动了发送广播的方法:

     private void sendBroadcast() {
            Intent intent = new Intent();
            intent.setPackage(getPackageName());//Android8.0以上需指定包名
            intent.setAction("husanity");
            intent.putExtra("info", "这是一条静态广播");
            sendBroadcast(intent);
        }

    看下logcat的输出日志:

    02-15 15:46:21.891 11181-11181/com.hxc.supreme I/MyStaticReceiver: onReceive: 这是一条静态广播

    事实是证明可以的,但是Google推荐使用动态注册,那我么接下来就看一下动态注册的使用方式。

    动态注册广播:

    直接上代码:

    package com.hxc.supreme.activity;
    
    import android.content.BroadcastReceiver;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.os.Bundle;
    import android.support.annotation.Nullable;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    import com.hxc.supreme.R;
    
    
    /**
     * created by huxc  on 2017/9/28.
     * func:Android广播详解
     * email: hxc242313@qq.com
     */
    
    public class BroadcastActivity extends AppCompatActivity implements View.OnClickListener {
    
        private TextView tvStaticBroadcast;
        private TextView tvDynamicBroadcast;
        private DynamicReceiver dynamicReceiver;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_broadcast);
            tvStaticBroadcast = findViewById(R.id.tv_static_broadcast);
            tvDynamicBroadcast = findViewById(R.id.tv_dynamic_broadcast);
            tvStaticBroadcast.setOnClickListener(this);
            tvDynamicBroadcast.setOnClickListener(this);
            dynamicReceiver = new DynamicReceiver();
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction("husanity");
            registerReceiver(dynamicReceiver, intentFilter);
        }
    
    
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.tv_static_broadcast:
                    sendBroadcast();
                    break;
                case R.id.tv_dynamic_broadcast:
                    sendDynamicBroadcast();
                    break;
            }
        }
    
        private void sendBroadcast() {
            Intent intent = new Intent();
            intent.setPackage(getPackageName());//Android8.0以上需指定包名
            intent.setAction("husanity");
            intent.putExtra("info", "这是一条静态广播");
            sendBroadcast(intent);
        }
    
        private void sendDynamicBroadcast() {
            Intent intent = new Intent();
            intent.setAction("husanity");
            intent.putExtra("extra", "这是一条动态广播");
            sendBroadcast(intent);
    
        }
    
        class DynamicReceiver extends BroadcastReceiver {
    
            @Override
            public void onReceive(Context context, Intent intent) {
                Log.i("BroadcastActivity", "onReceive: " + intent.getStringExtra("extra"));
    
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            //onDestroy中需要反注册,用来优化内存空间避免内存泄漏
            unregisterReceiver(dynamicReceiver);
        }
    }
    View Code

    看下log cat打印日志:

    02-15 16:08:25.559 11597-11597/com.hxc.supreme I/BroadcastActivity: onReceive: 这是一条动态广播

    可以看到结果也是能够收到广播的,那么既然两种都可以,那静态注册和动态注册到底有什么区别呢?

    静态注册和动态注册的区别:

    通过一个拨打电话然后监听收到的打电话的广播来看看两者的区别:

    manifest修改:

    <receiver
        android:name=".broadcast.MyStaticReceiver"
        android:enabled="true"
        android:exported="true">
           <intent-filter>
              <!--<action android:name="husanity"/>-->
              <!--设置打电话对应的action-->
              <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
              </intent-filter>
    </receiver>

    Java代码中动态广播修改:(Android6.0之后的获取通讯录权限需要动态获取)

    <receiver
                android:name=".broadcast.MyStaticReceiver"
                android:enabled="true"
                android:exported="true">
                <intent-filter>
                    <!--<action android:name="husanity"/>-->
                    <!--设置打电话对应的action-->
                    <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
                </intent-filter>
    
            </receiver>
    View Code

    静态广播修改:

    package com.hxc.supreme.broadcast;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.util.Log;
    import android.widget.Toast;
    
    import com.hxc.supreme.utils.ToastUtil;
    
    public class MyStaticReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i("MyStaticReceiver", "静态广播接收到您正在拨打电话 " + getResultData());
        }
    }

    当我们直接从BroadcastActivity这个界面回到手机界面打电话时,看一下logcat的输出:

    02-15 16:30:46.162 4744-4744/com.hxc.supreme I/BroadcastActivity: 动态广播接收到您正在拨打电话 10001
    02-15 16:30:46.200 4744-4744/com.hxc.supreme I/MyStaticReceiver: 静态广播接收到您正在拨打电话 10001

    然后从BroadcastActivity界面先返回上级界面然后再回到手机界面拨打电话,此时的logcat输出:

    02-15 16:40:04.007 4744-4744/com.hxc.supreme I/com.hxc.supreme.activity.BroadcastActivity: onDestroy: 
    02-15 16:40:27.189 4744-4744/com.hxc.supreme I/MyStaticReceiver: 静态广播接收到您正在拨打电话 10001

    这是只能收到静态注册的广播,无法收到动态注册的广播了。

    所以,静态广播是常驻型广播,不随界面的销毁而销毁,只要程序没被杀死,收到了对应的广播通知时就会调用程序;

    而动态注册广播跟随界面的生命周期,不要忘了在页面销毁之前释放广播。

    有序广播和普通广播:

    普通广播:

    通过Context.sendBroadcast()方法来发送,它是完全异步的。所有的receivers(接收器)的执行顺序不确定,因此所有的receivers(接收器)接收broadcast的顺序不确定。
     
    有序广播:
    通过Context.sendOrderedBroadcast来发送,所有的receiver依次执行。BroadcastReceiver可以使用setResult系列函数来结果传给下一个BroadcastReceiver,通过getResult系列函数来取得上个BroadcastReceiver返回的结果,并可以abort系列函数来让系统丢弃该广播,使用该广播不再传送到别的BroadcastReceiver。可以通过在intent-filter中设置android:priority属性来设置receiver的优先级,优先级相同的receiver其执行顺序不确定。
     
    举例:
    短信拦截:你可以设置自己的app的广播接收器的级别高于系统原来的级别,并且收到后中断往下传播,这样的话收件箱里面就不会收到短信了。
  • 相关阅读:
    SQL SERVER将指定表中的指定字段按照(,)逗号分隔
    关于百度 UEditor的使用
    关于jquery的 $("form").serialize()和 new FormData表单序列化
    mvc5 + ef6 + autofac搭建项目(repository+uow)(二)
    (转载)[FFmpeg]使用ffmpeg从各种视频文件中直接截取视频图片
    sql查看数据库表使用情况
    EF FluentAPI映射一对多 关系时候报错
    (转载)Javascript 进阶 作用域 作用域链
    (转载)loadrunner简单使用——HTTP,WebService,Socket压力测试脚本编写
    [moka学习笔记]yii2.0 rules的用法(收集,不定期更新)
  • 原文地址:https://www.cnblogs.com/hxchaoshuai/p/10384768.html
Copyright © 2011-2022 走看看