Compare commits

...

12 Commits

Author SHA1 Message Date
69e248b389 版本更改为 4.5.3 2020-12-24 11:12:37 +08:00
43f6bfc4c2 Merge branch 'hotfix-v4.5.2-252-updateLogic' into 'release'
Hotfix v4.5.2 252 update logic

See merge request halo/assistant-android!52
2020-12-24 11:09:56 +08:00
c8b81ab56a 优化模拟器游戏在下载按钮中的判断逻辑 2020-12-24 11:08:34 +08:00
aa41fd98e8 重置下载按钮的文字显示优先级 2020-12-24 10:49:49 +08:00
ee8ce87e28 Merge branch 'hotfix-v4.5.2-252-crash' into 'release'
处理一些数组越界闪退

See merge request halo/assistant-android!51
2020-12-23 10:58:40 +08:00
a944a7f730 处理一些数组越界闪退 2020-12-23 10:55:37 +08:00
165ba01afd Merge branch 'hotfix-v4.5.2-252-crash' into 'release'
修复v4.5.2版本闪退问题

See merge request halo/assistant-android!50
2020-12-21 16:36:23 +08:00
a39a8c2cce 1.修复视频流滑动闪退问题 2.修复WebView闪退问题 2020-12-21 16:02:00 +08:00
e4765089fa Merge branch 'hotfix-v4.5.2-252-genericCrash' into 'release'
修复一些空指针和数组越界闪退

See merge request halo/assistant-android!49
2020-12-21 11:23:06 +08:00
721e73ca1e Merge branch 'hotfix-v4.5.2-252-sentry' into 'release'
缩窄 Sentry ANR 的上报条件避免日志轰炸

See merge request halo/assistant-android!48
2020-12-21 11:19:15 +08:00
e406c90027 修复一些空指针和数组越界闪退 2020-12-21 11:17:34 +08:00
e7c4886219 缩窄 Sentry ANR 的上报条件避免日志轰炸 2020-12-21 10:15:20 +08:00
19 changed files with 87 additions and 47 deletions

View File

@ -20,7 +20,12 @@ class VolumeObserver(var context: Context, handler: Handler, var callback: MuteC
super.onChange(selfChange)
val audio = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
val currentVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC)
var currentVolume = 0
tryCatchInRelease {
// 部分设备(Meizu 7.1.2 M6 Note)的 audioManager getStreamVolume 内部会触发空指针 :(
currentVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC)
}
val delta = previousVolume - currentVolume

View File

