Files
assistant-android/app/src/main/java/com/gh/gamecenter/MainActivity.java

1201 lines
54 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.gh.gamecenter;
import android.app.Dialog;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.widget.TextView;
import com.gh.base.AppUncaughtHandler;
import com.gh.base.BaseActivity;
import com.gh.base.fragment.BaseFragment_ViewPager;
import com.gh.common.constant.Config;
import com.gh.common.constant.Constants;
import com.gh.common.exposure.ExposureUtils;
import com.gh.common.exposure.meta.MetaUtil;
import com.gh.common.im.ImManager;
import com.gh.common.util.ClassUtils;
import com.gh.common.util.CommunityHelper;
import com.gh.common.util.ConcernUtils;
import com.gh.common.util.DataCollectionUtils;
import com.gh.common.util.DataLogUtils;
import com.gh.common.util.DataUtils;
import com.gh.common.util.DeviceTokenUtils;
import com.gh.common.util.DeviceUtils;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.DirectUtils;
import com.gh.common.util.EntranceUtils;
import com.gh.common.util.GameUtils;
import com.gh.common.util.GsonUtils;
import com.gh.common.util.LogUtils;
import com.gh.common.util.MtaHelper;
import com.gh.common.util.NetworkUtils;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.PlatformUtils;
import com.gh.common.util.TrafficUtils;
import com.gh.common.util.UrlFilterUtils;
import com.gh.download.DownloadManager;
import com.gh.download.DownloadNotification;
import com.gh.gamecenter.db.info.GameInfo;
import com.gh.gamecenter.db.info.InstallInfo;
import com.gh.gamecenter.entity.ApkEntity;
import com.gh.gamecenter.entity.CommunityEntity;
import com.gh.gamecenter.entity.GameDigestEntity;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.entity.GameUpdateEntity;
import com.gh.gamecenter.entity.InnerMetaInfoEntity;
import com.gh.gamecenter.entity.SettingsEntity;
import com.gh.gamecenter.eventbus.EBNetworkState;
import com.gh.gamecenter.eventbus.EBPackage;
import com.gh.gamecenter.eventbus.EBReuse;
import com.gh.gamecenter.eventbus.EBShowDialog;
import com.gh.gamecenter.eventbus.EBSkip;
import com.gh.gamecenter.fragment.MainWrapperFragment;
import com.gh.gamecenter.manager.DataCollectionManager;
import com.gh.gamecenter.manager.FilterManager;
import com.gh.gamecenter.manager.GameManager;
import com.gh.gamecenter.manager.InstallManager;
import com.gh.gamecenter.manager.PackageManager;
import com.gh.gamecenter.manager.UpdateManager;
import com.gh.gamecenter.manager.UserManager;
import com.gh.gamecenter.normal.NormalFragment;
import com.gh.gamecenter.qa.AskFragment;
import com.gh.gamecenter.retrofit.ObservableUtil;
import com.gh.gamecenter.retrofit.Response;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.gh.gamecenter.suggest.SuggestType;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.halo.assistant.HaloApp;
import com.lightgame.config.CommonDebug;
import com.lightgame.download.DataWatcher;
import com.lightgame.download.DownloadConfig;
import com.lightgame.download.DownloadEntity;
import com.lightgame.download.DownloadStatus;
import com.lightgame.download.FileUtils;
import com.lightgame.utils.Util_System_Phone_State;
import com.lightgame.utils.Utils;
import com.tencent.bugly.beta.tinker.TinkerManager;
import com.tencent.bugly.crashreport.CrashReport;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.HttpException;
import static com.gh.common.util.EntranceUtils.KEY_TO;
import static com.gh.gamecenter.fragment.MainWrapperFragment.INDEX_PERSONAL;
import static com.gh.gamecenter.personal.PersonalFragment.LOGIN_TAG;
import static com.gh.gamecenter.personal.PersonalFragment.LOGOUT_TAG;
/**
* 项目的主Activity3个Fragment都嵌入在这里。
*/
public class MainActivity extends BaseActivity {
public final static String EB_MAINACTIVITY_TAG = "MainActivity";
public final static String EB_SKIP_GAMEFRAGMENT = "GameFragment";
public final static String SHOULD_INIT_IM = "should_init_im";
public final static String SWITCH_TO_COMMUNITY = "switch_to_community";
private MainWrapperFragment mMainWrapperFragment;
private SharedPreferences sp;
private InstallManager mInstallManager;
private static final int SKIP_SETTING_REQUEST = 14;
private boolean isSkipped;
public static boolean isNewFirstLaunch;
public static boolean openCommunityWithDefaultIdForTheFirsTime; // 是否根据 META-INFO 里的 JSON 自动选择默认的社区 ID
Runnable skipRun = new Runnable() {
@Override
public void run() {
if (getIntent() != null && getIntent().getExtras() != null && !isSkipped) {
isSkipped = true;
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
String to = bundle.getString(KEY_TO);
if (!TextUtils.isEmpty(to)) {
Class<?> clazz = ClassUtils.forName(to);
if (clazz != null) {
String entrance = bundle.getString(EntranceUtils.KEY_ENTRANCE);
if (TextUtils.isEmpty(entrance) || !entrance.startsWith("(") || !entrance.endsWith(")")) {
bundle.putString(EntranceUtils.KEY_ENTRANCE, "(插件跳转)");
}
String packageName = bundle.getString("packageName");
if (packageName != null) {
bundle.putInt(BaseFragment_ViewPager.ARGS_INDEX, 1);
}
if (NormalFragment.class.isAssignableFrom(clazz)) {
NormalActivity.startFragment(MainActivity.this, (Class<? extends NormalFragment>) clazz, bundle);
} else {
Intent skipIntent = new Intent(MainActivity.this, clazz);
skipIntent.putExtras(bundle);
startActivity(skipIntent);
}
}
}
}
}
}
};
private Handler handler = new Handler();
// 黄壮华 添加观察者 修改2015/8/15
private DataWatcher dataWatcher = new DataWatcher() {
@Override
public void onDataChanged(DownloadEntity downloadEntity) {
if (DownloadStatus.hijack.equals(downloadEntity.getStatus())) {
// 链接被劫持
processHijack(downloadEntity);
String nameAndPlatform = downloadEntity.getName() + ":"
+ PlatformUtils.getInstance(getApplicationContext()).getPlatformName(downloadEntity.getPlatform());
DataUtils.onMtaEvent(getApplicationContext(), "下载劫持", "游戏名字", nameAndPlatform, "网络状态" + DeviceUtils.getNetwork(getApplication()));
return;
} else if (DownloadStatus.notfound.equals(downloadEntity.getStatus())) {
// 404 Not Found
// 删除任务
downloadEntity.setStatus(DownloadStatus.cancel);
DownloadManager.getInstance(getApplicationContext()).cancel(downloadEntity.getUrl());
toast("该链接已失效!请联系管理员。");
EventBus.getDefault().post(new EBShowDialog("notfound", downloadEntity.getName()));
MtaHelper.onEventWithBasicDeviceInfo("下载失败弹窗",
"游戏", downloadEntity.getName(),
"平台", downloadEntity.getPlatform());
return;
} else if (DownloadStatus.neterror.equals(downloadEntity.getStatus())
|| DownloadStatus.timeout.equals(downloadEntity.getStatus())) {
DownloadNotification.showWaitingNotification(MainActivity.this); // 系统通知
toast("网络不稳定,下载任务已暂停");
DataLogUtils.uploadNeterrorLog(MainActivity.this, downloadEntity);
MtaHelper.onEventWithBasicDeviceInfo("下载自动暂停",
"游戏", downloadEntity.getName(),
"平台", downloadEntity.getPlatform());
}
if (DownloadStatus.done.equals(downloadEntity.getStatus())) {
if (downloadEntity.getName().contains(getString(R.string.app_name))) {
DataUtils.onEvent(MainActivity.this, "软件更新", "下载完成");
startActivity(PackageUtils.getInstallIntent(MainActivity.this, downloadEntity.getPath()));
DataLogUtils.uploadUpgradeLog(MainActivity.this, "install"); //上传更新安装数据
} else {
statDoneEvent(downloadEntity);
String platform = PlatformUtils.getInstance(getApplicationContext())
.getPlatformName(downloadEntity.getPlatform());
if (platform != null) {
if (downloadEntity.isPluggable()) {
// 弹出插件化提示框
EventBus.getDefault().post(new EBShowDialog("plugin", downloadEntity.getPath()));
} else if (downloadEntity.isPlugin()) {
toast(downloadEntity.getName() + " - " + platform + " - 下载完成");
} else {
toast(downloadEntity.getName() + " - 下载完成");
}
} else {
toast(downloadEntity.getName() + " - 下载完成");
}
if (!downloadEntity.isPluggable()) {
// 是否是自动安装
if (sp.getBoolean("autoinstall", true)) {
if (FileUtils.isEmptyFile(downloadEntity.getPath())) {
toast(R.string.install_failure_hint);
DownloadManager.getInstance(MainActivity.this).cancel(downloadEntity.getUrl());
} else {
if (PackageUtils.isCanLaunchSetup(getApplicationContext(), downloadEntity.getPath())) {
startActivity(PackageUtils.getInstallIntent(MainActivity.this, downloadEntity.getPath()));
} else {
// 弹出卸载提示框
EventBus.getDefault().post(new EBShowDialog("plugin", downloadEntity.getPath()));
}
}
}
}
// 统计下载完成
uploadData(downloadEntity.getGameId(), downloadEntity.getPlatform());
}
// 下载过程分析统计
android.content.pm.PackageManager pm = getApplicationContext().getPackageManager();
PackageInfo packageInfo = pm.getPackageArchiveInfo(downloadEntity.getPath(), android.content.pm.PackageManager.GET_ACTIVITIES);
if (packageInfo == null) {
MtaHelper.onEventWithBasicDeviceInfo("解析包错误分析"
, "游戏名字", downloadEntity.getName() + ":"
+ PlatformUtils.getInstance(getApplicationContext()).getPlatformName(downloadEntity.getPlatform()));
MtaHelper.onEventWithBasicDeviceInfo(
"解析包错误_新",
"游戏", downloadEntity.getName() + ":" + PlatformUtils.getInstance(getApplicationContext()).getPlatformName(downloadEntity.getPlatform()));
}
}
}
};
/*
* 黄壮华 按连续按返回键两次才退出应用
*/
private long[] mHits = new long[2];
@NonNull
public static Intent getMainIntent(Context context) {
Intent intent = new Intent(context, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
return intent;
}
// 统计下载
private void uploadData(String id, String platform) {
Map<String, String> params = new HashMap<>();
params.put("game", id);
params.put("platform", platform);
RequestBody body = RequestBody.create(MediaType.parse("application/json"),
new JSONObject(params).toString());
RetrofitManager.getInstance(this).getApi().postDownload(body)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<ResponseBody>());
}
// 统计下载完成事件
private void statDoneEvent(DownloadEntity downloadEntity) {
ExposureUtils.DownloadType type;
String platform = PlatformUtils.getInstance(HaloApp.getInstance().getApplication()).getPlatformName(downloadEntity.getPlatform());
Map<String, Object> kv1 = new HashMap<>();
kv1.put("版本", platform);
kv1.put("状态", "下载完成");
kv1.put("用户机型", Build.MODEL);
kv1.put("设备IMEI", Util_System_Phone_State.getDeviceId(HaloApp.getInstance().getApplication()));
kv1.put("网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
kv1.put("光环助手版本", BuildConfig.VERSION_NAME);
if (downloadEntity.isUpdate()) {
type = ExposureUtils.DownloadType.UPDATE;
DataUtils.onEvent(MainActivity.this, "游戏更新", downloadEntity.getName(), kv1);
} else {
type = ExposureUtils.DownloadType.DOWNLOAD;
}
Map<String, Object> kv2 = new HashMap<>();
kv2.put("版本", downloadEntity.getPlatform());
kv2.put("状态", "下载完成");
kv2.put("位置", downloadEntity.getEntrance());
kv2.put("游戏分平台", downloadEntity.getName() + "-" + platform);
kv2.put("光环助手版本", BuildConfig.VERSION_NAME);
DataUtils.onEvent(MainActivity.this, "游戏下载位置", downloadEntity.getName(), kv2);
if (downloadEntity.isPluggable()) {
Map<String, Object> kv3 = new HashMap<>();
kv3.put("下载", "下载完成");
kv3.put("版本", downloadEntity.getPlatform());
kv3.put("位置", downloadEntity.getEntrance());
type = ExposureUtils.DownloadType.PLUGIN_DOWNLOAD;
DataUtils.onEvent(MainActivity.this, "插件化", downloadEntity.getName(), kv3);
DataUtils.onMtaEvent(this,
"插件化_新",
"位置", downloadEntity.getEntrance(),
"游戏", downloadEntity.getName() + "-" + downloadEntity.getPlatform(),
"操作", "下载完成",
"网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
}
ExposureUtils.logADownloadCompleteExposureEvent(new GameEntity(downloadEntity.getGameId()), downloadEntity.getPlatform(), downloadEntity.getExposureTrace(), type);
DataCollectionUtils.uploadDownload(this, downloadEntity, "完成");
}
private void processHijack(DownloadEntity downloadEntity) {
// 删除任务
downloadEntity.setStatus(DownloadStatus.cancel);
DownloadManager.getInstance(getApplicationContext()).cancel(downloadEntity.getUrl());
// 弹出提示框
EventBus.getDefault().post(new EBShowDialog("hijack"));
// 记录链接被劫持
DataCollectionUtils.uploadHijack(this, downloadEntity);
// 上传劫持log
DataLogUtils.uploadHijack(this, downloadEntity);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
DownloadEntity downloadEntity = null;
for (DownloadEntity entity : DownloadManager.getInstance(getApplicationContext()).getAll()) {
if (entity.getStatus().equals(DownloadStatus.done)) {
if (PackageUtils.isInstalled(getApplicationContext(), entity.getPackageName())
&& (!entity.isPlugin()
|| PackageUtils.isSignature(getApplicationContext(), entity.getPackageName()))) {
continue;
}
if (downloadEntity == null) {
downloadEntity = entity;
} else if (entity.getEnd() > downloadEntity.getEnd()) {
downloadEntity = entity;
}
}
}
if (downloadEntity != null) {
String msg;
if (downloadEntity.isPlugin()) {
msg = "" + downloadEntity.getName() + "-"
+ PlatformUtils.getInstance(getApplicationContext()).getPlatformName(downloadEntity.getPlatform())
+ "》已下载完但还未安装,是否立即安装?";
} else {
msg = "" + downloadEntity.getName() + "》已下载完但还未安装,是否立即安装?";
}
final String path = downloadEntity.getPath();
DialogUtils.showWarningDialog(this,
"提示", msg,
"直接退出",
"立即安装",
() -> handler.postDelayed(() -> PackageUtils.launchSetup(MainActivity.this, path), 200),
this::finish);
return true;
}
System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1);
mHits[mHits.length - 1] = SystemClock.uptimeMillis();
if (mHits[0] >= (SystemClock.uptimeMillis() - 1000)) {
finish();
} else {
toast("再按一次就退出光环助手了哦");
return true;
}
}
return super.onKeyDown(keyCode, event);
}
@Override
public void finish() {
// 上传数据
DataCollectionManager.getInstance(getApplicationContext()).statClickData();
super.finish();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("isSkipped", isSkipped);
if (mMainWrapperFragment != null) {
outState.putInt(BaseFragment_ViewPager.ARGS_INDEX, mMainWrapperFragment.getCurrentItem());
}
}
@Override
protected int getLayoutId() {
return R.layout.layout_wrapper_activity;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SKIP_SETTING_REQUEST) {
List<PackageInfo> installedList = getPackageManager().getInstalledPackages(0);
if (installedList.isEmpty()) {
toast("读取应用列表失败");
} else {
getInstalledListFromServer();
}
}
}
// 获取已安装游戏
private void getInstalledListFromServer() {
ArrayList<String> list = PackageUtils.getAllPackageName(getApplicationContext());
PackageManager.INSTANCE.initData(list);
// 忽略 xposed 安装器
list.remove(Constants.XPOSED_INSTALLER_PACKAGE_NAME);
//应用上报
uploadAppList();
// 过滤助手收录的包
ArrayList<String> localList = new ArrayList<>();
FilterManager filterManager = new FilterManager(this);
for (int i = 0, size = list.size(); i < size; i++) {
if (filterManager.isFilter(list.get(i))) {
localList.add(list.get(i));
}
}
final CountDownLatch latch = ObservableUtil.latch(localList.size(), o -> updateInstall(), new Object());
for (int i = 0, size = localList.size(); i < size; i++) {
final String packageName = localList.get(i);
RetrofitManager.getInstance(this).getApi().getGameDigestByPackageName(UrlFilterUtils.getFilterQuery("package", packageName))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<List<GameDigestEntity>>() {
@Override
public void onResponse(List<GameDigestEntity> response) {
for (GameDigestEntity gameDigestEntity : response) {
GameInfo gameInfo = new GameInfo();
gameInfo.setId(gameDigestEntity.getId());
gameInfo.setGameIcon(gameDigestEntity.getIcon());
gameInfo.setPackageName(packageName);
gameInfo.setGameName(gameDigestEntity.getName());
mInstallManager.updateByEntity(gameInfo);
}
latch.countDown();
}
@Override
public void onFailure(HttpException e) {
latch.countDown();
}
});
}
}
private void uploadAppList() {
//检查是否符合应用上报周期
long time = sp.getLong("last_upload_applist_time", 0);
if (Utils.getTime(this) - time >= 604800L) {//一周为一个周期
DataCollectionUtils.uploadAppList(this, PackageUtils.getAppList(this));
}
}
/**
* 为已安装的游戏添加助手后台存在的包
*/
private void updateInstall() {
ArrayList<String> concernIdList = new ArrayList<>();
for (InstallInfo entity : mInstallManager.getAllInstall()) {
concernIdList.add(entity.getId());
}
if (concernIdList.isEmpty()) {
update();
} else {
List<Observable<GameEntity>> sequences = new ArrayList<>();
for (String id : concernIdList) {
sequences.add(RetrofitManager.getInstance(this).getApi().getGameDigest(id));
}
Observable.mergeDelayError(sequences)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<GameEntity>() {
@Override
public void onNext(GameEntity response) {
InstallInfo installInfo = mInstallManager.findInstallById(response.getId());
if (installInfo != null && response.getApk().size() != 0) {
HashMap<String, Boolean> packageNames = new HashMap<>();
for (ApkEntity apkEntity : response.getApk()) {
if (PackageManager.INSTANCE.isInstalled(apkEntity.getPackageName())) {
packageNames.put(apkEntity.getPackageName(), true);
} else {
packageNames.put(apkEntity.getPackageName(), false);
}
}
installInfo.setTime(System.currentTimeMillis());
installInfo.setPackageNames(packageNames);
mInstallManager.updateInstall(installInfo);
}
}
@Override
public void onFailure(@Nullable HttpException e) {
update();
}
@Override
public void onComplete() {
update();
}
});
}
}
/**
* 更新安装列表数据
*/
private void update() {
HaloApp.getInstance().getMainExecutor().execute(() -> {
final List<String> installed = new ArrayList<>();
TrafficUtils spy = TrafficUtils.getInstance(getApplicationContext(), true);
List<InstallInfo> concernList = mInstallManager.getAllInstall();
for (InstallInfo concernEntity : concernList) {
concernEntity.setTime(System.currentTimeMillis());
int quantity = 0;
HashMap<String, Boolean> packageNames = new HashMap<>();
for (String packageName : concernEntity.getPackageNames().keySet()) {
if (PackageManager.INSTANCE.isInstalled(packageName)) {
quantity++;
packageNames.put(packageName, true);
installed.add(packageName);
} else {
packageNames.put(packageName, false);
}
}
concernEntity.setPackageNames(packageNames);
concernEntity.setInstalledQuantity(quantity);
int weight = 0;
long traffic = spy.getTraffic(new ArrayList<>(concernEntity.getPackageNames().keySet()));
concernEntity.setTraffic(traffic);
if (traffic > 0) {
weight++;
}
concernEntity.setWeight(weight);
mInstallManager.updateInstall(concernEntity);
}
// 更新用户已安装游戏
RequestBody body = RequestBody.create(MediaType.parse("application/json"),
new JSONArray(installed).toString());
RetrofitManager.getInstance(MainActivity.this).getApi().putPackage(UserManager.getInstance().getUserId(), body)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new Response<ResponseBody>());
handler.postDelayed(() -> DataCollectionUtils.uploadUser(MainActivity.this), 1000);
// 检查游戏更新
checkGameUpdate();
// 检查可插件化游戏
checkGamePlugin();
});
}
private void checkGameUpdate() {
List<InstallInfo> infos = mInstallManager.getAllInstall();
ArrayList<String> packageList = PackageUtils.getAllPackageName(this);
for (InstallInfo info : infos) {
for (String packageName : info.getPackageNames().keySet()) {
if (info.getPackageNames().get(packageName)
&& packageList.contains(packageName)) {
checkGameUpdate(packageName);
}
}
}
}
private void checkGamePlugin() {
final List<GameEntity> list = new ArrayList<>();
List<Observable<GameEntity>> sequences = new ArrayList<>();
for (InstallInfo info : mInstallManager.getAllInstall()) {
sequences.add(RetrofitManager.getInstance(this).getApi().getGameDigest(info.getId()));
}
Observable.mergeDelayError(sequences)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<GameEntity>() {
@Override
public void onNext(GameEntity response) {
list.add(response);
}
@Override
public void onFailure(@Nullable HttpException e) {
processPluginData(list);
}
@Override
public void onComplete() {
processPluginData(list);
}
});
}
private void checkGameUpdate(String packageName) {
Object gh_id = PackageUtils.getMetaData(this, packageName, "gh_id");
Observable<GameEntity> observable;
if (gh_id == null) {
observable = RetrofitManager.getInstance(this).getApi().getGameUpdate(UrlFilterUtils.getFilterQuery("packages", packageName));
} else {
observable = RetrofitManager.getInstance(this).getApi().getGameUpdateById((String) gh_id);
}
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<GameEntity>() {
@Override
public void onResponse(GameEntity response) {
List<GameUpdateEntity> updateList = PackageUtils.isCanUpdate(getApplication(), response);
if (updateList.size() > 0) {
PackageManager.INSTANCE.addUpdateList(updateList);
}
}
});
}
private void processPluginData(List<GameEntity> list) {
if (list == null || list.isEmpty()) {
return;
}
List<InstallInfo> infos = mInstallManager.getAllInstall();
HashMap<String, Boolean> map;
for (InstallInfo info : infos) {
for (GameEntity gameEntity : list) {
if (gameEntity.getId().equals(info.getId())
&& gameEntity.getTag() != null && gameEntity.getTag().size() != 0
&& gameEntity.getApk() != null) {
map = info.getPackageNames();
for (String key : map.keySet()) {
if (map.get(key)) {
for (ApkEntity apkEntity : gameEntity.getApk()) {
if (apkEntity.getPackageName().equals(key)
&& !TextUtils.isEmpty(apkEntity.getGhVersion())
&& !PackageUtils.isSignature(this, apkEntity.getPackageName())) {
PackageManager.INSTANCE.addUpdate(GameUtils.getGameUpdateEntity(gameEntity, apkEntity));
break;
}
}
GameManager manager = new GameManager(this);
manager.addOrUpdate(gameEntity);
}
}
break;
}
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 上传数据
DataCollectionManager.getInstance(getApplicationContext()).upload();
sp = PreferenceManager.getDefaultSharedPreferences(this);
isNewFirstLaunch = sp.getBoolean("isNewFirstLaunchV" + PackageUtils.getVersionName(), true);
isSkipped = false;
if (savedInstanceState != null) {
isSkipped = savedInstanceState.getBoolean("isSkipped");
}
mMainWrapperFragment = new MainWrapperFragment();
if (savedInstanceState != null) {
mMainWrapperFragment.setArguments(savedInstanceState);
} else if (getIntent() != null) {
Bundle extras = getIntent().getExtras();
mMainWrapperFragment.setArguments(extras);
}
replaceFragment(mMainWrapperFragment);
mInstallManager = new InstallManager(getApplicationContext());
// 检查助手更新
UpdateManager.getInstance(this).checkUpdate(true, null);
if (isNewFirstLaunch) {
LogUtils.uploadDevice(DeviceTokenUtils.getLaunchType());
getPluginUpdate();
sp.edit().putBoolean("isNewFirstLaunchV" + PackageUtils.getVersionName(), false).apply();
checkDevice(); // 根据设备信息判断用户是否是新用户
}
// 获取默认配置
getGhzsSettings();
// 初始化PlatformUtils
PlatformUtils.getInstance(getApplicationContext());
// 添加观察者
DownloadManager.getInstance(this).addObserver(dataWatcher);
// 检查是否有权限读取应用列表
checkPermission();
final String message = Config.getExceptionMsg(this);
if (!TextUtils.isEmpty(message)) {
Config.setExceptionMsg(this, null);
AppUncaughtHandler.reportException(this, new Throwable(message));
DialogUtils.showWarningDialog(this, "发生闪退", "光环助手刚刚发生了闪退,马上反馈以帮助我们更好地修复问题?(只需简单描述你刚才的操作)"
, "暂不", "马上反馈",
() -> {
SuggestionActivity.startSuggestionActivity(MainActivity.this, SuggestType.crash, "APP闪退");
MtaHelper.onEventWithBasicDeviceInfo(
"闪退弹窗",
"玩家操作", "点击反馈");
},
() -> MtaHelper.onEventWithBasicDeviceInfo(
"闪退弹窗",
"玩家操作", "点击关闭"));
}
checkTinkerPath();
checkRetryDownload();
// 初始化 IM只有在 APP 刚启动时执行
if (HaloApp.get(SHOULD_INIT_IM, false) != null) {
HaloApp.put(SHOULD_INIT_IM, false);
handler.postDelayed(ImManager::attachIm, 1000);
}
// 获取可用(没有被隐藏的)的社区列表
CommunityHelper.getAvailableCommunityList();
handler.postDelayed(this::switchToCommunityTabAndRefresh, 800);
// 执行跳转事件
handler.postDelayed(skipRun, 500);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
switchToCommunityTabAndRefresh();
}
private void switchToCommunityTabAndRefresh() {
// 跳转到问答社区并刷新
if (getIntent().getBooleanExtra(SWITCH_TO_COMMUNITY, false)) {
getIntent().putExtra(SWITCH_TO_COMMUNITY, false);
Log.e("Switch", "true");
EventBus.getDefault().post(new EBSkip(MainActivity.EB_SKIP_GAMEFRAGMENT, 1));
EventBus.getDefault().post(new EBReuse(AskFragment.EB_RETRY_PAGE));
}
}
private void getGhzsSettings() {
String channel = HaloApp.getInstance().getChannel();
RetrofitManager.getInstance(this)
.getApi().getSettings(PackageUtils.getVersionName(), channel)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<SettingsEntity>() {
@Override
public void onResponse(SettingsEntity response) {
Config.setSettings(response);
// 意见反馈
SharedPreferences.Editor edit = sp.edit();
edit.putString(SuggestionActivity.SUGGESTION_HINT_TYPE,
GsonUtils.Companion.getInstance().toJson(response.getSuggestion()));
edit.apply();
if (!sp.getBoolean("isFixDownload", false) && Config.isShow()) {
sp.edit().putBoolean("isFixDownload", true).apply();
}
EventBus.getDefault().post(new EBReuse("Refresh"));
}
});
}
private void checkRetryDownload() {
if (!NetworkUtils.isWifiConnected(this)) return;
for (DownloadEntity downloadEntity : DownloadManager.getInstance(this).getAll()) {
if (DownloadStatus.neterror.equals(downloadEntity.getStatus()) ||
DownloadStatus.timeout.equals(downloadEntity.getStatus()) ||
DownloadStatus.subscribe.equals(downloadEntity.getStatus())) {
DownloadManager.getInstance(this).put(downloadEntity.getUrl(), System.currentTimeMillis());
Message msg = Message.obtain();
msg.what = DownloadConfig.CONTINUE_DOWNLOAD_TASK;
msg.obj = downloadEntity.getUrl();
DownloadManager.getInstance(getApplicationContext()).sendMessageDelayed(msg, 1000);
}
Utils.log("checkRetryDownload::" + downloadEntity.getStatus());
}
}
private void checkTinkerPath() {
CommonDebug.logMethodWithParams(this, TinkerManager.getTinkerId(), TinkerManager.getNewTinkerId());
CommonDebug.logMethodWithParams(this, CrashReport.getAppVer(), CrashReport.getAppID(), CrashReport.getAppChannel(), CrashReport.getSdkExtraData());
// 1.母包首次启动tinkerId不为空newTinkerId(patchTinkerId)应该是空的
// 2. 补丁包启动tinkerId和之前一致但newTinkerId不一致
// 2.1 显示更新信息弹窗记录tinkerId+newTinkerId
// 2.1.1 若tinkerId一致但newTinkerId不一致才能认为是一次补丁更新
String tinkerId = TinkerManager.getTinkerId();
String newTinkerId = TinkerManager.getNewTinkerId();
if (TextUtils.isEmpty(newTinkerId)) {
//这是一个新的母包,没有任何补丁信息
return;
}
final Gson gson = new Gson();
Type type = new TypeToken<HashMap<String, Set<String>>>() {
}.getType();
final Map<String, Set<String>> tinkerIdMap;
final String tinkerMapJson = sp.getString(Config.PATCHES, "");
if (!TextUtils.isEmpty(tinkerMapJson)) {
tinkerIdMap = gson.fromJson(tinkerMapJson, type);
} else {
tinkerIdMap = new HashMap<>();
}
Set<String> tinkerIdSet = tinkerIdMap.get(tinkerId);
if (tinkerIdSet == null) {
tinkerIdSet = new HashSet<>();
tinkerIdMap.put(tinkerId, tinkerIdSet);
}
// 有新的补丁,没有显示过
if (!tinkerIdSet.contains(newTinkerId)) {
tinkerIdSet.add(newTinkerId);
final Dialog dialog = new Dialog(this, R.style.GhAlertDialog);
View contentView = LayoutInflater.from(this).inflate(R.layout.dialog_alert, null);
TextView contentTv = contentView.findViewById(R.id.dialog_content);
TextView titleTv = contentView.findViewById(R.id.dialog_title);
TextView negativeTv = contentView.findViewById(R.id.dialog_negative);
TextView positiveTv = contentView.findViewById(R.id.dialog_positive);
titleTv.setText("补丁更新成功");
contentTv.setText("光环助手已成功更新到V" + PackageUtils.getPatchVersionName());
positiveTv.setText("知道了");
negativeTv.setText(null);
negativeTv.setOnClickListener(view -> dialog.dismiss());
positiveTv.setOnClickListener(view -> dialog.dismiss());
dialog.setOnDismissListener(dialog1 -> sp.edit().putString(Config.PATCHES, gson.toJson(tinkerIdMap)).apply());
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
DownloadManager.getInstance(this).removeObserver(dataWatcher);
handler.removeCallbacksAndMessages(null);
}
private void checkDevice() {
String content = DeviceUtils.getUserDevice(MainActivity.this).toString();
RequestBody body = RequestBody.create(MediaType.parse("application/json"), content);
RetrofitManager.getInstance(this).getApi().checkDevice(body)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<ResponseBody>() {
@Override
public void onResponse(ResponseBody response) {
super.onResponse(response);
try {
String string = response.string();
JSONObject object = new JSONObject(string);
String deviceId = object.getString("device_id");
if (!TextUtils.isEmpty(deviceId)) {
oldUserSkip(deviceId);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void oldUserSkip(String deviceId) {
sp.edit().putString("syncDeviceID", deviceId).apply();
DialogUtils.showForceDialog(MainActivity.this, "数据同步提醒"
, "系统检测到你是光环助手的老用户,为了避免数据丢失,请尽快登录"
, "前往登录", "残忍拒绝", new DialogUtils.ConfirmListener() {
@Override
public void onConfirm() {
EventBus.getDefault().post(new EBSkip(MainActivity.EB_SKIP_GAMEFRAGMENT, INDEX_PERSONAL));
}
}, null);
}
private void checkPermission() {
List<PackageInfo> installedList = getPackageManager().getInstalledPackages(0);
if (installedList.isEmpty()) {
// 无权限获取应用列表
Spanned content = Html.fromHtml("请前往系统权限设置,把“" +
"<font color='#ff0000'>读取应用列表</font>”选择为打开" +
"“<font color='#ff0000'>允许</font>”,否则光环助手将无法帮您安装插件加速版的游戏");
DialogUtils.showWarningDialog(this, "提示", content, "忽略", "去开启",
() -> {
// 跳转应用信息界面
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, SKIP_SETTING_REQUEST);
}, null);
} else {
getInstalledListFromServer();
}
}
// 获取META-INF中的plugin_update 文件判断是否从游戏插件中下载的app是则获取游戏id启动游戏更新下载该游戏
private void getPluginUpdate() {
HaloApp.getInstance().getMainExecutor().execute(() -> {
ApplicationInfo appinfo = getApplicationInfo();
String sourceDir = appinfo.sourceDir;
ZipFile zipfile = null;
try {
zipfile = new ZipFile(sourceDir);
Enumeration<?> entries = zipfile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = ((ZipEntry) entries.nextElement());
String entryName = entry.getName();
if (entryName.contains("gh_assist")) { // TODO: 20/09/17 统一入口
String packageName = entryName.substring(entryName.lastIndexOf("_") + 1);
Intent intent = new Intent(MainActivity.this, DownloadManagerActivity.class);
intent.putExtra("currentItem", 1);
intent.putExtra("packageName", packageName);
intent.putExtra(EntranceUtils.KEY_ENTRANCE, "(游戏插件)");
startActivity(intent);
break;
} else if (entryName.contains("halo_skip.json")) {
InputStream in = zipfile.getInputStream(entry);
if (in != null) {
final Gson gson = new Gson();
final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
InnerMetaInfoEntity info = gson.fromJson(reader, InnerMetaInfoEntity.class);
if (info != null) {
if (EntranceUtils.HOST_COMMUNITY.equals(info.getType())) {
openCommunityWithDefaultIdForTheFirsTime = true;
UserManager.getInstance().setCommunityData(new CommunityEntity(info.getLink(), info.getText()));
runOnUiThread(() -> mMainWrapperFragment.setCurrentItem(MainWrapperFragment.INDEX_ASK));
} else {
DirectUtils.directToSpecificPage(this,
info.getType(),
info.getLink(),
info.getText(),
EntranceUtils.KEY_PLUGIN,
"特定包启动跳转");
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (zipfile != null) {
try {
zipfile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
}
// 连接上网络事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(EBNetworkState busNetworkState) {
if (busNetworkState.isNetworkConnected()) {
checkRetryDownload();
if (Config.getSettings() == null) {
getGhzsSettings();
}
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(EBPackage busFour) {
final String packageName = busFour.getPackageName();
DownloadEntity mDownloadEntity = null;
for (DownloadEntity downloadEntity : DownloadManager.getInstance(getApplicationContext()).getAll()) {
if (packageName.equals(downloadEntity.getPackageName())) {
mDownloadEntity = downloadEntity;
break;
}
}
if ("安装".equals(busFour.getType())) {
// 删除下载完成 弹窗
NotificationManager nManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nManager.cancel(packageName.hashCode());
// 添加进已安装map中
PackageManager.INSTANCE.addInstalled(packageName);
if (mDownloadEntity != null) {
if (mDownloadEntity.isPluggable()) {
Map<String, Object> kv6 = new HashMap<>();
kv6.put("安装或卸载", "安装完成");
DataUtils.onEvent(this, "插件化", mDownloadEntity.getName(), kv6);
DataUtils.onMtaEvent(this,
"插件化_新",
"位置", mDownloadEntity.getEntrance(),
"游戏", mDownloadEntity.getName() + "-" + mDownloadEntity.getPlatform(),
"操作", "安装完成",
"网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
}
DownloadManager.getInstance(getApplicationContext()).cancel(
mDownloadEntity.getUrl(), false); // 默认不删除安装包 sp.getBoolean("autodelete", true)
}
GameManager gameManager = new GameManager(getApplicationContext());
GameInfo gameInfo = gameManager.findGame(packageName);
if (gameInfo != null) {
mInstallManager.updateByEntity(gameInfo);
}
if (sp.getBoolean("concerngame", true)) { //设置页面控制是否安装后自动关注
// 安装后关注游戏
DownloadEntity finalDownloadEntity = mDownloadEntity;
RetrofitManager.getInstance(this).getApi().getGameDigestByPackageName(UrlFilterUtils.getFilterQuery("package", packageName))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<List<GameDigestEntity>>() {
@Override
public void onResponse(List<GameDigestEntity> response) {
for (GameDigestEntity gameDigestEntity : response) {
concernGame(gameDigestEntity.getId(), packageName);
if (!TextUtils.isEmpty(gameDigestEntity.getId())) { // 关注游戏
if (finalDownloadEntity != null && gameDigestEntity.getId().equals(finalDownloadEntity.getGameId())) {
ConcernUtils.INSTANCE.postConcernGameId(MainActivity.this, gameDigestEntity.getId(), null);
}
}
}
if (PackageUtils.getMetaData(getApplicationContext(),
packageName, "gh_version") != null) {
checkGameUpdate(packageName);
}
// 更新已安装游戏
RetrofitManager.getInstance(MainActivity.this).getApi()
.postPackage(UserManager.getInstance().getUserId(), packageName)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new Response<ResponseBody>());
}
});
}
}
if ("卸载".equals(busFour.getType())) {
// 删除map中数据
PackageManager.INSTANCE.removeInstalled(packageName);
if (mDownloadEntity != null && mDownloadEntity.isPluggable()) {
Map<String, Object> kv6 = new HashMap<>();
kv6.put("安装或卸载", "卸载完成");
DataUtils.onEvent(this, "插件化", mDownloadEntity.getName(), kv6);
DataUtils.onMtaEvent(this,
"插件化_新",
"位置", mDownloadEntity.getEntrance(),
"游戏", mDownloadEntity.getName() + "-" + mDownloadEntity.getPlatform(),
"操作", "卸载完成",
"网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
startActivity(PackageUtils.getInstallIntent(this, mDownloadEntity.getPath()));
}
FilterManager filterManager = new FilterManager(getApplicationContext());
if (filterManager.isFilter(packageName)) {
mInstallManager.updateByPackageName(packageName);
}
// 更新已安装游戏
RetrofitManager.getInstance(this).getApi()
.deletePackage(UserManager.getInstance().getUserId(), packageName)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(new Response<ResponseBody>());
}
if ("卸载".equals(busFour.getType()) || "安装".equals(busFour.getType())) {
PackageManager.INSTANCE.removeUpdate(packageName);
}
DataCollectionUtils.uploadInorunstall(this, busFour.getType(), busFour.getPackageName());
}
private void concernGame(final String id, final String packageName) {
RetrofitManager.getInstance(this).getApi().getGameDigest(id)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<GameEntity>() {
@Override
public void onResponse(GameEntity response) {
GameManager manager = new GameManager(getApplicationContext());
manager.addOrUpdate(response);
// 检查是否能插件化
if (response.getTag() != null && response.getTag().size() != 0) {
for (ApkEntity apkEntity : response.getApk()) {
if (packageName.equals(apkEntity.getPackageName())
&& !TextUtils.isEmpty(apkEntity.getGhVersion())
&& !PackageUtils.isSignature(getApplicationContext(), apkEntity.getPackageName())) {
PackageManager.INSTANCE.addUpdate(GameUtils.getGameUpdateEntity(response, apkEntity));
break;
}
}
}
}
});
}
// 接收登录和登出更新事件统计的 Meta
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(EBReuse reuse) {
if (reuse.getType().equals(LOGIN_TAG) || reuse.getType().equals(LOGOUT_TAG)) {
MetaUtil.INSTANCE.refreshMeta();
}
}
}