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的广播接收器的级别高于系统原来的级别,并且收到后中断往下传播,这样的话收件箱里面就不会收到短信了。
  • 相关阅读:
    UVa 1451 Average (斜率优化)
    POJ 1160 Post Office (四边形不等式优化DP)
    HDU 3507 Print Article (斜率DP)
    LightOJ 1427 Substring Frequency (II) (AC自动机)
    UVa 10245 The Closest Pair Problem (分治)
    POJ 1741 Tree (树分治)
    HDU 3487 Play with Chain (Splay)
    POJ 2828 Buy Tickets (线段树)
    HDU 3723 Delta Wave (高精度+calelan数)
    UVa 1625 Color Length (DP)
  • 原文地址:https://www.cnblogs.com/hxchaoshuai/p/10384768.html
Copyright © 2011-2022 走看看