Android framework短时间内发送多个相同的广播给app,如何做限制?

触发某个事件后会去调用Android framework的sendPermissionProtectedBroadcast函数,这个函数会发送指定广播出去,有权限的app都会接收这一条广播。

在做压力测试时,由于较长时间(60s)内频繁触发这个事件,然后在这60s内就发送了大量相同的广播,当测试停下来的时候,从日志中还能看到广播还在排队发送。所以怎么去限制这个广播的重复发送呢?

想法:我想的是当发送完一条广播后,如果10s内判断即将发送的广播Action如果和上一条一样,就不发送,这样就大大减少的发广播的次数。这样的话就需要记录上一条广播发送时间,然后在发下一跳广播的时候做计算。

        private void sendPermissionProtectedBroadcast(Intent intent) {
            if (mEventInstalledPackages.isEmpty()) {
                return;
            }
            intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
            for (String packageName : mEventInstalledPackages) {
                intent.setPackage(packageName);
                mContext.sendBroadcast(intent);
            }
        }

1. 添加一个变量来记录上一次发送广播的时间,比如:
java
private long mLastBroadcastTime;
2. 在发送广播前判断,如果与上次发送时间间隔小于给定值(如10秒),则不发送:
java
long now = System.currentTimeMillis();
if (now - mLastBroadcastTime < 10 * 1000) {
    return;  // 不发送广播
}
mLastBroadcastTime = now;  // 更新上次发送时间
3. 发送广播的代码可以改成这样:
java
private void sendPermissionProtectedBroadcast(Intent intent) {

    if (shouldThrottleBroadcast()) {
        return;  // 不发送广播
    }

    // 发送广播逻辑...
    mLastBroadcastTime = System.currentTimeMillis();  // 更新上次发送时间
}

private boolean shouldThrottleBroadcast() {
    long now = System.currentTimeMillis();
    return now - mLastBroadcastTime < 10 * 1000;  // 10秒内
} 
这样就可以限制10秒内不会发送重复的广播,达到节流的效果。10秒这个时间可以根据你的需要灵活调整。
这个思路就是通过记录上次发送广播的时间,在发送下一条广播前判断时间间隔,如果在给定阈值内就不发送,达到限制重复广播的目的。

你的想法是对的,需要保存上一条广播发送的时间,并在发送下一条广播前和当前时间进行比较。下面是一个实现的示例:

private static final int MIN_SEND_INTERVAL = 10000; // 最小发送间隔为 10s
private long lastSendTime = 0;
private String lastAction = null;

private void sendPermissionProtectedBroadcast(Intent intent) {
    if (mEventInstalledPackages.isEmpty()) {
        return;
    }

    // 如果和上一条广播是同一个,且距离上次发送时间还不到 MIN_SEND_INTERVAL ,那么不发送
    String currentAction = intent.getAction();
    long currentTime = System.currentTimeMillis();
    if (lastAction != null && lastAction.equals(currentAction) && currentTime - lastSendTime < MIN_SEND_INTERVAL) {
        return;
    }

    intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
    for (String packageName : mEventInstalledPackages) {
        intent.setPackage(packageName);
        mContext.sendBroadcast(intent);
    }

    // 保存当前广播信息
    lastSendTime = currentTime;
    lastAction = currentAction;
}

在发送下一条广播前,需要先判断上一条广播的 Action 是否和当前一致,如果不一致直接发送,如果一致再判断距离上一次发送的时间间隔是否满足最小发送间隔 MIN_SEND_INTERVAL,如果满足则发送,不满足则不发送。同时,每次发送广播后都需要记录下当前时间和当前 Action,以便和下一条广播做比较。