最近在友盟上發(fā)現(xiàn)一處崩潰
java.lang.IllegalArgumentException: regist too many Broadcast Receivers at android.app.ContextImpl.registerReceiverInternal
導(dǎo)致這個問題的原因是華為5.1和5.1.1上,有一個針對廣播注冊的限制,HuaWei自家定制的ROM系統(tǒng)中有一個白名單機制,只有加入了白名單的APP才允許注冊超過500個BroadcastReceiver,否則就會拋出Register too many Broadcast Receivers的異常。
也就是說沒有加入該白名單機制的APP最多只能注冊500個BroadcastReceiver。
那么解決這個問題可以分成兩種
1:找到注冊廣播的源頭,解決。
2:用反射黑科技,把自己包名加入到華為白名單里,從而豁免500限制。
反射的辦法網(wǎng)上很多個,參考
https://ishinagimoeta.github.io/2018/10/15/HuaweiRegister2many/、https://github.com/bumptech/glide/issues/1161
我們從源頭排查問題,發(fā)現(xiàn)是glide這個圖片加載框架引起的。
app打開了網(wǎng)絡(luò)權(quán)限("android.permission.ACCESS_NETWORK_STATE"), glide 能監(jiān)聽網(wǎng)絡(luò)變化,在有網(wǎng)、斷網(wǎng)的時候調(diào)整自身的加載策略,核心類是DefaultConnectivityMonitorFactory、DefaultConnectivityMonitor
崩潰發(fā)生在DefaultConnectivityMonitor的注冊廣播函數(shù),華為拋出的IllegalArgumentException無法被捕獲
private void register() {
if (isRegistered) {
return;
}
// Initialize isConnected.
isConnected = isConnected(context);
try {
// See #1405
context.registerReceiver(connectivityReceiver,
new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
isRegistered = true;
} catch (SecurityException e) {
// See #1417, registering the receiver can throw SecurityException.
if (Log.isLoggable(TAG, Log.WARN)) {
Log.w(TAG, "Failed to register", e);
}
}
}
好在glide支持模塊自主配置,因此我們在華為的5.0、5.1上不再注冊glide的網(wǎng)絡(luò)監(jiān)聽事件。下面是我們解決的辦法,核心是builder.setConnectivityMonitorFactory(new NoConnectivityMonitorFactory());
@GlideModule
public final class XLOkHttpLibraryGlideModule extends AppGlideModule {
@Override
public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
super.applyOptions(context, builder);
//兼容了華為平板 5.1 5.0機型上,Register too many Broadcast Receivers 的問題
if (NoConnectivityMonitorFactory.needDisableNetCheck()) {
builder.setConnectivityMonitorFactory(new NoConnectivityMonitorFactory());
}
}
}
**
* 功能:不做網(wǎng)絡(luò)監(jiān)聽,兼容華為平板
* 描述:
* Created by 陳俊杰 on 2019/9/3.
*/
public class NoConnectivityMonitorFactory implements ConnectivityMonitorFactory {
/**
* 華為 5.1 5.11機型需要禁用glide網(wǎng)絡(luò)監(jiān)聽功能
*
* @return
*/
public static boolean needDisableNetCheck() {
return isHuawei() && Build.VERSION.SDK_INT < Build.VERSION_CODES.M;
}
static boolean isHuawei() {
String brand = Build.BRAND.toLowerCase();
return brand.contains("huawei") || brand.contains("honor");
}
@NonNull
@Override
public ConnectivityMonitor build(@NonNull Context context, @NonNull ConnectivityMonitor.ConnectivityListener listener) {
return new ConnectivityMonitor() {
@Override
public void onStart() {
//不做處理
}
@Override
public void onStop() {
//不做處理
}
@Override
public void onDestroy() {
//不做處理
}
};
}
}