595 lines
22 KiB
Java
595 lines
22 KiB
Java
package com.halo.assistant;
|
||
|
||
import android.app.Application;
|
||
import android.content.Context;
|
||
import android.content.Intent;
|
||
import android.content.IntentFilter;
|
||
import android.content.pm.PackageInfo;
|
||
import android.net.ConnectivityManager;
|
||
import android.net.Uri;
|
||
import android.os.Build;
|
||
import android.os.StrictMode;
|
||
import android.preference.PreferenceManager;
|
||
import android.text.TextUtils;
|
||
import android.webkit.WebView;
|
||
|
||
import androidx.annotation.NonNull;
|
||
import androidx.collection.ArrayMap;
|
||
import androidx.lifecycle.ProcessLifecycleOwner;
|
||
import androidx.multidex.MultiDexApplication;
|
||
import androidx.webkit.WebViewCompat;
|
||
|
||
import com.alibaba.android.arouter.launcher.ARouter;
|
||
import com.facebook.animated.giflite.GifDecoder;
|
||
import com.facebook.imageformat.DefaultImageFormats;
|
||
import com.facebook.imagepipeline.core.ImagePipelineConfig;
|
||
import com.facebook.imagepipeline.core.ImagePipelineFactory;
|
||
import com.facebook.imagepipeline.core.ImageTranscoderType;
|
||
import com.facebook.imagepipeline.core.MemoryChunkType;
|
||
import com.facebook.imagepipeline.decoder.ImageDecoderConfig;
|
||
import com.gh.base.GlobalActivityLifecycleObserver;
|
||
import com.gh.common.FixedRateJobHelper;
|
||
import com.gh.common.filter.RegionSettingHelper;
|
||
import com.gh.common.util.DataUtils;
|
||
import com.gh.common.util.DownloadNotificationHelper;
|
||
import com.gh.common.util.DownloadObserver;
|
||
import com.gh.common.util.HomeBottomBarHelper;
|
||
import com.gh.common.util.PackageHelper;
|
||
import com.gh.common.util.PackageUtils;
|
||
import com.gh.common.videolog.VideoRecordUtils;
|
||
import com.gh.download.simple.DownloadMessageHandler;
|
||
import com.gh.download.simple.SimpleDownloadDatabase;
|
||
import com.gh.download.simple.SimpleDownloadManager;
|
||
import com.gh.gamecenter.BuildConfig;
|
||
import com.gh.gamecenter.Injection;
|
||
import com.gh.gamecenter.common.constant.Config;
|
||
import com.gh.gamecenter.common.constant.Constants;
|
||
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
|
||
import com.gh.gamecenter.common.image.EmptyDecoder;
|
||
import com.gh.gamecenter.common.tracker.Tracker;
|
||
import com.gh.gamecenter.common.utils.DarkModeUtils;
|
||
import com.gh.gamecenter.common.utils.DeviceUtils;
|
||
import com.gh.gamecenter.common.utils.ExtensionsKt;
|
||
import com.gh.gamecenter.common.utils.ImageUtils;
|
||
import com.gh.gamecenter.common.utils.PackageFlavorHelper;
|
||
import com.gh.gamecenter.core.AppExecutor;
|
||
import com.gh.gamecenter.core.iinterface.IApplication;
|
||
import com.gh.gamecenter.core.utils.DisplayUtils;
|
||
import com.gh.gamecenter.core.utils.GsonUtils;
|
||
import com.gh.gamecenter.core.utils.SPUtils;
|
||
import com.gh.gamecenter.entity.SubjectRecommendEntity;
|
||
import com.gh.gamecenter.fragment.MainWrapperRepository;
|
||
import com.gh.gamecenter.login.user.UserRepository;
|
||
import com.gh.gamecenter.oaid.OAIDHelper;
|
||
import com.gh.gamecenter.packagehelper.PackageRepository;
|
||
import com.gh.gamecenter.core.provider.IFlavorProvider;
|
||
import com.gh.gamecenter.provider.FlavorProviderImp;
|
||
import com.gh.gamecenter.receiver.ActivitySkipReceiver;
|
||
import com.gh.gamecenter.receiver.DownloadReceiver;
|
||
import com.gh.gamecenter.receiver.InstallAndUninstallReceiver;
|
||
import com.gh.gamecenter.receiver.InstallReceiver;
|
||
import com.gh.gamecenter.receiver.NetworkStateReceiver;
|
||
import com.gh.vspace.VHelper;
|
||
import com.github.piasy.biv.BigImageViewer;
|
||
import com.github.piasy.biv.loader.fresco.FrescoImageLoader;
|
||
import com.lg.ndownload.DownloadDbManager;
|
||
import com.lightgame.utils.Utils;
|
||
import com.llew.huawei.verifier.LoadedApkHuaWei;
|
||
import com.shuyu.gsyvideoplayer.cache.CacheFactory;
|
||
import com.shuyu.gsyvideoplayer.player.PlayerFactory;
|
||
|
||
import java.lang.reflect.Method;
|
||
import java.util.List;
|
||
import java.util.ServiceLoader;
|
||
|
||
import io.reactivex.plugins.RxJavaPlugins;
|
||
import tv.danmaku.ijk.media.exo2.Exo2PlayerManager;
|
||
import tv.danmaku.ijk.media.exo2.ExoPlayerCacheManager;
|
||
|
||
public class HaloApp extends MultiDexApplication {
|
||
|
||
private static HaloApp mInstance;
|
||
private static final ArrayMap<String, Object> sObjectMap = new ArrayMap<>();
|
||
|
||
private String mChannel;
|
||
private String mGid;
|
||
private String mTemporaryLocalDeviceId; // 临时设备ID (本地生成,与GID不相关)
|
||
private String mUA;
|
||
private String mOAID = "";
|
||
private String mServerUserMark = ""; // 服务端用来标记用户是新/老的标记,有 new 和 old 两个,获取不到时为空
|
||
|
||
private boolean mIsPostInitialized = false; // 是否已经延迟初始化过相关组件,避免重复初始化
|
||
private boolean mIsReinstallTheSameVersion = false; // 当前用户是否重新安装了一次当前版本后的第一次打开
|
||
|
||
public long deviceRamSize = 0;
|
||
public boolean isBrandNewInstall = false; // 当前用户是否是安装光环后第一次打开
|
||
public boolean isNewForThisVersion = false; // 当前用户是否是安装当前版本后第一次打开 (包括全新和更新)
|
||
public boolean isRunningForeground = false; // 标记当前 APP 是否处于前台运行中
|
||
|
||
public boolean isAlreadyUpAndRunning = false; // 应用是否处于运行中状态 (进入到 MainActivity 就当运行中)
|
||
private List<String> webViewAbiList;
|
||
private IFlavorProvider mFlavorProvider = new FlavorProviderImp();
|
||
private final ServiceLoader<IApplication> mApplicationList = ServiceLoader.load(IApplication.class, this.getClass().getClassLoader());
|
||
|
||
public static void put(String key, Object object) {
|
||
sObjectMap.put(key, object);
|
||
}
|
||
|
||
public static Object get(String key, boolean isRemove) {
|
||
if (isRemove) {
|
||
return sObjectMap.remove(key);
|
||
} else {
|
||
return sObjectMap.get(key);
|
||
}
|
||
}
|
||
|
||
public static void remove(String key) {
|
||
sObjectMap.remove(key);
|
||
}
|
||
|
||
public void setGid(String gid) {
|
||
mGid = gid;
|
||
}
|
||
|
||
public String getGid() {
|
||
return mGid;
|
||
}
|
||
|
||
public void refreshGid() {
|
||
DataUtils.getGid();
|
||
}
|
||
|
||
public void setLocalTemporaryDeviceId(String key) {
|
||
mTemporaryLocalDeviceId = key;
|
||
}
|
||
|
||
public String getTemporaryLocalDeviceId() {
|
||
return mTemporaryLocalDeviceId;
|
||
}
|
||
|
||
public void setServerUserMark(String mark) {
|
||
mServerUserMark = mark;
|
||
}
|
||
|
||
public String getServerUserMark() {
|
||
return mServerUserMark;
|
||
}
|
||
|
||
public static synchronized HaloApp getInstance() {
|
||
return mInstance;
|
||
}
|
||
|
||
|
||
public String getChannel() {
|
||
// 存在 IO 初始化线程阻塞(万物皆可阻塞)导致 mChannel 为空的情况,这里特殊处理下
|
||
if (TextUtils.isEmpty(mChannel)) {
|
||
return "";
|
||
} else {
|
||
return mChannel;
|
||
}
|
||
}
|
||
|
||
public void setChannel(String channel) {
|
||
mChannel = channel;
|
||
}
|
||
|
||
public void setOAID(String oaid) {
|
||
mOAID = oaid;
|
||
}
|
||
|
||
public String getOAID() {
|
||
return mOAID;
|
||
}
|
||
|
||
public String getUserAgent() {
|
||
if (TextUtils.isEmpty(mUA)) {
|
||
mUA = DeviceUtils.getUserAgent();
|
||
}
|
||
return mUA;
|
||
}
|
||
|
||
public List<String> getWebViewAbiList() {
|
||
return webViewAbiList;
|
||
}
|
||
|
||
@Override
|
||
public void onCreate() {
|
||
super.onCreate();
|
||
initArouter();
|
||
|
||
if (!Injection.appInit(this)) {
|
||
return;
|
||
}
|
||
|
||
mInstance = this;
|
||
|
||
// 每个进程都用自己的进程名作为后缀的文件夹来存 WebView cache
|
||
// https://sentry.shanqu.cc/organizations/lightgame/issues/285063/?project=22&query=is%3Aunresolved
|
||
// https://stackoverflow.com/a/61748345/4812571 这个无效
|
||
// WebView.disableWebView() 也无效
|
||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||
try {
|
||
String process = getProcessName();
|
||
WebView.setDataDirectorySuffix(process);
|
||
} catch (IllegalStateException e) {
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
|
||
for (IApplication application : mApplicationList) {
|
||
application.onCreate(mInstance);
|
||
}
|
||
|
||
// 似乎只是 load SO 不涉及方法调用,所以可以在隐私政策前调用吧?
|
||
OAIDHelper.INSTANCE.doSystemLoad();
|
||
|
||
// 70ms
|
||
PlayerFactory.setPlayManager(Exo2PlayerManager.class);
|
||
CacheFactory.setCacheManager(ExoPlayerCacheManager.class);
|
||
|
||
AppExecutor.getIoExecutor().execute(() -> {
|
||
initDataHelper();
|
||
ExtensionsKt.doOnMainProcessOnly(this, () -> Tracker.init(this));
|
||
|
||
initFresco();
|
||
|
||
deviceRamSize = DeviceUtils.getTotalRamSizeOfDevice(this);
|
||
mChannel = mFlavorProvider.getChannelStr(this);
|
||
|
||
// 异步初始化 SP
|
||
SPUtils.getString("");
|
||
|
||
DownloadDbManager.init(this);
|
||
});
|
||
|
||
RxJavaPlugins.setIoSchedulerHandler(scheduler -> AppExecutor.INSTANCE.getCachedScheduler());
|
||
|
||
if (isUserAcceptPrivacyPolicy(this)) {
|
||
postInit(false);
|
||
}
|
||
|
||
//设置严格模式
|
||
if (BuildConfig.DEBUG) {
|
||
StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
|
||
.detectAll()
|
||
.penaltyLog()
|
||
.build();
|
||
StrictMode.setVmPolicy(policy);
|
||
}
|
||
|
||
// debug 包和 jenkins 内部包启用 dokit
|
||
if (PackageFlavorHelper.IS_TEST_FLAVOR) {
|
||
try {
|
||
Class<?> clazz = Class.forName("com.didichuxing.doraemonkit.DoraemonKit");
|
||
Method method = clazz.getMethod("install", Application.class);
|
||
method.invoke(null, this);
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
|
||
registerActivityLifecycleCallbacks(new GlobalActivityLifecycleObserver());
|
||
|
||
DarkModeUtils.INSTANCE.initDarkMode();
|
||
}
|
||
|
||
/**
|
||
* 需要延迟初始化的东西,以下代码调用都放置到用户同意了隐私政策之后
|
||
*/
|
||
public void postInit(boolean initImmediately) {
|
||
if (mIsPostInitialized) return;
|
||
|
||
long delay = 500;
|
||
if (initImmediately) {
|
||
delay = 0;
|
||
}
|
||
postInit(delay);
|
||
|
||
mIsPostInitialized = true;
|
||
}
|
||
|
||
private void postInit(long delay) {
|
||
// 初始化 sentry
|
||
DataUtils.init(this, mChannel);
|
||
|
||
// 获取/更新 GID 和 读 SP 的操作不需要 delay
|
||
DataUtils.getGid();
|
||
|
||
OAIDHelper.INSTANCE.getOAID(this, s -> {
|
||
setOAID(s);
|
||
MetaUtil.INSTANCE.refreshMeta();
|
||
return null;
|
||
});
|
||
|
||
// 获取 settings 配置
|
||
ExtensionsKt.doOnMainProcessOnly(this, com.gh.common.constant.Config::getGhzsSettings);
|
||
|
||
String localTemporaryDeviceId = SPUtils.getString(Constants.SP_TEMPORARY_DEVICE_ID);
|
||
if (!TextUtils.isEmpty(localTemporaryDeviceId)) {
|
||
HaloApp.getInstance().setLocalTemporaryDeviceId(localTemporaryDeviceId);
|
||
}
|
||
|
||
// 刷新内存中的用户信息,避免应用进程重建时因没有用户信息数据而显示为掉登录状态
|
||
// 必须放在外面,否则不能及时刷新用户数据
|
||
UserRepository.getInstance().getLoginUserInfo();
|
||
|
||
MainWrapperRepository.Companion.getInstance().getHomeNavBar();
|
||
|
||
AppExecutor.getUiExecutor().executeWithDelay(() -> {
|
||
FixedRateJobHelper.begin();
|
||
|
||
RegionSettingHelper.getRegionSetting();
|
||
|
||
ExtensionsKt.doOnMainProcessOnly(this, () -> {
|
||
PackageRepository.initData();
|
||
PackageHelper.refreshLocalPackageList();
|
||
PackageHelper.initList();
|
||
});
|
||
|
||
initReceiver();
|
||
initPackageChangesReceiver();
|
||
initConnectivityChangesReceiver();
|
||
|
||
initTimeConsumingAction();
|
||
|
||
getWebviewAbiList();
|
||
|
||
// 注册回调以用于做各种统计
|
||
ProcessLifecycleOwner.get().getLifecycle().addObserver(new ProcessorLifeCycleOwner());
|
||
|
||
// 初始化畅玩相关数据
|
||
ExtensionsKt.doOnMainProcessOnly(this, this::retrieveVGameInfoIfNeeded);
|
||
|
||
// 开发环境不要强制捕获相关异常,这些异常通常是需要处理的
|
||
if (!BuildConfig.DEBUG) {
|
||
RxJavaPlugins.setErrorHandler(throwable -> {
|
||
if (Config.DEFAULT_CHANNEL.equals(mChannel)) {
|
||
Utils.toast(this, "当前页面未捕获的异常:" + throwable.toString());
|
||
}
|
||
});
|
||
}
|
||
}, delay);
|
||
}
|
||
|
||
private void initArouter() {
|
||
if (BuildConfig.DEBUG) { // 这两行必须写在init之前,否则这些配置在init过程中将无效
|
||
ARouter.openLog(); // 打印日志
|
||
ARouter.openDebug(); // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
|
||
}
|
||
ARouter.init(this); // 尽可能早,推荐在Application中初始化
|
||
}
|
||
|
||
public void getWebviewAbiList() {
|
||
int versionCode = SPUtils.getInt(Constants.SP_WEBVIEW_VERSION_CODE);
|
||
final PackageInfo webviewPackageInfo = WebViewCompat.getCurrentWebViewPackage(this);
|
||
if (webviewPackageInfo == null) return;
|
||
int webviewVersionCode = webviewPackageInfo.versionCode;
|
||
String json = SPUtils.getString(Constants.SP_WEBVIEW_ABI_LIST);
|
||
if (versionCode == webviewVersionCode && !json.isEmpty()) {
|
||
try {
|
||
webViewAbiList = GsonUtils.fromJsonList(json);
|
||
return;
|
||
} catch (AssertionError e) {
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
AppExecutor.getIoExecutor().execute(() -> {
|
||
final String webviewPath = PackageUtils.getWebviewPath(this);
|
||
if (webviewPath == null) return;
|
||
final List<String> abiList = PackageUtils.getApkAbiList(webviewPath);
|
||
webViewAbiList = abiList;
|
||
SPUtils.setString(Constants.SP_WEBVIEW_ABI_LIST, GsonUtils.toJson(abiList));
|
||
SPUtils.setInt(Constants.SP_WEBVIEW_VERSION_CODE, webviewVersionCode);
|
||
});
|
||
}
|
||
|
||
private void initDataHelper() {
|
||
VideoRecordUtils.init(this, AppExecutor.getLogExecutor());
|
||
}
|
||
|
||
// todo 动态注册和静态注册并行的话会触发多次回调
|
||
// 3.5 开始将 targetSdk 升级至 26,原来写在 Manifest 的部分 receiver 由于系统限制需要换成在运行时注册
|
||
private void initReceiver() {
|
||
DownloadReceiver downloadReceiver = new DownloadReceiver();
|
||
IntentFilter downloadFilter = new IntentFilter();
|
||
downloadFilter.addAction(DownloadNotificationHelper.ACTION_DOWNLOAD);
|
||
downloadFilter.addAction(DownloadNotificationHelper.ACTION_VDOWNLOAD);
|
||
this.registerReceiver(downloadReceiver, downloadFilter);
|
||
|
||
InstallReceiver installReceiver = new InstallReceiver();
|
||
IntentFilter installFilter = new IntentFilter();
|
||
installFilter.addAction(DownloadNotificationHelper.ACTION_INSTALL);
|
||
this.registerReceiver(installReceiver, installFilter);
|
||
|
||
ActivitySkipReceiver skipReceiver = new ActivitySkipReceiver();
|
||
IntentFilter skipFilter = new IntentFilter();
|
||
skipFilter.addAction(ActivitySkipReceiver.ACTION_ACTIVITY_SKIP);
|
||
this.registerReceiver(skipReceiver, skipFilter);
|
||
}
|
||
|
||
private void initPackageChangesReceiver() {
|
||
InstallAndUninstallReceiver receiver = new InstallAndUninstallReceiver();
|
||
IntentFilter intentFilter = new IntentFilter();
|
||
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||
intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
|
||
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||
intentFilter.addDataScheme("package");
|
||
this.registerReceiver(receiver, intentFilter);
|
||
}
|
||
|
||
private void initConnectivityChangesReceiver() {
|
||
NetworkStateReceiver receiver = new NetworkStateReceiver();
|
||
IntentFilter intentFilter = new IntentFilter();
|
||
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||
this.registerReceiver(receiver, intentFilter);
|
||
}
|
||
|
||
private void initTimeConsumingAction() {
|
||
AppExecutor.getIoExecutor().execute(() -> {
|
||
// 初始化全局下载监听
|
||
DownloadObserver.initObserver();
|
||
|
||
if ("miui".equals(Build.MANUFACTURER) && Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||
DisplayUtils.sShouldUseLegacyMiuiStatusBarMethod = true;
|
||
}
|
||
|
||
// 避免在华为设备上出现 `Register too many Broadcast Receivers` 异常,可见 https://github.com/llew2011/HuaWeiVerifier
|
||
LoadedApkHuaWei.hookHuaWeiVerifier(this);
|
||
|
||
SimpleDownloadManager.INSTANCE.init();
|
||
DownloadMessageHandler.INSTANCE.init(SimpleDownloadDatabase.getInstance().downloadDao());
|
||
|
||
// 预加载游戏库图标
|
||
SubjectRecommendEntity barData = HomeBottomBarHelper.getDefaultGameBarData();
|
||
if (!TextUtils.isEmpty(barData.getIconSelect())) {
|
||
ImageUtils.getPicasso().load(Uri.parse(barData.getIconSelect())).fetch();
|
||
}
|
||
if (!TextUtils.isEmpty(barData.getIconUnselect())) {
|
||
ImageUtils.getPicasso().load(Uri.parse(barData.getIconUnselect())).fetch();
|
||
}
|
||
});
|
||
}
|
||
|
||
|
||
public void initFresco() {
|
||
// 初始化 Fresco(BigImageViewer 已包含Fresco)
|
||
if (!ImageUtils.isFrescoInitialized()) {
|
||
// 在 5.0 & 5.1 设备上 disable native code,原因是应用附带了 arm64 的 SO 以后在部分 5.0/5.1 设备
|
||
// 会出现找不到 arm64 so 的情况,具体可见
|
||
// https://sentry.ghzs.com/organizations/lightgame/issues/53107/
|
||
// 所以这里尝试在 5.0 & 5.1 设备上关闭 fresco 的 native 解码,应该会让 5.0 & 5.1 的设备 OOM 概率提高,但先试试效果
|
||
// 同时禁用动图
|
||
ImagePipelineConfig.Builder pipelineConfigBuilder = ImagePipelineConfig.newBuilder(this);
|
||
ImageDecoderConfig.Builder decodeConfigBuilder = ImageDecoderConfig.newBuilder();
|
||
|
||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP
|
||
|| Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||
pipelineConfigBuilder.setMemoryChunkType(MemoryChunkType.BUFFER_MEMORY)
|
||
.setImageTranscoderType(ImageTranscoderType.JAVA_TRANSCODER);
|
||
|
||
decodeConfigBuilder.overrideDecoder(DefaultImageFormats.GIF, new GifDecoder()).build();
|
||
|
||
String manufacture = Build.MANUFACTURER.toLowerCase();
|
||
|
||
// OPPO 和 VIVO 的 5.1.1 设备还会去加载 WEBP_ANIMATED 的 SO,
|
||
// 实测没有发现有地方使用 WEBP_ANIMATED 的图片,这里用空占位图来替换 WEBP 动图
|
||
if ("oppo".equals(manufacture) || "vivo".equals(manufacture)) {
|
||
decodeConfigBuilder.overrideDecoder(DefaultImageFormats.WEBP_ANIMATED, new EmptyDecoder()).build();
|
||
}
|
||
|
||
pipelineConfigBuilder
|
||
.setImageDecoderConfig(decodeConfigBuilder.build())
|
||
.experiment()
|
||
.setNativeCodeDisabled(true);
|
||
|
||
// 图片仅加载静态图片
|
||
ImageUtils.disableAnimatedImage();
|
||
}
|
||
|
||
try {
|
||
BigImageViewer.initialize(FrescoImageLoader.with(this, pipelineConfigBuilder.build()));
|
||
} catch (Throwable e) {
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
}
|
||
|
||
private void retrieveVGameInfoIfNeeded() {
|
||
VHelper.init(this);
|
||
}
|
||
|
||
public boolean isReinstallTheSameVersion() {
|
||
return mIsReinstallTheSameVersion;
|
||
}
|
||
|
||
public void setIsReinstallTheSameVersion(boolean value) {
|
||
mIsReinstallTheSameVersion = value;
|
||
}
|
||
|
||
public Application getApplication() {
|
||
return this;
|
||
}
|
||
|
||
/**
|
||
* 判断当前用户是否是已经同意过隐私政策协议
|
||
* 覆盖安装进入过首页的也当作是同意了
|
||
*/
|
||
public static boolean isUserAcceptPrivacyPolicy(Context context) {
|
||
return !PreferenceManager.getDefaultSharedPreferences(context).getBoolean("isNewFirstLaunchV" + PackageUtils.getGhVersionName(), true)
|
||
|| !SPUtils.getBooleanWithContext(context, Constants.SP_BRAND_NEW_USER, true)
|
||
|| SPUtils.getBooleanWithContext(context, Constants.SP_IS_USER_ACCEPTED_PRIVACY_STATEMENT, false);
|
||
}
|
||
|
||
public IFlavorProvider getFlavorProvider() {
|
||
return mFlavorProvider;
|
||
}
|
||
|
||
// @NonNull
|
||
// @Override
|
||
// public Configuration getWorkManagerConfiguration() {
|
||
// return new Configuration.Builder().build();
|
||
// }
|
||
|
||
@Override
|
||
protected void attachBaseContext(Context base) {
|
||
super.attachBaseContext(base);
|
||
for (IApplication application : mApplicationList) {
|
||
application.attachBaseContext();
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void onLowMemory() {
|
||
super.onLowMemory();
|
||
|
||
clearMemoryCaches();
|
||
|
||
for (IApplication application : mApplicationList) {
|
||
application.onLowMemory();
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void onConfigurationChanged(@NonNull android.content.res.Configuration newConfig) {
|
||
super.onConfigurationChanged(newConfig);
|
||
for (IApplication application : mApplicationList) {
|
||
application.onConfigurationChanged(newConfig);
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void onTerminate() {
|
||
super.onTerminate();
|
||
for (IApplication application : mApplicationList) {
|
||
application.onTerminate();
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void onTrimMemory(int level) {
|
||
super.onTrimMemory(level);
|
||
|
||
if (level >= TRIM_MEMORY_MODERATE) {
|
||
clearMemoryCaches();
|
||
}
|
||
|
||
for (IApplication application : mApplicationList) {
|
||
application.onTrimMemory(level);
|
||
}
|
||
}
|
||
|
||
private void clearMemoryCaches() {
|
||
// 有一定机率在 ImagePipelineFactory 还没完成初始化就被调用,
|
||
// 直接粗暴地 catch 异常 "ImagePipelineFactory was not initialized!"
|
||
// 毕竟这里只是内存不足时候的操作,不用保证执行结果
|
||
try {
|
||
ImagePipelineFactory.getInstance().getImagePipeline().clearMemoryCaches();
|
||
} catch (NullPointerException e) {
|
||
e.printStackTrace();
|
||
}
|
||
ImageUtils.getPicassoLruCache().clear();
|
||
ImageUtils.clearUrlCaches();
|
||
}
|
||
|
||
}
|