@ -33,7 +33,7 @@ object SimulatorGameManager {
@JvmStatic
fun deleteLocalGames(names: List<String>) {
val downloadEntityList = DownloadDao.getInstance(HaloApp.getInstance().application).all
val downloadEntityList = DownloadManager.getInstance(HaloApp.getInstance().application).allDownloadEntity
names.forEach { name ->
val downloadEntity = downloadEntityList.find { it.name == name }
if (downloadEntity != null) {
@ -48,7 +48,7 @@ object SimulatorGameManager {
@JvmStatic
fun deleteLocalGame(name: String) {
val downloadEntityList = DownloadDao.getInstance(HaloApp.getInstance().application).all
val downloadEntityList = DownloadManager.getInstance(HaloApp.getInstance().application).allDownloadEntity
val downloadEntity = downloadEntityList.find { it.name == name }
if (downloadEntity != null) {
val file = File(downloadEntity.path)

View File

@ -42,6 +42,15 @@ public class DataUtils {
}
SentryAndroid.init(context, options -> {
// Sentry 疯狂报 ANR (很大一部分还是莫名奇妙的 ANR)严重影响到其它闪退日志的收集
// 这里将它局限到只有官网渠道的包才统计 ANR
if ("GH_206".equals(channel)) {
options.setAnrEnabled(true);
options.setAnrTimeoutIntervalMillis(6000);
} else {
options.setAnrEnabled(false);
}
options.setDebug(BuildConfig.DEBUG);
options.setEnableSessionTracking(true);
options.setEnvironment(BuildConfig.FLAVOR);
@ -57,10 +66,6 @@ public class DataUtils {
});
Sentry.configureScope(scope -> {
User user = new User();
user.setId(HaloApp.getInstance().getGid());
scope.setUser(user);
if (BuildConfig.BUILD_TIME != 0L) {
scope.setTag("alias", "内测版" + BuildConfig.VERSION_NAME + "_" + BuildConfig.BUILD_TIME);
} else {

View File

@ -78,6 +78,9 @@ public class GameUtils {
int pluginCount = 0; // 可插件化数量
int updateCount = 0; // 可更新数量
int installCount = 0; // 已安装数量
boolean isRelatedEmulatorInstalled = false; // 若该游戏是模拟器游戏时其对应的模拟器是否已经安装
DownloadEntity downloadEntity;
Object gh_id;
apkFor:
@ -123,20 +126,26 @@ public class GameUtils {
boolean isInstalled = PackageUtils.isInstalledFromAllPackage(context, gameEntity.getSimulator().getApk().getPackageName());
if (isInstalled) {
installCount++;
isRelatedEmulatorInstalled = true;
} else {
doneCount++;
}
}
}
}
if (installCount != 0) {
if (isRelatedEmulatorInstalled && doneCount != 0) {
return context.getString(R.string.launch);
}
if (doneCount != 0) {
return context.getString(R.string.install);
} else if (pluginCount != 0 && !SimulatorGameManager.isSimulatorGame(gameEntity)) {
return context.getString(R.string.pluggable);
} else if (updateCount != 0 && !SimulatorGameManager.isSimulatorGame(gameEntity)) {
return context.getString(R.string.update);
} else if (doneCount != 0) {
return context.getString(R.string.install);
} else if (installCount != 0) {
return context.getString(R.string.launch);
} else if (gameEntity.getVersionNumber().contains("无版号") && Config.isGameDomeSwitchOpen() && !SimulatorGameManager.isSimulatorGame(gameEntity)) {
return context.getString(R.string.attempt);
} else {

View File

@ -183,16 +183,13 @@ public class PackageUtils {
return null;
}
// TODO 找一个更好的办法来比较签名并且不触发 ANR
public static boolean compareSignatureBetweenInstalledAppWithApk(Context context, String packageName, String apkFilePath) {
try {
// 统计签名比较使用的频率 (大文件会触发 ANR)
SentryHelper.INSTANCE.onEvent(
"SIGNATURE_COMPARE",
"packageName", packageName);
// 据 Sentry 统计,刚上架一个周末的包里对这个方法有 700+ 次调用,然后其中一部分会造成 ANR
Signature sig = context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_SIGNATURES).signatures[0];
// Fuck HUAWEI, 华为系统调用 getPackageArchiveInfo 获取魔羯 apk 的签名时会耗时超过5秒造成 ANR没有找到解决方法
// 调用 getPackageArchiveInfo 获取较大的 apk 的签名时会耗时超过5秒造成 ANR没有找到解决方法
// 如果可以的话尽量避免调用 getPackageArchiveInfo 方法
Signature releaseSig = context.getPackageManager().getPackageArchiveInfo(apkFilePath, PackageManager.GET_SIGNATURES).signatures[0];
return sig.hashCode() == releaseSig.hashCode();

View File

@ -414,7 +414,7 @@ public class DWebView extends WebView {
e.printStackTrace();
try {
super.loadUrl("javascript:" + script);
} catch (Exception ignored){
} catch (Exception ignored) {
}
}
@ -1023,4 +1023,19 @@ public class DWebView extends WebView {
mainHandler.post(runnable);
}
@Override
public void setOverScrollMode(int mode) {
try {
super.setOverScrollMode(mode);
} catch (Throwable e) {
String trace = Log.getStackTraceString(e);
if (trace.contains("android.content.pm.PackageManager$NameNotFoundException")
|| trace.contains("java.lang.RuntimeException: Cannot load WebView")
|| trace.contains("android.webkit.WebViewFactory$MissingWebViewPackageException: Failed to load WebView provider: No WebView installed")) {
e.printStackTrace();
} else {
throw e;
}
}
}
}

View File

@ -543,7 +543,7 @@ public class DownloadManager implements DownloadStatusListener {
}
public List<DownloadEntity> getAllSimulatorDownloadEntity() {
List<DownloadEntity> downloadEntityList = mDownloadDao.getAll();
List<DownloadEntity> downloadEntityList = getAllDownloadEntity();
ArrayList<DownloadEntity> filteredDownloadEntityList = new ArrayList<>();
for (DownloadEntity downloadEntity : downloadEntityList) {
if (ExtensionsKt.isSimulatorGame(downloadEntity) && downloadEntity.getStatus() == DownloadStatus.done) {
@ -560,7 +560,7 @@ public class DownloadManager implements DownloadStatusListener {
if (CommonDebug.IS_DEBUG) {
CommonDebug.logMethodName(this);
}
List<DownloadEntity> all = mDownloadDao.getAll();
List<DownloadEntity> all = getAllDownloadEntity();
return filterSilentDownloadTask(all);
}

View File

@ -300,7 +300,7 @@ public class SplashScreenActivity extends BaseActivity {
finish();
}
private void uploadTeaAndGdtData(){
private void uploadTeaAndGdtData() {
// 在可能获取了相关权限后才初始化SDK/发送激活数据
// TeaHelper.init(getApplication(), HaloApp.getInstance().getChannel());
try {
@ -422,25 +422,25 @@ public class SplashScreenActivity extends BaseActivity {
// 检查下载文件夹下是否有旧版本的光环助手的包,有则删除
@SuppressWarnings("ResultOfMethodCallIgnored")
private void deleteOutdatedUpdatePackage() {
File folder = new File(FileUtils.getDownloadDir(this) + File.separator);
if (folder.isDirectory()) {
for (File file : folder.listFiles()) {
if (!file.isDirectory() && file.getName().startsWith("光环助手V")) {
String name = file.getName();
int index = name.indexOf("_");
if (index != -1) {
try {
try {
File folder = new File(FileUtils.getDownloadDir(this) + File.separator);
if (folder.isDirectory()) {
for (File file : folder.listFiles()) {
if (!file.isDirectory() && file.getName().startsWith("光环助手V")) {
String name = file.getName();
int index = name.indexOf("_");
if (index != -1) {
String versionString = name.substring(name.indexOf("V") + 1, index);
Version currentVersion = new Version(PackageUtils.getVersionName());
if (currentVersion.isHigherThan(versionString) || currentVersion.isEqual(versionString)) {
file.delete();
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

View File

@ -20,6 +20,7 @@ public abstract class ListAdapter<DataType> extends BaseRecyclerAdapter {
public static final int FOOTER_ITEM_COUNT = 1;
public static final int TOP_ITEM_COUNT = 1;
// TODO mEntityList 适配多线程读写
protected List<DataType> mEntityList = new ArrayList<>();
protected boolean mIsOver;

View File

@ -79,6 +79,9 @@ public class GameDownloadFragment extends BaseFragment implements View.OnClickLi
@Nullable Integer location = adapter.getLocation(downloadEntity.getUrl());
String xapkStatus = downloadEntity.getMeta().get(XapkInstaller.XAPK_UNZIP_STATUS);
if (location != null && XapkUnzipStatus.UNZIPPING.name().equals(xapkStatus)) {
if (location > adapter.getDoneList().size()) return;
adapter.getDoneList().set(location, downloadEntity);
adapter.notifyItemChanged(location + 1);
return;

View File

@ -199,7 +199,7 @@ class GameDetailFragment : NormalFragment() {
if (mGameEntity != null && mGameEntity!!.getApk().size == 1) {
val url = mGameEntity!!.getApk()[0].url
if (downloadEntity.url == url) {
if ("pause" != DownloadManager.getInstance(context).getStatus(downloadEntity.url).status) {
if ("pause" != DownloadManager.getInstance(context).getStatus(downloadEntity.url)?.status) {
mDownloadEntity = downloadEntity
DetailDownloadUtils.detailInvalidate(detailViewHolder)
}
@ -282,8 +282,8 @@ class GameDetailFragment : NormalFragment() {
mMaxWidth = resources.displayMetrics.widthPixels - DisplayUtils.dip2px(40f)
val args = arguments
mAutoDownload = args!!.getBoolean(EntranceUtils.KEY_AUTO_DOWNLOAD)
val args = arguments ?: Bundle()
mAutoDownload = args.getBoolean(EntranceUtils.KEY_AUTO_DOWNLOAD)
mTraceEvent = args.getParcelable(EntranceUtils.KEY_TRACE_EVENT)
mSkipGameComment = args.getBoolean(EntranceUtils.KEY_SKIP_GAME_COMMENT)
mDestinationTab = args.getInt(EntranceUtils.KEY_TARGET, -1)

View File

@ -84,8 +84,8 @@ class FuLiFragment : BaseFragment<Any>(), IScrollable {
mAdapter?.itemList = it.data
mAdapter?.notifyDataSetChanged()
} else {
containerRl.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.white))
noDataImg.visibility = View.VISIBLE
containerRl?.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.white))
noDataImg?.visibility = View.VISIBLE
}
})

View File

@ -84,7 +84,7 @@ class TopVideoView @JvmOverloads constructor(context: Context, attrs: AttributeS
clearFullscreenLayout()
}
errorBtn.setOnClickListener {
errorBtn?.setOnClickListener {
debounceActionWithInterval(errorBtn.id, 1000) {
if (!com.shuyu.gsyvideoplayer.utils.NetworkUtils.isAvailable(mContext)) {
Utils.toast(context, "网络异常,请检查手机网络状态")

View File

@ -10,7 +10,10 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import com.gh.base.fragment.BaseFragment_TabLayout
import com.gh.base.fragment.WaitingDialogFragment
import com.gh.common.util.*
import com.gh.common.util.DisplayUtils
import com.gh.common.util.ImageUtils
import com.gh.common.util.observeNonNull
import com.gh.common.util.viewModelProvider
import com.gh.gamecenter.ImageViewerActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.SelectUserIconActivity
@ -48,14 +51,14 @@ class AvatarBorderFragment : BaseFragment_TabLayout() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mUserViewModel = viewModelProvider(UserViewModel.Factory(HaloApp.getInstance().application))
mUserViewModel.loginObsUserinfo.observe(this, Observer {
mUserViewModel.loginObsUserinfo.observeNonNull(this) {
if (it.data.background?.url.isNullOrEmpty()) {
ImageUtils.display(mBinding.forumBackground, R.drawable.bg_avatar_border)
} else {
ImageUtils.display(mBinding.forumBackground, it.data.background?.url)
}
mBinding.userAvatar.display(it.data.iconBorder?.url, it.data.icon ?: "")
})
}
mUserViewModel.editObsUserinfo.observe(this, Observer {
mBinding.userAvatar.displayAvatar(it.data.icon ?: "")
})

View File

@ -117,7 +117,7 @@ class BindPhoneFragment : NormalFragment() {
// 如果当前登录方式是手机号登录也要更新loginType
UserManager.getInstance().loginTokenEntity?.apply {
if (loginType.length == 11) loginType = phoneNum
if (loginType?.length == 11) loginType = phoneNum
}
requireActivity().finish()
@ -183,7 +183,7 @@ class BindPhoneFragment : NormalFragment() {
}
@OnClick(R.id.bind_phone_skip, R.id.bind_phone_captcha, R.id.bind_phone_btn)
override fun onClick(v : View) {
override fun onClick(v: View) {
// 防止快速点击
if (ClickUtils.isFastDoubleClick()) return

View File

@ -122,7 +122,7 @@ class SimulatorGameFragment : NormalFragment() {
MtaHelper.onEvent("我的光环_新", "模拟器游戏", "点击${mTypeAliasList[it]}")
if (mCurrentPage != it) {
(mFragmentsList[mCurrentPage] as SimulatorGameListFragment).resetPage()
(mFragmentsList.safelyGetInRelease(mCurrentPage) as? SimulatorGameListFragment)?.resetPage()
mCurrentPage = it
}
}

View File

@ -218,6 +218,7 @@ class VideoDetailContainerFragment : BaseLazyFragment(), OnBackPressedListener {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val (itemHeight, distance) = getDistance()
if (itemHeight <= 0) return
val offsetY = distance % itemHeight
val alpha = 1 - offsetY.toFloat() / itemHeight
val homeVideoFragment = this@VideoDetailContainerFragment.parentFragment as? HomeVideoFragment
@ -242,7 +243,7 @@ class VideoDetailContainerFragment : BaseLazyFragment(), OnBackPressedListener {
}
override fun onPageRelease(isNext: Boolean, position: Int) {
val video = mViewModel.videoList.value?.get(position)
val video = mViewModel.videoList.value?.safelyGetInRelease(position)
video?.let {
ExoCacheManager.cancel(video.url)

View File

@ -11,7 +11,6 @@ import com.gh.common.runOnIoThread
import com.gh.common.util.UrlFilterUtils
import com.gh.common.util.createRequestBodyAny
import com.gh.common.util.tryCatchInRelease
import com.gh.common.util.tryWithDefaultCatch
import com.gh.download.DownloadManager
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.entity.MyVideoEntity
@ -455,8 +454,10 @@ class VideoDetailContainerViewModel(application: Application) : AndroidViewModel
}
fun shareVideoStatistics(videoEntity: VideoEntity?) {
if (videoEntity == null) return
RetrofitManager.getInstance(getApplication())
.api.shareVideoStatistics(videoEntity!!.id)
.api.shareVideoStatistics(videoEntity.id)
.subscribeOn(Schedulers.io())
.subscribe(object : BiResponse<JsonObject>() {
override fun onSuccess(data: JsonObject) {

View File

@ -7,8 +7,8 @@ ext {
targetSdkVersion = 26
// application info (每个大版本之间的 versionCode 增加 20)
versionCode = 252
versionName = "4.5.2"
versionCode = 253
versionName = "4.5.3"
applicationId = "com.gh.gamecenter"
// AndroidX