BroadcastReceiver详解

本文详细介绍了BroadcastReceiver的使用方式,包括在Manifest.xml中和代码中注册。深入探讨了BroadcastReceiver的原理,涵盖静态和动态注册的过程,以及发送、接收和取消广播的方法。还对比了BroadcastReceiver与LocalBroadcastReceiver的区别,强调了LocalBroadcastReceiver的线程安全和单例模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

BroadcastReceiver详解

使用方式

在Manifest.xml文件中注册

<receiver
  android:name=".test.broadcast.MyTestReceiver"
  android:enabled="true"
  android:exported="true">
  <intent-filter>
      <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
      <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
      <action android:name="android.intent.action.SCREEN_ON" />
      <action android:name="android.intent.action.SCREEN_OFF" />
      <action android:name="android.intent.action.INPUT_METHOD_CHANGED" />
      <action android:name="android.intent.action.CONFIGURATION_CHANGED" />
      <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
      <action android:name="android.intent.action.USER_PRESENT" />
  </intent-filter>
</receiver>

在Manifesh.xml文件中注册自定义的BroadcastReceiver,当意图过滤器中的动作发生时,会回调BroadcastReceiver中的onRecevie方法.

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

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent != null) {
            String action = intent.getAction();
            Log.d(TAG, "onReceive: receive action is " + action);
        }
    }
}

代码中动态注册

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);

registerReceiver(new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
      String action = intent == null ? "" : intent.getAction();
      if (Intent.ACTION_SCREEN_OFF.equalsIgnoreCase(action)) {
          Log.i(TAG, "onReceive: 屏幕关闭");
      }
      context.unregisterReceiver(this);
  }
}, intentFilter);

在Activity上下文中调用registerReceiver方法,动态注册一个广播接收者,同时指定了意图过滤器。
这里要注意注册的BroadcastReceiver最好是静态类,防止内存泄漏。否则要及时取消注册。

原理

注册通知

静态注册

通过PackageManagerService安装应用时,会解析安装包中的Manifest.xml文件,存储解析到Receiver标签对应的广播接收器。

通过Unix Socket接收需要安装的Apk文件
//android/os/FileBridge.java

public class FileBridge extends Thread {
    private static final int MSG_LENGTH = 8;
    private final FileDescriptor mServer = new FileDescriptor();
    private final FileDescriptor mClient = new FileDescriptor();
    
    private FileDescriptor mTarget;

    //构造函数
    //创建Unix Domain Socket的客户端和服务端,然后会将代表客户端的文件描述符发送给客户端进程
    public FileBridge() {
        try {
            Os.socketpair(AF_UNIX, SOCK_STREAM, 0, mServer, mClient);
        } catch (ErrnoException e) {
            throw new RuntimeException("Failed to create bridge");
        }
    }
    
    //mTarget文件描述符用来存储客户端进程发送过来的Apk文件数据
    public void setTargetFile(FileDescriptor target) {
        mTarget = target;
    }

    public FileDescriptor getClientSocket() {
        return mClient;
    }
    
    //这是一个线程,不停监听Socket的Server端
    @Override
    public void run() {
        final byte[] temp = new byte[8192];//读缓冲区
        //读取Socket的Server端,如果没有数据会阻塞
        //每次先读取8字节,前4个字节代表数据类型,后4四个字节代表数据长度
        while (IoBridge.read(mServer, temp, 0, MSG_LENGTH) == MSG_LENGTH) {
            //按照大端序读取前4字节
            final int cmd = Memory.peekInt(temp, 0, ByteOrder.BIG_ENDIAN);
            //数据写入,将apk文件数据写入到mTraget代表的文件描述中
            if (cmd == CMD_WRITE) {
                int len = Memory.peekInt(temp, 4, ByteOrder.BIG_ENDIAN);
               while (len > 0) {
                   int n = IoBridge.read(mServer, temp, 0, Math.min(temp.length, len));
                   if (n == -1) {
                       throw new IOException(
                               "Unexpected EOF; still expected " + len + " bytes");
                   }
                   IoBridge.write(mTarget, temp, 0, n);
                   len -= n;
               }
            //数据同步,并回显给客户端确认
            } else if (cmd == CMD_FSYNC) {
                Os.fsync(mTarget);
                IoBridge.write(mServer, temp, 0, MSG_LENGTH);
            //关闭消息通道,并回显给客户端确认
            } else if (cmd == CMD_CLOSE) {
                Os.fsync(mTarget);
               Os.close(mTarget);
               mClosed = true;
               IoBridge.write(mServer, temp, 0, MSG_LENGTH);
               break;
            }
        }
        
    }
}
验证APK合法性
  1. 包名、版本号
  2. 签名(V2+V1)sudo
  3. 其他应用验证package-verifier
  4. 应用申请的权限,需要用户确认
  5. 拷贝安装包到data/data/{包名}/目录下,并且复制Native库到lib目录下
解析Apk文件
  1. 添加apk文件路径到AssetManager管理中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值