Android BroadcastReceive广播详解

版权声明:没事随便转 https://blog.csdn.net/qq_41816123/article/details/85137492

定义

是一个全局的监听器

工作原理

在这里插入图片描述

使用流程

在这里插入图片描述

自定义广播接收者BroadcastReceiver

继承BroadcastReceivre基类
必须复写抽象方法onReceive()方法
1.广播接收器接收到相应广播后,会自动回调 onReceive() 方法
2.一般情况下,onReceive方法会涉及 与 其他组件之间的交互,如发送Notification、启动Service等
3.默认情况下,广播接收器运行在 UI 线程,因此,onReceive()方法不能执行耗时操作,否则将导致ANR
代码范例

package com.yuexia.myservice;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class MyBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "MyBroadcastReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        Log.d(TAG, "onReceive: 接收成功");
        //使用广播拦截技术,代码如下
        //-------------------abortBroadcast();
    }
}

广播接收器注册方式

静态注册
在AndroidManifest.xml中声明

<receiver 
    android:enabled=["true" | "false"]
//此broadcastReceiver能否接收其他App的发出的广播
//默认值是由receiver中有无intent-filter决定的:如果有intent-filter,默认值为true,否则为false
    android:exported=["true" | "false"]
    android:icon="drawable resource"
    android:label="string resource"
//继承BroadcastReceiver子类的类名
    android:name=".mBroadcastReceiver"
//具有相应权限的广播发送者发送的广播才能被此BroadcastReceiver所接收;
    android:permission="string"
//BroadcastReceiver运行所处的进程
//默认为app的进程,可以指定独立的进程
//注:Android四大基本组件都可以通过此属性指定自己的独立进程
    android:process="string" >

//用于指定此广播接收器将接收的广播类型
//本示例中给出的是用于接收网络状态改变时发出的广播
 <intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
</receiver>

动态注册

// 选择在Activity生命周期方法中的onResume()中注册
@Override
  protected void onResume(){
      super.onResume();
    // 1. 实例化BroadcastReceiver子类 &  IntentFilter
     mBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver();
     IntentFilter intentFilter = new IntentFilter();

    // 2. 设置接收广播的类型
    intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);

    // 3. 动态注册:调用Context的registerReceiver()方法
     registerReceiver(mBroadcastReceiver, intentFilter);
 }
// 注册广播后,要在相应位置记得销毁广播
// 即在onPause() 中unregisterReceiver(mBroadcastReceiver)
// 当此Activity实例化时,会动态将MyBroadcastReceiver注册到系统中
// 当此Activity销毁时,动态注册的MyBroadcastReceiver将不再接收到相应的广播。
 @Override
 protected void onPause() {
     super.onPause();
      //销毁在onResume()方法中的广播
     unregisterReceiver(mBroadcastReceiver);
     }
}
1.动态广播,有注册就必然得有注销,否则会导致内存泄露
2.重复注册、重复注销也不允许
3.在onResume()注册、onPause()注销是因为onPause()在App死亡前一定会被执行,从而保证广播在App死亡前一定会被注销,从而防止内存泄露。

不在onCreate() & onDestory() 或 onStart() & onStop()注册、注销是因为:
3.1
当系统因为内存不足(优先级更高的应用需要内存,请看上图红框)要回收Activity占用的资源时,Activity在执行完onPause()方法后就会被销毁,有些生命周期方法onStop(),onDestory()就不会执行。当再回到此Activity时,是从onCreate方法开始执行。
3.2
假设我们将广播的注销放在onStop(),onDestory()方法里的话,有可能在Activity被销毁后还未执行onStop(),onDestory()方法,即广播仍还未注销,从而导致内存泄露。
3.3
但是,onPause()一定会被执行,从而保证了广播在App死亡前一定会被注销,从而防止内存泄露。

两种注册方式的区别

两种注册方式的区别

普通广播

即 开发者自身定义 intent的广播(最常用)。发送广播使用如下:

Intent intent = new Intent();
//对应BroadcastReceiver中intentFilter的action
intent.setAction(BROADCAST_ACTION);
//发送广播
sendBroadcast(intent);

若被注册了的广播接收者中注册时intentFilter的action与上述匹配,则会接收此广播(即进行回调onReceive())。如下mBroadcastReceiver则会接收上述广播

<receiver 
    //此广播接收者类是mBroadcastReceiver
    android:name=".mBroadcastReceiver" >
    //用于接收网络状态改变时发出的广播
    <intent-filter>
        <action android:name="BROADCAST_ACTION" />
    </intent-filter>
</receiver>

若发送广播有相应权限,那么广播接收者也需要相应权限

有序广播

1.定义
发送出去的广播被广播接收者按照先后顺序接收

2.广播接受者接收广播的顺序规则(同时面向静态和动态注册的广播接受者)

3.按照Priority属性值从大-小排序;
Priority属性相同者,动态注册的广播优先;

4.特点
接收广播按顺序接收
先接收的广播接收者可以对广播进行截断,即后接收的广播接收者不再接收到此广播;
先接收的广播接收者可以对广播进行修改,那么后接收的广播接收者将接收到被修改后的广播

5.具体使用
有序广播的使用过程与普通广播非常类似,差异仅在于广播的发送方式:

sendOrderedBroadcast(intent);

App应用内广播

其他还有
系统广播(System Broadcast)
粘性广播(Sticky Broadcast)
我就不一一介绍了
付Demo:

MyBroadcastReceiver.calss
package com.yuexia.myservice;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class MyBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "MyBroadcastReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        Log.d(TAG, "onReceive: 接收成功");
        //使用广播拦截技术,代码如下
        //-------------------abortBroadcast();
    }
}
MainActivity.calss
package com.yuexia.myservice;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity implements View.OnClickListener{
    private boolean isBound = false;
    private Intent intent;
    private MyBroadcastReceiver mBroadcastReceiver;
    private LocalBroadcastManager localBroadcastManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intent = new Intent(this,TextService.class);
        initView();
    }
    
    private void initView() {
    	//发送广播的按钮
        Button btn_send=(Button) this.findViewById(R.id.btn_send);
        btn_send.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_send :
                Intent intent = new Intent();
                //对应BroadcastReceiver中intentFilter的action
                intent.setAction("android.net.conn.CONNECTIVITY_CHANGE");
                //发送广播
                localBroadcastManager.sendBroadcast(intent);
                break;
        }
    }
    // 选择在Activity生命周期方法中的onResume()中注册
    @Override
    protected void onResume(){
        // 1. 实例化BroadcastReceiver子类 &  IntentFilter
        mBroadcastReceiver = new MyBroadcastReceiver();
        IntentFilter intentFilter = new IntentFilter();

        // 2. 设置接收广播的类型
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");

        //步骤2:实例化LocalBroadcastManager的实例
        localBroadcastManager = LocalBroadcastManager.getInstance(this);
        //步骤4:调用LocalBroadcastManager单一实例的registerReceiver()方法进行动态注册
        localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);

        // 3. 动态注册:调用Context的registerReceiver()方法
//        registerReceiver(mBroadcastReceiver, intentFilter);
        super.onResume();
    }
    // 注册广播后,要在相应位置记得销毁广播
    // 即在onPause() 中unregisterReceiver(mBroadcastReceiver)
    // 当此Activity实例化时,会动态将MyBroadcastReceiver注册到系统中
    // 当此Activity销毁时,动态注册的MyBroadcastReceiver将不再接收到相应的广播。
    @Override
    protected void onPause() {
        //销毁在onResume()方法中的广播
        localBroadcastManager.unregisterReceiver(mBroadcastReceiver);
        super.onPause();
    }
}

到这里就结束了

本文借鉴了很多内容和图片,更详细的可以看
https://www.jianshu.com/p/ca3d87a4cdf3

猜你喜欢

转载自blog.csdn.net/qq_41816123/article/details/85137492