Compare commits

..

3 Commits

485 changed files with 3206 additions and 9854 deletions

View File

@ -42,7 +42,7 @@ android {
}
ndk {
abiFilters "armeabi-v7a"
abiFilters "armeabi-v7a", "x86"
}
// 由于app只针对中文用户所以仅保留zh资源其他删掉
@ -68,13 +68,6 @@ android {
buildConfigField "String", "LETO_APPID", "\"${LETO_APPID}\""
buildConfigField "String", "TTAD_APPID", "\"${TTAD_APPID}\""
buildConfigField "String", "MIPUSH_APPID", "\"${MIPUSH_APPID}\""
buildConfigField "String", "MIPUSH_APPKEY", "\"${MIPUSH_APPKEY}\""
buildConfigField "String", "MEIZUPUSH_APPID", "\"${MEIZUPUSH_APPID}\""
buildConfigField "String", "MEIZUPUSH_APPKEY", "\"${MEIZUPUSH_APPKEY}\""
resValue "string", "huawei_push_appid", "appid=${HUAWEI_PUSH_APPID}"
/**
* Build Time 供区分 jenkins 打包时间用
*/
@ -102,7 +95,7 @@ android {
signingConfig signingConfigs.debug
buildConfigField "String", "EXPOSURE_REPO", "\"test\""
buildConfigField "String", "EXPOSURE_VERSION", "\"E4\""
buildConfigField "String", "EXPOSURE_VERSION", "\"E3\""
multiDexKeepProguard file("tinker_multidexkeep.pro")
}
@ -114,7 +107,7 @@ android {
signingConfig signingConfigs.release
buildConfigField "String", "EXPOSURE_REPO", "\"exposure\""
buildConfigField "String", "EXPOSURE_VERSION", "\"E4\""
buildConfigField "String", "EXPOSURE_VERSION", "\"E3\""
multiDexKeepProguard file("tinker_multidexkeep.pro")
}
@ -131,10 +124,13 @@ android {
dimension "nonsense"
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
buildConfigField "String", "SENSITIVE_API_HOST", "\"${SENSITIVE_API_HOST}\""
buildConfigField "String", "UMENG_APPKEY", "\"${UMENG_APPKEY}\""
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${UMENG_MESSAGE_SECRET}\""
buildConfigField "String", "MIPUSH_APPID", "\"${MIPUSH_APPID}\""
buildConfigField "String", "MIPUSH_APPKEY", "\"${MIPUSH_APPKEY}\""
buildConfigField "String", "MEIZUPUSH_APPID", "\"${MEIZUPUSH_APPID}\""
buildConfigField "String", "MEIZUPUSH_APPKEY", "\"${MEIZUPUSH_APPKEY}\""
buildConfigField "String", "BUGLY_APPID", "\"${BUGLY_APPID}\""
}
// internal test dev host
@ -144,11 +140,14 @@ android {
buildConfigField "String", "API_HOST", "\"${DEV_API_HOST}\""
buildConfigField "String", "SENSITIVE_API_HOST", "\"${DEV_API_HOST}\""
buildConfigField "String", "UMENG_APPKEY", "\"${DEBUG_UMENG_APPKEY}\""
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${DEBUG_UMENG_MESSAGE_SECRET}\""
buildConfigField "String", "MIPUSH_APPID", "\"${DEBUG_MIPUSH_APPID}\""
buildConfigField "String", "MIPUSH_APPKEY", "\"${DEBUG_MIPUSH_APPKEY}\""
buildConfigField "String", "MEIZUPUSH_APPID", "\"${DEBUG_MEIZUPUSH_APPID}\""
buildConfigField "String", "MEIZUPUSH_APPKEY", "\"${DEBUG_MEIZUPUSH_APPKEY}\""
buildConfigField "String", "UMENG_APPKEY", "\"${DEV_UMENG_APPKEY}\""
buildConfigField "String", "UMENG_MESSAGE_SECRET", "\"${DEV_UMENG_MESSAGE_SECRET}\""
buildConfigField "String", "BUGLY_APPID", "\"${DEV_BUGLY_APPID}\""
buildConfigField "String", "BUGLY_APPID", "\"${DEBUG_BUGLY_APPID}\""
}
}
}
@ -172,7 +171,7 @@ rebuildChannel {
repositories {
flatDir {
dirs 'libs', 'libs/aars'
dirs 'libs','libs/aars'
}
}
@ -264,11 +263,13 @@ dependencies {
implementation "com.squareup.picasso:picasso:${picasso}"
// for video streaming
implementation("com.shuyu:gsyVideoPlayer-java:$gsyVideo", {
implementation ("com.shuyu:gsyVideoPlayer-java:$gsyVideo",{
exclude module: "gsyvideoplayer-androidvideocache"
})
implementation "com.shuyu:GSYVideoPlayer-exo2:$gsyVideo"
implementation "com.github.wendux:DSBridge-Android:$dsBridge"
implementation "android.arch.work:work-runtime:${workManager}"
implementation "com.llew.huawei:verifier:${verifier}"

View File

@ -248,10 +248,4 @@
-keep class com.pgl.sys.ces.* {*;}
-keep class com.gyf.immersionbar.* {*;}
-dontwarn com.gyf.immersionbar.**
-keep class com.taobao.securityjni.**{*;}
-keep class com.taobao.wireless.security.**{*;}
-keep class com.ut.secbody.**{*;}
-keep class com.taobao.dp.**{*;}
-keep class com.alibaba.wireless.security.**{*;}
-dontwarn com.gyf.immersionbar.**

View File

@ -4,6 +4,7 @@ import android.app.Application;
import com.facebook.stetho.Stetho;
import com.facebook.stetho.okhttp3.StethoInterceptor;
import com.squareup.leakcanary.LeakCanary;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
@ -17,6 +18,15 @@ import okhttp3.logging.HttpLoggingInterceptor;
public class Injection {
public static boolean appInit(Application application) {
// init leakcanary
if (LeakCanary.isInAnalyzerProcess(application)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
return false;
}
LeakCanary.install(application);
// init stetho
Stetho.initializeWithDefaults(application);

View File

@ -82,7 +82,6 @@
android:largeHeap="true"
android:resizeableActivity="true"
android:theme="@style/AppCompatTheme.APP"
tools:replace="android:allowBackup"
tools:targetApi="n">
<!--android:launchMode = "singleTask"-->
@ -519,7 +518,6 @@
<activity
android:name="com.gh.gamecenter.PushProxyActivity"
android:exported="true"
android:launchMode="singleTask"
android:theme="@android:style/Theme.Translucent" />
<activity
@ -582,7 +580,7 @@
</receiver>
<!--魅族push应用定义消息receiver声明 -->
<receiver android:name="com.gh.gamecenter.receiver.UmengMeizuPushReceiver">
<receiver android:name="com.gh.gamecenter.receiver.MeizuPushReceiver">
<intent-filter>
<!-- 接收push消息 -->
<action android:name="com.meizu.flyme.push.intent.MESSAGE" />
@ -607,11 +605,7 @@
</intent-filter>
</receiver>
<meta-data android:name="com.huawei.hms.client.appid" android:value="@string/huawei_push_appid"/>
<service
android:name="com.gh.base.GHUmengNotificationService"
android:permission="android.permission.BIND_JOB_SERVICE" />
<service android:name="com.gh.base.GHUmengNotificationService" />
<!--<service android:name = "com.gh.gamecenter.statistics.AppStaticService" />-->

View File

@ -3,25 +3,17 @@ package com.gh.base;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.gh.base.fragment.BaseFragment;
import com.gh.common.constant.Constants;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.MtaHelper;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.RunningUtils;
@ -45,7 +37,6 @@ import java.lang.ref.WeakReference;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Lifecycle;
import butterknife.ButterKnife;
@ -118,15 +109,6 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
}
}
@SuppressWarnings("ConstantConditions")
@Override
public void setContentView(View view) {
if (BuildConfig.DEBUG || BuildConfig.BUILD_TIME != 0) {
view = getRootViewWithEnvIndicator(view);
}
super.setContentView(view);
}
@Override
protected void onDestroy() {
if (useEventBus()) EventBus.getDefault().unregister(this);
@ -146,55 +128,21 @@ public abstract class BaseActivity extends BaseAppCompatActivity implements Easy
String icon,
String shareTitle,
String shareSummary,
ShareUtils.ShareEntrance shareEntrance, String id) {
ShareUtils.ShareType shareType) {
ShareUtils.getInstance(this).showShareWindows(this,
getWindow().getDecorView(),
url,
icon,
shareTitle,
shareSummary,
shareEntrance, id);
if (shareEntrance == ShareUtils.ShareEntrance.game || shareEntrance == ShareUtils.ShareEntrance.plugin) {
shareType);
if (shareType == ShareUtils.ShareType.game || shareType == ShareUtils.ShareType.plugin) {
MtaHelper.onEvent("内容分享", "内容分享", shareTitle + shareSummary);
} else {
MtaHelper.onEvent("内容分享", "内容分享", shareTitle);
}
}
private View getRootViewWithEnvIndicator(View view) {
RelativeLayout screenRootView = new RelativeLayout(this);
screenRootView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
LinearLayout ll = new LinearLayout(this);
TextView tv = new TextView(this);
String envText = "正式环境";
if (BuildConfig.FLAVOR.equals("internal")) {
envText = "测试环境";
}
tv.setText(envText);
tv.setGravity(Gravity.CENTER);
tv.setTextColor(Color.WHITE);
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13);
tv.setBackground(ContextCompat.getDrawable(this, R.color.red));
tv.measure(0, 0);
tv.setAlpha(0.15F);
int height = tv.getMeasuredHeight();
int width = tv.getMeasuredWidth();
tv.setPadding(DisplayUtils.dip2px(20), 0, DisplayUtils.dip2px(20), 0);
ll.setTranslationX(DisplayUtils.dip2px(20));
ll.setRotation(45);
ll.addView(tv);
ll.setPadding(0, (width - height) / 2, 0, (width - height) / 2);
screenRootView.addView(view);
screenRootView.addView(ll);
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) ll.getLayoutParams();
lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
view.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
return screenRootView;
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(final EBShowDialog showDialog) {
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)

View File

@ -35,7 +35,6 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
val mRichEditor by bindView<RichEditor>(R.id.rich_editor)
val mDraftBtn by bindView<TextView>(R.id.draft_btn)
private val mEditorTextNumTv by bindView<TextView>(R.id.editorTextNumTv)
private val mEditorFont by bindView<CheckableImageView>(R.id.editor_font)
private val mEditorLink by bindView<CheckableImageView>(R.id.editor_link)
private val mEditorParagraph by bindView<CheckableImageView>(R.id.editor_paragraph)
@ -90,7 +89,6 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
// 防止个别手机在Js里无法获取粘贴内容
mRichEditor.addJavascriptInterface(OnPasteListener(), "onPasteListener")
mRichEditor.addJavascriptInterface(OnCursorChangeListener(), "OnCursorChangeListener")
mRichEditor.addJavascriptInterface(OnEditorTextChangeListener(), "OnEditorTextChangeListener")
mRichEditor.setInputEnabled(true)
mDraftBtn.text = if (this is AnswerEditActivity) {
@ -260,14 +258,6 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
}
}
private inner class OnEditorTextChangeListener {
@JavascriptInterface
fun onTextChange(count: Int) {
val num = if (count > MAX_INPUT_TEXT_NUM) MAX_INPUT_TEXT_NUM - count else count
mEditorTextNumTv.text = num.toString()
}
}
abstract fun mtaEventName(): String
companion object {
@ -283,6 +273,5 @@ abstract class BaseRichEditorActivity : ToolBarActivity() {
const val INSERT_ANSWER_CODE = 411
const val INSERT_ARTICLE_CODE = 412
const val INSERT_GAME_CODE = 413
const val MAX_INPUT_TEXT_NUM = 10000
}
}

View File

@ -95,7 +95,7 @@ class GHUmengNotificationService : UmengMessageService() {
// 用户未登录的情况下不生成消息中心通知,避免用户掉登录了还收到跳转至消息中心的通知
if (data != null
&& data.link?.link == "system"
&& data.link?.target == "system"
&& !UserManager.getInstance().isLoggedIn) {
return
}

View File

@ -15,6 +15,7 @@ import android.widget.RelativeLayout;
import android.widget.TextView;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.MtaHelper;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.DownloadManagerActivity;
import com.gh.gamecenter.R;
@ -238,7 +239,7 @@ public abstract class ToolBarActivity extends BaseActivity implements ToolbarCon
@Override
public boolean onMenuItemClick(MenuItem item) {
if (item.getItemId() == R.id.menu_download) {
// MtaHelper.onEvent("下载管理", "下载管理入口", getActivityNameInChinese());
MtaHelper.onEvent("下载管理", "下载管理入口", getActivityNameInChinese());
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(this, mEntrance);
startActivity(intent);
}

View File

@ -9,14 +9,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.RecyclerView;
import com.gh.base.OnListClickListener;
import com.gh.base.OnRequestCallBackListener;
import com.gh.common.constant.Constants;
@ -37,6 +29,13 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.ButterKnife;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
@ -211,13 +210,6 @@ public abstract class BaseFragment<T> extends Fragment implements OnRequestCallB
return mCachedView;
}
@Override
public void onDestroyView() {
super.onDestroyView();
mCachedView = null;
}
@Override
public void onResume() {
super.onResume();

View File

@ -3,10 +3,11 @@ package com.gh.base.fragment
import android.content.Intent
import android.graphics.Typeface
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.widget.CheckedTextView
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.viewpager.widget.PagerAdapter
import androidx.viewpager.widget.ViewPager
import butterknife.BindView
import com.gh.base.adapter.FragmentAdapter
@ -14,6 +15,7 @@ import com.gh.common.view.TabIndicatorView
import com.gh.gamecenter.R
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import com.lightgame.view.NoScrollableViewPager
@ -21,10 +23,8 @@ abstract class BaseLazyTabFragment : BaseLazyFragment(), ViewPager.OnPageChangeL
@BindView(R.id.fragment_tab_layout)
lateinit var mTabLayout: TabLayout
@BindView(R.id.fragment_view_pager)
lateinit var mViewPager: NoScrollableViewPager
@BindView(R.id.fragment_tab_indicator)
lateinit var mTabIndicatorView: TabIndicatorView
@ -66,10 +66,6 @@ abstract class BaseLazyTabFragment : BaseLazyFragment(), ViewPager.OnPageChangeL
if (arguments != null) mCheckedIndex = requireArguments().getInt(PAGE_INDEX, 0)
}
open fun providePagerAdapter(): PagerAdapter? {
return null
}
override fun onFragmentFirstVisible() {
super.onFragmentFirstVisible()
@ -78,8 +74,7 @@ abstract class BaseLazyTabFragment : BaseLazyFragment(), ViewPager.OnPageChangeL
mViewPager.offscreenPageLimit = mFragmentsList.size
mViewPager.addOnPageChangeListener(this)
mViewPager.adapter = providePagerAdapter()
?: FragmentAdapter(childFragmentManager, mFragmentsList, mTabTitleList)
mViewPager.adapter = FragmentAdapter(childFragmentManager, mFragmentsList, mTabTitleList)
mViewPager.currentItem = mCheckedIndex
mTabLayout.setupWithViewPager(mViewPager)
mTabIndicatorView.setupWithTabLayout(mTabLayout)
@ -89,10 +84,60 @@ abstract class BaseLazyTabFragment : BaseLazyFragment(), ViewPager.OnPageChangeL
val tab = mTabLayout.getTabAt(i) ?: continue
val tabTitle = if (tab.text != null) tab.text.toString() else ""
var tabView = provideTabView(i, tabTitle)
if (tabView == null) tabView = BaseFragment_TabLayout.createDefaultTabCustomView(tabTitle)
if (tabView == null) tabView = createDefaultTabCustomView(tabTitle)
tab.customView = tabView
}
BaseFragment_TabLayout.initTabStyle(mTabLayout, mCheckedIndex)
initTabStyle(mTabLayout, mCheckedIndex)
}
open fun initTabStyle(tabLayout: TabLayout?, currentItem: Int) { // 默认选择addOnTabSelectedListener不会回调
val tabCount = tabLayout!!.tabCount
if (tabCount > 0) {
val tab = tabLayout.getTabAt(currentItem)
if (tab != null) updateTabStyle(tab, true)
}
tabLayout.addOnTabSelectedListener(object : OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) {
updateTabStyle(tab, true)
}
override fun onTabUnselected(tab: TabLayout.Tab) {
updateTabStyle(tab, false)
}
override fun onTabReselected(tab: TabLayout.Tab) {
updateTabStyle(tab, true)
}
})
}
open fun updateTabStyle(tab: TabLayout.Tab, isChecked: Boolean) {
val tabView = tab.customView
if (tabView == null) {
Utils.log("TabLayout->Tab样式不是通用样式,请检查")
return
}
val tabTitle: TextView?
tabTitle = if (tabView is TextView) {
tabView
} else {
tabView.findViewById(R.id.tab_title)
}
if (tabTitle == null) {
Utils.log("TabLayout->Tab样式不是通用样式,请检查")
return
}
tabTitle.typeface = if (isChecked) Typeface.DEFAULT_BOLD else Typeface.DEFAULT
}
// 如果不设置View的话无法动态设置字体样式
open fun createDefaultTabCustomView(title: String?): View {
val view = LayoutInflater.from(HaloApp.getInstance().application.baseContext).inflate(R.layout.tab_item, null)
val tabTitle = view.findViewById<View>(R.id.tab_title)
if (tabTitle is CheckedTextView) {
tabTitle.text = title
}
return view
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}

View File

@ -6,7 +6,6 @@ import android.webkit.JavascriptInterface
import androidx.annotation.Keep
import com.gh.base.CurrentActivityHolder
import com.gh.common.util.*
import com.gh.common.view.dsbridge.CompletionHandler
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.LoginActivity
import com.gh.gamecenter.ViewImageActivity
@ -24,6 +23,7 @@ import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import org.json.JSONObject
import retrofit2.HttpException
import wendu.dsbridge.CompletionHandler
class DefaultJsApi(var context: Context) {

View File

@ -4,22 +4,19 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.text.TextUtils
import com.gh.common.util.CheckLoginUtils
import com.gh.common.util.DialogUtils
import com.gh.common.util.DirectUtils
import com.gh.common.util.*
import com.gh.common.util.DirectUtils.directToGameDetailVideoStreaming
import com.gh.common.util.DirectUtils.directToGameVideo
import com.gh.common.util.DirectUtils.directToVideoDetail
import com.gh.common.util.EntranceUtils
import com.gh.gamecenter.*
import com.gh.gamecenter.entity.CommunityEntity
import com.gh.gamecenter.entity.SubjectRecommendEntity
import com.gh.gamecenter.entity.VideoLinkEntity
import com.gh.gamecenter.subject.SubjectActivity
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
import com.lightgame.utils.Utils
object DefaultUrlHandler {
object DefaultWebViewUrlHandler {
@JvmStatic
fun interceptUrl(context: Context, url: String, entrance: String): Boolean {
@ -187,41 +184,27 @@ object DefaultUrlHandler {
DirectUtils.directAskColumnDetail(context, columnId, community, entrance, "")
}
EntranceUtils.HOST_BLOCK -> {
val name = uri.getQueryParameter("name")
?: ""
val entity = SubjectRecommendEntity(link = id, name = name, text = name)
DirectUtils.directToBlock(context, entity)
}
EntranceUtils.HOST_SERVER_BLOCK -> {
DirectUtils.directToGameServers(context, entrance = entrance, path = "")
}
EntranceUtils.HOST_AMWAY_BLOCK -> {
DirectUtils.directToAmway(context, entrance = entrance, path = "")
}
EntranceUtils.HOST_HELP -> {
val name = uri.getQueryParameter("name")
?: ""
DirectUtils.directToQa(context, name, id)
}
EntranceUtils.HOST_HELP_COLLECTION -> {
val name = uri.getQueryParameter("name")
?: ""
DirectUtils.directToQaCollection(context, name, id)
}
EntranceUtils.HOST_GAME_UPLOAD -> {
DirectUtils.directGameUpload(context,entrance = entrance, path = "")
}
else -> DialogUtils.showLowVersionDialog(context)
}
return true
}
if (url.startsWith("alipays:") || url.startsWith("alipay")) {
try {
context.startActivity(Intent("android.intent.action.VIEW", Uri.parse(url)))
} catch (e: java.lang.Exception) {
ToastUtils.showToast("请安装支付宝客户端")
}
return true
} else if (url.startsWith("weixin")) {
try {
context.startActivity(Intent("android.intent.action.VIEW", Uri.parse(url)))
} catch (e: java.lang.Exception) {
ToastUtils.showToast("请安装微信客户端")
}
return true
}
if ("http" != uri.scheme && "https" != uri.scheme) return true
return false
}

View File

@ -1,68 +0,0 @@
package com.gh.common
import com.gh.common.exposure.ExposureManager
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.loghub.LoghubUtils
import com.gh.common.util.doOnMainProcessOnly
import com.gh.common.videolog.VideoRecordUtils
import com.gh.gamecenter.entity.TimeEntity
import com.gh.gamecenter.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.schedulers.Schedulers
import kotlin.concurrent.fixedRateTimer
object FixedRateJobHelper {
private const val CHECKER_PERIOD: Long = 60 * 1000L
private const val TIME_PERIOD: Long = 600 * 1000L
private const val LOGHUB_PERIOD: Long = 120 * 1000L
private const val EXPOSURE_PERIOD: Long = 300 * 1000L
private const val REGION_SETTING_PERIOD: Long = 300 * 1000L
private const val VIDEO_RECORD_PERIOD: Long = 60 * 1000L
private var mExecuteCount: Int = 0
var timeDeltaBetweenServerAndClient: Long = 0
@JvmStatic
fun begin() {
doOnMainProcessOnly {
fixedRateTimer("Global-Fixed-Rate-Timer", initialDelay = 100, period = CHECKER_PERIOD) {
// 时间校对10分钟一次
if ((mExecuteCount * CHECKER_PERIOD) % TIME_PERIOD == 0L) {
RetrofitManager.getInstance(HaloApp.getInstance().application).api.time
.subscribeOn(Schedulers.io())
.subscribe(object : Response<TimeEntity>() {
override fun onResponse(response: TimeEntity?) {
val serverTime = response?.time
serverTime?.let { timeDeltaBetweenServerAndClient = it * 1000 - System.currentTimeMillis() }
}
})
}
// 提交曝光数据
if ((mExecuteCount * CHECKER_PERIOD) % EXPOSURE_PERIOD == 0L) {
ExposureManager.commitSavedExposureEvents(true)
}
// 提交普通 loghub 数据
if ((mExecuteCount * CHECKER_PERIOD) % LOGHUB_PERIOD == 0L) {
LoghubUtils.commitSavedLoghubEvents()
}
// 更新游戏屏蔽信息
if ((mExecuteCount * CHECKER_PERIOD) % REGION_SETTING_PERIOD == 0L) {
RegionSettingHelper.getRegionSetting()
}
// 提交视频浏览记录数据
if ((mExecuteCount * CHECKER_PERIOD) % VIDEO_RECORD_PERIOD == 0L) {
VideoRecordUtils.commitVideoRecord()
}
// ExposureUtils.logADownloadCompleteExposureEvent(GameEntity(id = mExecuteCount.toString(), name = "测试曝光上传"), platform = "", trace = null, downloadType = ExposureUtils.DownloadType.DOWNLOAD)
mExecuteCount++
}
}
}
}

View File

@ -38,17 +38,22 @@ object PushManager {
fun init(channel: String) {
tryWithDefaultCatch {
//初始化友盟推送
UMConfigure.init(mApplication, Config.UMENG_APPKEY, channel, UMConfigure.DEVICE_TYPE_PHONE, Config.UMENG_MESSAGE_SECRET)
val pushAgent = PushAgent.getInstance(mApplication)
runOnIoThread { registerDevice() }
UMConfigure.init(mApplication,
Config.UMENG_APPKEY, channel,
UMConfigure.DEVICE_TYPE_PHONE,
Config.UMENG_MESSAGE_SECRET)
// 注册小米、华为和魅族通道
MiPushRegistar.register(mApplication, Config.MIPUSH_APPID, Config.MIPUSH_APPKEY)
HuaWeiRegister.register(mApplication)
MeizuRegister.register(mApplication, BuildConfig.MEIZUPUSH_APPID, BuildConfig.MEIZUPUSH_APPKEY)
//友盟推送
val pushAgent = PushAgent.getInstance(mApplication)
//注册推送服务每次调用register方法都会回调该接口
runOnIoThread { registerDevice() }
val aliasInSp = PreferenceManager.getDefaultSharedPreferences(mApplication).getString(SP_PUSH_ALIAS, "")
mPreviousAlias = aliasInSp?.toObject()

View File

@ -31,7 +31,6 @@ import io.reactivex.schedulers.Schedulers;
public class Config {
public static final String API_HOST = BuildConfig.API_HOST;
public static final String SENSITIVE_API_HOST = BuildConfig.SENSITIVE_API_HOST;
/**
* 需要配置的请使用{@link PreferenceManager#getDefaultSharedPreferences(Context)}
@ -254,7 +253,7 @@ public class Config {
public static void getGhzsSettings() {
String channel = HaloApp.getInstance().getChannel();
RetrofitManager.getInstance(HaloApp.getInstance().getApplication())
.getSensitiveApi().getSettings(PackageUtils.getVersionName(), channel)
.getApi().getSettings(PackageUtils.getVersionName(), channel)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<SettingsEntity>() {

View File

@ -42,9 +42,6 @@ public class Constants {
// 最近显示的弹窗信息
public static final String SP_LAST_OPENING_ID = "last_opening_dialog_id";
public static final String SP_LAST_OPENING_TIME = "last_opening_dialog_time";
// 新用户首次启动光环的时间
public static final String SP_INITIAL_USAGE_TIME = "initial_usage_time";
//引导设置 “通知管理” 引导弹窗
public static final String SP_SHOWED_NOTIFICATION_LOGIN = "show_notification_login_hint";
@ -89,8 +86,6 @@ public class Constants {
public static final String SP_AUTH_DIALOG = "auth_dialog";
//顶部视频进度保存,重启恢复
public static final String SP_TOP_VIDEO_SCHEDULE = "top_video_schedule";
//我的光环小红点提示
public static final String SP_GH_RED_POINT_REMIND = "gh_red_point_remind";
//手机号码匹配规则
public static final String REGEX_MOBILE = "^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";

View File

@ -2,7 +2,6 @@ package com.gh.common.databind;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Typeface;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
@ -14,12 +13,6 @@ import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.databinding.BindingAdapter;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.facebook.drawee.view.SimpleDraweeView;
import com.gh.base.OnViewClickListener;
import com.gh.common.constant.Config;
@ -75,6 +68,12 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.databinding.BindingAdapter;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
/**
* Created by khy on 12/02/18.
*/
@ -96,26 +95,6 @@ public class BindingAdapters {
view.setTextSize(number);
}
@BindingAdapter("setTypeface")
public static void setTypeface(TextView view, String type) {
if (type == null) return;
switch (type) {
case "bold":
view.setTypeface(null, Typeface.BOLD);
break;
case "italic":
view.setTypeface(null, Typeface.ITALIC);
break;
case "bold_italic":
view.setTypeface(null, Typeface.BOLD_ITALIC);
break;
default:
view.setTypeface(null, Typeface.NORMAL);
break;
}
}
@BindingAdapter({"addDetailKaiFuView", "addDetailKaiFuViewListener", "isReadyPatch"})
public static void addDetailKaiFuView(LinearLayout view, List<ServerCalendarEntity> list
, OnViewClickListener listener, Boolean isReadyPatch) {
@ -708,15 +687,14 @@ public class BindingAdapters {
}
}
@BindingAdapter({"setGameName", "isShowPlatform", "isShowSuffix"})
public static void setGameName(TextView view, GameEntity game, boolean isShowPlatform, @Nullable Boolean isShowSuffix) {
if (isShowSuffix == null) isShowSuffix = true; // 默认显示
@BindingAdapter({"setGameName", "isShowPlatform"})
public static void setGameName(TextView view, GameEntity game, boolean isShowPlatform) {
if (isShowPlatform && game.getApk().size() > 0) {
view.setText(String.format("%s - %s", !isShowSuffix ? game.getNameWithoutSuffix() : game.getName(),
view.setText(String.format("%s - %s", game.getName(),
PlatformUtils.getInstance(view.getContext()).getPlatformName(
game.getApk().get(0).getPlatform())));
} else {
view.setText(!isShowSuffix ? game.getNameWithoutSuffix() : game.getName());
view.setText(game.getName());
}
}

View File

@ -10,7 +10,6 @@ import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.text.HtmlCompat
import com.gh.base.fragment.BaseDialogFragment
import com.gh.common.util.DirectUtils
import com.gh.common.util.DisplayUtils
import com.gh.common.util.MtaHelper
@ -19,10 +18,7 @@ import com.gh.gamecenter.entity.GameEntity
import kotlinx.android.synthetic.main.dialog_game_off_service.*
// 游戏关闭下载弹窗
class GameOffServiceDialogFragment
// : BaseTrackableDialogFragment()
:BaseDialogFragment() {
class GameOffServiceDialogFragment : BaseTrackableDialogFragment() {
private var mDialog: GameEntity.Dialog? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
@ -46,7 +42,7 @@ class GameOffServiceDialogFragment
siteTv.text = site.text
siteTv.paintFlags = siteTv.paintFlags or Paint.UNDERLINE_TEXT_FLAG
siteTv.setOnClickListener {
// MtaHelper.onEvent("游戏下载状态按钮", getKey(), site.text)
MtaHelper.onEvent("游戏下载状态按钮", getKey(), site.text)
DirectUtils.directToWebView(requireContext(), site.url, "(关闭下载弹窗)")
dismiss()
}
@ -56,13 +52,13 @@ class GameOffServiceDialogFragment
}
}
// override fun getEvent(): String {
// return "游戏下载状态按钮"
// }
//
// override fun getKey(): String {
// return "查看详情弹窗"
// }
override fun getEvent(): String {
return "游戏下载状态按钮"
}
override fun getKey(): String {
return "查看详情弹窗"
}
companion object {
@JvmStatic

View File

@ -14,7 +14,6 @@ import androidx.lifecycle.MutableLiveData
import butterknife.BindView
import butterknife.ButterKnife
import butterknife.OnClick
import com.gh.base.fragment.BaseDialogFragment
import com.gh.common.constant.Config
import com.gh.common.history.HistoryHelper
import com.gh.common.repository.ReservationRepository
@ -30,9 +29,7 @@ import okhttp3.ResponseBody
import org.json.JSONObject
// 预约弹窗
class ReserveDialogFragment
: BaseDialogFragment() {
// : BaseTrackableDialogFragment() {
class ReserveDialogFragment : BaseTrackableDialogFragment() {
@BindView(R.id.reserve_hint_tv)
lateinit var reserveHintTv: TextView
@ -67,13 +64,13 @@ class ReserveDialogFragment
return inflater.inflate(R.layout.dialog_reserve_game, null)
}
// override fun getEvent(): String {
// return "预约游戏"
// }
//
// override fun getKey(): String {
// return "预约功能操作"
// }
override fun getEvent(): String {
return "预约游戏"
}
override fun getKey(): String {
return "预约功能操作"
}
@Suppress("DEPRECATION")
@SuppressLint("SetTextI18n")
@ -112,7 +109,7 @@ class ReserveDialogFragment
} else {
customizableBtn.text = dialogConfig?.text
customizableBtn.setOnClickListener {
// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击跳转按钮")
MtaHelper.onEvent("预约游戏", "预约功能操作", "点击跳转按钮")
DirectUtils.directToLinkPage(
requireContext(),
dialogConfig!!.toLinkEntity(),
@ -130,7 +127,7 @@ class ReserveDialogFragment
fun onClick(view: View) {
when (view.id) {
R.id.reserve_without_mobile_btn -> {
// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击无手机号预约")
MtaHelper.onEvent("预约游戏", "预约功能操作", "点击无手机号预约")
mViewModel.reserve(gameId = mGameId, gameName = mGameName)
}
@ -141,12 +138,12 @@ class ReserveDialogFragment
return
}
// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击立即预约")
MtaHelper.onEvent("预约游戏", "预约功能操作", "点击立即预约")
mViewModel.reserve(gameId = mGameId, gameName = mGameName, mobile = mobile)
}
R.id.close_btn -> {
// MtaHelper.onEvent("预约游戏", "预约功能操作", "点击关闭")
MtaHelper.onEvent("预约游戏", "预约功能操作", "点击关闭")
dismissAllowingStateLoss()
}
}
@ -192,7 +189,7 @@ class ReserveViewModel(application: Application) : AndroidViewModel(application)
reservation.postValue(Reservation(success = true, withMobile = mobile.isNotEmpty(), boundWechat = boundWechat))
ReservationRepository.addReservationToMemoryAndRefresh(gameId)
// MtaHelper.onEvent("预约游戏", "预约", gameName)
MtaHelper.onEvent("预约游戏", "预约", gameName)
}
override fun onFailure(exception: Exception) {

View File

@ -11,7 +11,6 @@ data class ExposureEntity(
@SerializedName("game_id")
val gameId: String? = "",
val gameName: String? = "",
val gameVersion: String? = "",
val sequence: Int? = 0,
val platform: String? = "",
val downloadType: String? = "",

View File

@ -8,7 +8,6 @@ import com.gh.common.constant.Constants
import com.gh.common.exposure.meta.Meta
import com.gh.common.exposure.meta.MetaUtil
import com.gh.common.exposure.time.TimeUtil
import com.gh.common.util.getFirstElementDividedByDivider
import com.gh.gamecenter.entity.GameEntity
import kotlinx.android.parcel.Parcelize
import java.util.*
@ -28,14 +27,9 @@ data class ExposureEvent(
companion object {
@JvmStatic
fun createEvent(gameEntity: GameEntity?, source: List<ExposureSource>, eTrace: List<ExposureEvent>? = null, event: ExposureType = ExposureType.EXPOSURE): ExposureEvent {
if (gameEntity?.getApk()?.size == 1) {
gameEntity.gameVersion = gameEntity.getApk().elementAtOrNull(0)?.version ?: ""
}
return ExposureEvent(
payload = ExposureEntity(
gameId = gameEntity?.id?.getFirstElementDividedByDivider(Constants.GAME_ID_DIVIDER),
payload = ExposureEntity(gameId = gameEntity?.id,
gameName = gameEntity?.name?.removeSuffix(Constants.GAME_NAME_DECORATOR),
gameVersion = gameEntity?.gameVersion,
sequence = gameEntity?.sequence,
platform = gameEntity?.platform,
downloadType = gameEntity?.downloadType,

View File

@ -26,10 +26,6 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy
visibleState?.let { commitExposure(it) }
throttleBus?.clear()
}
override fun onFragmentViewDestroyed(fm: FragmentManager, f: Fragment) {
fragment.fragmentManager?.unregisterFragmentLifecycleCallbacks(this)
}
}, false)
}

View File

@ -9,6 +9,7 @@ import com.gh.loghub.LoghubHelper
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import java.util.concurrent.Executors
import kotlin.concurrent.fixedRateTimer
/**
* A handful tool for committing logs to aliyun loghub.
@ -16,7 +17,7 @@ import java.util.concurrent.Executors
* 如何简单地统计列表中每个 item 的曝光事件?
*
* 1. Adapter 实现 IExposable 接口,在 BindView 阶段更新 ExposureEventExposureEvent 供 getEventByPosition(pos) 方法获取用
* 2. 构建一个 ExposureListener 并作为入参添加至 recyclerview 的 onScroll 回调中
* 2. 构建一个 ExposureListener 并作为入参添加至 recyclerview 的 Scroll 回调中
* 3. 没了
*/
object ExposureManager {
@ -24,6 +25,7 @@ object ExposureManager {
private const val ENDPOINT = "cn-qingdao.log.aliyuncs.com"
private const val PROJECT = "ghzs"
private const val STORE_SIZE = 100
private const val STORE_FORCE_UPLOAD_PERIOD = 300 * 1000L
private const val LOG_STORE = BuildConfig.EXPOSURE_REPO
private val loghubHelper = LoghubHelper.getInstance()
@ -36,12 +38,18 @@ object ExposureManager {
@JvmStatic
fun init() {
TimeUtil.init()
loghubHelper.init(HaloApp.getInstance().application, ENDPOINT, PROJECT, LOG_STORE) { TimeUtil.currentTimeMillis() }
exposureExecutor.execute {
val eventList = exposureDao.getAll()
exposureSet.addAll(eventList)
}
fixedRateTimer(name = "ExposureManager-Store-Checker", initialDelay = 500, period = STORE_FORCE_UPLOAD_PERIOD) {
commitSavedExposureEvents(true)
}
}
/**

View File

@ -1,6 +1,5 @@
package com.gh.common.exposure
import android.text.TextUtils
import com.g00fy2.versioncompare.Version
import com.gh.common.constant.Constants
import com.gh.common.util.PackageUtils
@ -23,7 +22,6 @@ object ExposureUtils {
} else {
entity.id
}
gameEntity.gameVersion = entity.getApk().elementAtOrNull(0)?.version ?: gameEntity.gameVersion
gameEntity.platform = platform
gameEntity.downloadType = downloadType.toString()
val exposureEvent = ExposureEvent.createEvent(gameEntity = gameEntity,
@ -65,11 +63,7 @@ object ExposureUtils {
}
}
} else {
if (!TextUtils.isEmpty(apkEntity.ghVersion)) {
DownloadType.PLUGIN_DOWNLOAD
} else {
DownloadType.UPDATE
}
DownloadType.PLUGIN_DOWNLOAD
}
} else {
DownloadType.DOWNLOAD

View File

@ -0,0 +1,30 @@
package com.gh.common.exposure.time
import com.gh.gamecenter.entity.TimeEntity
import com.gh.gamecenter.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.schedulers.Schedulers
import kotlin.concurrent.fixedRateTimer
class Corrector {
companion object {
const val TIME_CORRECTOR_ADJUST_PERIOD: Long = 600000
}
var delta: Long = 0
init {
fixedRateTimer("TimeUtil-Corrector-Checker", initialDelay = 0, period = TIME_CORRECTOR_ADJUST_PERIOD) {
RetrofitManager.getInstance(HaloApp.getInstance().application).api.time
.subscribeOn(Schedulers.io())
.subscribe(object : Response<TimeEntity>() {
override fun onResponse(response: TimeEntity?) {
val serverTime = response?.time
serverTime?.let { delta = it * 1000 - System.currentTimeMillis() }
}
})
}
}
}

View File

@ -1,15 +1,23 @@
package com.gh.common.exposure.time
import com.gh.common.FixedRateJobHelper
object TimeUtil {
private lateinit var corrector: Corrector
fun init() {
corrector = Corrector()
}
fun currentTimeMillis(): Long {
return FixedRateJobHelper.timeDeltaBetweenServerAndClient + System.currentTimeMillis()
return corrector.delta + System.currentTimeMillis()
}
fun currentTime(): Int {
return ((FixedRateJobHelper.timeDeltaBetweenServerAndClient + System.currentTimeMillis()) / 1000).toInt()
return if (::corrector.isInitialized) {
((corrector.delta + System.currentTimeMillis()) / 1000).toInt()
} else {
(System.currentTimeMillis() / 1000).toInt()
}
}
}

View File

@ -1,21 +0,0 @@
package com.gh.common.filter
import androidx.annotation.Keep
import com.google.gson.annotations.SerializedName
@Keep
data class RegionSetting(
@SerializedName("game_mirror")
var mirrorGameIdSet: HashSet<String>,
@SerializedName("game_block")
var filterGameIdSet: HashSet<String>,
@SerializedName("channel_control")
var channelControl: ChannelControl) {
@Keep
data class ChannelControl(
@SerializedName("game_category")
var gameCategory: String,
@SerializedName("effect")
var effect: Boolean)
}

View File

@ -1,96 +0,0 @@
package com.gh.common.filter
import android.annotation.SuppressLint
import com.gh.common.constant.Constants
import com.gh.common.util.SPUtils
import com.gh.common.util.toJson
import com.gh.common.util.toObject
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.retrofit.BiResponse
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Function
import io.reactivex.schedulers.Schedulers
object RegionSettingHelper {
private var mChannelControl: RegionSetting.ChannelControl? = null
private var mFilterGameIdSet: HashSet<String>? = hashSetOf()
private var mDisplayMirrorIfoGameIdSet: HashSet<String>? = hashSetOf()
private const val SP_SETTING = "region_setting"
fun shouldThisGameDisplayMirrorInfo(gameId: String): Boolean {
return mDisplayMirrorIfoGameIdSet?.contains(gameId) ?: false
}
@JvmStatic
fun shouldThisGameBeFiltered(gameId: String?): Boolean {
return mFilterGameIdSet?.contains(gameId) ?: false
}
@JvmStatic
fun filterGame(list: List<GameEntity>?): ArrayList<GameEntity> {
if (list == null) return arrayListOf()
if (mFilterGameIdSet?.isEmpty() == true) {
if (list is ArrayList) return list
}
val listCopy: ArrayList<GameEntity> = if (list is ArrayList) list else ArrayList(list)
listCopy.removeAll { mFilterGameIdSet?.contains(it.id) ?: false }
return listCopy
}
@JvmField
var filterGame = Function { list: List<GameEntity> ->
filterGame(list)
list
}
fun shouldGameOfThisCategoryUseMirrorInfo(category: String) : Boolean {
return if (mChannelControl == null || mChannelControl?.effect == false || !isUserUsedLessThan24Hours()) {
false
} else {
mChannelControl?.gameCategory == category
}
}
@SuppressLint("CheckResult")
@JvmStatic
fun getRegionSetting() {
RetrofitManager.getInstance(HaloApp.getInstance().application)
.sensitiveApi
.getRegionSetting(HaloApp.getInstance().channel)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<RegionSetting>() {
override fun onSuccess(data: RegionSetting) {
updateSettingsInMemory(data)
SPUtils.setString(SP_SETTING, data.toJson())
}
override fun onFailure(exception: Exception) {
SPUtils.getString(SP_SETTING).toObject<RegionSetting>()?.let {
updateSettingsInMemory(it)
}
}
})
}
private fun updateSettingsInMemory(data: RegionSetting) {
mFilterGameIdSet = data.filterGameIdSet
mDisplayMirrorIfoGameIdSet = data.mirrorGameIdSet
mChannelControl = data.channelControl
}
/**
* 该用户是否是使用了不到 24 小时的新用户
*/
private fun isUserUsedLessThan24Hours(): Boolean {
val initialUsageTime = SPUtils.getLong(Constants.SP_INITIAL_USAGE_TIME, 0)
return !(initialUsageTime == 0L || System.currentTimeMillis() - initialUsageTime > 86400000)
}
}

View File

@ -15,7 +15,7 @@ import com.gh.gamecenter.room.converter.*
import com.gh.gamecenter.room.dao.*
import com.halo.assistant.HaloApp
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class], version = 6, exportSchema = false)
@Database(entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class], version = 5, exportSchema = false)
@TypeConverters(CountConverter::class,
CommunityConverter::class,
TimeConverter::class,
@ -23,8 +23,7 @@ import com.halo.assistant.HaloApp
ThumbnailConverter::class,
TagStyleListConverter::class,
StringArrayListConverter::class,
CommunityVideoConverter::class,
UserConverter::class)
CommunityVideoConverter::class)
abstract class HistoryDatabase : RoomDatabase() {
@ -55,20 +54,11 @@ abstract class HistoryDatabase : RoomDatabase() {
}
}
val MIGRATION_5_6: Migration = object : Migration(5, 6) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("Alter TABLE MyVideoEntity add title TEXT NOT NULL DEFAULT ''")
database.execSQL("Alter TABLE MyVideoEntity add commentCount INTEGER NOT NULL DEFAULT 0")
database.execSQL("Alter TABLE MyVideoEntity add user TEXT NOT NULL DEFAULT ''")
}
}
val instance by lazy {
Room.databaseBuilder(HaloApp.getInstance().application, HistoryDatabase::class.java, "USER_TRACK_HISTORY_DATABASE")
.addMigrations(MIGRATION_2_3)
.addMigrations(MIGRATION_3_4)
.addMigrations(MIGRATION_4_5)
.addMigrations(MIGRATION_5_6)
.build()
}
}

View File

@ -6,10 +6,13 @@ import com.aliyun.sls.android.sdk.model.LogGroup
import com.gh.loghub.LoghubHelper
import org.json.JSONObject
import java.util.concurrent.Executors
import kotlin.concurrent.fixedRateTimer
object LoghubUtils {
private const val STORE_SIZE = 100
private const val STORE_FORCE_UPLOAD_INTERVAL = 120 * 1000L
private lateinit var mApplication: Application
private val loghubEventSet by lazy { hashSetOf<LoghubEvent>() }
@ -24,6 +27,10 @@ object LoghubUtils {
val eventList = loghubEventDao.getAll()
loghubEventSet.addAll(eventList)
}
fixedRateTimer(name = "Loghub-Event-Checker", initialDelay = 1000, period = STORE_FORCE_UPLOAD_INTERVAL) {
commitSavedLoghubEvents()
}
}
@JvmStatic
@ -47,7 +54,7 @@ object LoghubUtils {
LoghubHelper.getInstance().uploadLogGroup(logGroup, logStore)
}
fun commitSavedLoghubEvents() {
private fun commitSavedLoghubEvents() {
loghubEventExecutor.execute {
if (loghubEventSet.isEmpty()) return@execute

View File

@ -1,6 +1,5 @@
package com.gh.common.repository
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.util.ApkActiveUtils
import com.gh.common.util.RandomUtils
import com.gh.gamecenter.entity.GameEntity
@ -16,8 +15,7 @@ object RemenkapaiRepository {
@JvmStatic
fun getRemenkapai(size: Int): Observable<List<GameEntity>> {
return if (remenkapaiList.isEmpty()) {
RetrofitManager.getInstance(getApplication()).sensitiveApi.remenkapai
.map(RegionSettingHelper.filterGame)
RetrofitManager.getInstance(getApplication()).api.remenkapai
.map { gameList -> filterEntityWithoutApk(gameList) }
.map { pickRandomSizeEntity(size) }
.map(ApkActiveUtils.filterMapperList)

View File

@ -1,14 +0,0 @@
package com.gh.common.util
import com.alibaba.wireless.security.jaq.avmp.IJAQAVMPSignComponent
import com.alibaba.wireless.security.open.SecurityGuardManager
import com.halo.assistant.HaloApp
object AntiBotHelper {
@JvmStatic
val manager by lazy {
SecurityGuardManager.getInstance(HaloApp.getInstance().application).getInterface(IJAQAVMPSignComponent::class.java).apply {
this.initialize()
}
}
}

View File

@ -3,16 +3,19 @@ package com.gh.common.util;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Build;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import com.gh.common.constant.Config;
import com.gh.common.constant.Constants;
import com.gh.common.exposure.meta.MetaUtil;
import com.gh.gamecenter.BuildConfig;
import com.gh.gid.GidCallback;
import com.gh.gid.GidHelper;
import com.halo.assistant.HaloApp;
import com.lightgame.config.CommonDebug;
import com.lightgame.utils.Util_System_Phone_State;
import com.lightgame.utils.Utils;
import com.tencent.bugly.crashreport.CrashReport;
import com.tencent.stat.MtaSDkException;
@ -123,18 +126,11 @@ public class DataUtils {
public static void getGid() {
GidHelper.getInstance().registerDevice(new GidCallback() {
@Override
public void onSuccess(String gid) {
Utils.log("Gid", gid);
PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication()).edit().putString(Constants.DEVICE_KEY, gid).apply();
String originalGid = HaloApp.getInstance().getGid();
HaloApp.getInstance().setGid(gid);
// 避免重复调用
if (!TextUtils.isEmpty(gid) && !gid.equals(originalGid)) {
GameSubstituteRepositoryHelper.updateSubstitutableGames();
}
public void onSuccess(String s) {
Utils.log("Gid", s);
PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication()).edit().putString(Constants.DEVICE_KEY, s).apply();
HaloApp.getInstance().setGid(s);
// 避免初始化顺序问题导致 MetaUtil 一直持有空的 gid
MetaUtil.INSTANCE.refreshMeta();
}
@ -201,36 +197,36 @@ public class DataUtils {
// 游戏下载
public static void onGameDownloadEvent(Context context, String gameName, String platform, String entrance, String status, String method) {
// Map<String, Object> kv = new HashMap<>();
//
// platform = PlatformUtils.getInstance(HaloApp.getInstance().getApplication()).getPlatformName(platform);
//
// kv.put("版本", platform);
// kv.put("用户机型", Build.MODEL);
// kv.put("设备IMEI", Util_System_Phone_State.getDeviceId(HaloApp.getInstance().getApplication()));
// kv.put("网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
// kv.put("光环助手版本", BuildConfig.VERSION_NAME);
// kv.put("位置", entrance);
// kv.put("类型", method);
// kv.put("厂商", Build.MANUFACTURER);
// kv.put("Android版本", Build.VERSION.RELEASE);
// onEvent(context, "游戏下载", gameName, kv);
//
// Map<String, Object> kv2 = new HashMap<>();
// kv2.put("状态", status);
// kv2.put("位置", entrance);
//
// if (status.equals("开始")) {
// kv2.put("版本", entrance + "-开始");
// kv2.put("游戏分平台", gameName + "-" + platform + "-开始");
// kv2.put("光环助手版本", BuildConfig.VERSION_NAME + "-开始");
// } else {
// kv2.put("版本", platform);
// kv2.put("游戏分平台", gameName + "-" + platform);
// kv2.put("光环助手版本", BuildConfig.VERSION_NAME);
// }
//
// onEvent(context, "游戏下载位置", gameName, kv2);
Map<String, Object> kv = new HashMap<>();
platform = PlatformUtils.getInstance(HaloApp.getInstance().getApplication()).getPlatformName(platform);
kv.put("版本", platform);
kv.put("用户机型", Build.MODEL);
kv.put("设备IMEI", Util_System_Phone_State.getDeviceId(HaloApp.getInstance().getApplication()));
kv.put("网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
kv.put("光环助手版本", BuildConfig.VERSION_NAME);
kv.put("位置", entrance);
kv.put("类型", method);
kv.put("厂商", Build.MANUFACTURER);
kv.put("Android版本", Build.VERSION.RELEASE);
onEvent(context, "游戏下载", gameName, kv);
Map<String, Object> kv2 = new HashMap<>();
kv2.put("状态", status);
kv2.put("位置", entrance);
if (status.equals("开始")) {
kv2.put("版本", entrance + "-开始");
kv2.put("游戏分平台", gameName + "-" + platform + "-开始");
kv2.put("光环助手版本", BuildConfig.VERSION_NAME + "-开始");
} else {
kv2.put("版本", platform);
kv2.put("游戏分平台", gameName + "-" + platform);
kv2.put("光环助手版本", BuildConfig.VERSION_NAME);
}
onEvent(context, "游戏下载位置", gameName, kv2);
}
// 游戏更新

View File

@ -269,21 +269,18 @@ public class DeviceUtils {
// 只能获取WiFi的IpAddress
public static String getCurrentIpAddress() {
String ipAddress = "0.0.0.0";
try {
WifiManager wifiManager = (WifiManager) HaloApp.getInstance().
getApplication().
getApplicationContext().
getSystemService(Context.WIFI_SERVICE);
int address = wifiManager.getDhcpInfo().ipAddress;
ipAddress = ((address & 0xFF)
+ "." + ((address >> 8) & 0xFF)
+ "." + ((address >> 16) & 0xFF)
+ "." + ((address >> 24) & 0xFF));
return ipAddress;
} catch (Exception e) {
return ipAddress;
}
String ipAddress;
WifiManager wifiManager = (WifiManager) HaloApp.getInstance().
getApplication().
getApplicationContext().
getSystemService(Context.WIFI_SERVICE);
int address = wifiManager.getDhcpInfo().ipAddress;
ipAddress = ((address & 0xFF)
+ "." + ((address >> 8) & 0xFF)
+ "." + ((address >> 16) & 0xFF)
+ "." + ((address >> 24) & 0xFF));
return ipAddress;
}
}

View File

@ -8,6 +8,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.CountDownTimer;
import android.preference.PreferenceManager;
import android.text.Html;
@ -59,6 +60,7 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
@ -194,7 +196,7 @@ public class DialogUtils {
AppExecutor.getUiExecutor().executeWithDelay(() -> Utils.toast(context, "当前使用移动网络下载,请注意流量消耗"), 500);
callBack.onResponse(false);
} else {
// MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "出现弹窗提示");
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(context), "出现弹窗提示");
showDownloadDialog(context,
() -> callBack.onResponse(false),
() -> callBack.onResponse(true));
@ -254,12 +256,12 @@ public class DialogUtils {
}, 500);
listener.onConfirm();
dialog.dismiss();
// MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "本次允许");
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "本次允许");
});
wifiAuto.setOnClickListener(v -> {
cancelListener.onCancel();
dialog.dismiss();
// MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "连上WiFi后自动下载");
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "连上WiFi后自动下载");
});
allowAlways.setOnClickListener(v -> {
PreferenceManager
@ -274,7 +276,7 @@ public class DialogUtils {
}, 500);
listener.onConfirm();
dialog.dismiss();
// MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "总是允许");
MtaHelper.onEvent("移动网络下载", NetworkUtils.getMobileNetworkType(finalContext), "总是允许");
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
@ -1341,33 +1343,6 @@ public class DialogUtils {
dialog.show();
}
public static void showPluggableNeverRemindDialog(Context context, String nameAndPlatform, @NonNull ConfirmListener listener) {
context = checkDialogContext(context);
final Dialog dialog = new Dialog(context, R.style.GhAlertDialog);
View contentView = LayoutInflater.from(context).inflate(R.layout.dialog_pluggable_never_remind, null);
View cancelBtn = contentView.findViewById(R.id.cancel);
View confirmBtn = contentView.findViewById(R.id.confirm);
TextView contentTv = contentView.findViewById(R.id.content);
contentTv.setText(("助手首页将不再提示《" + nameAndPlatform + "》的所有插件化消息,确定吗?"));
cancelBtn.setOnClickListener(v -> {
dialog.dismiss();
});
confirmBtn.setOnClickListener(v -> {
listener.onConfirm();
dialog.dismiss();
});
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(contentView);
dialog.show();
}
/**
* @param context may be is application context
* @return activity context

View File

@ -6,17 +6,11 @@ import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.text.TextUtils
import androidx.appcompat.app.AppCompatActivity
import com.gh.base.BaseActivity
import com.gh.base.ToolBarActivity
import com.gh.base.fragment.BaseFragment_TabLayout
import com.gh.common.AppExecutor
import com.gh.common.constant.Config
import com.gh.common.exposure.ExposureEvent
import com.gh.common.exposure.ExposureEvent.Companion.createEvent
import com.gh.common.exposure.ExposureManager.log
import com.gh.common.exposure.ExposureTraceUtils.appendTrace
import com.gh.common.exposure.ExposureType
import com.gh.common.util.EntranceUtils.*
import com.gh.gamecenter.*
import com.gh.gamecenter.amway.AmwayActivity
@ -27,7 +21,6 @@ import com.gh.gamecenter.eventbus.EBReuse
import com.gh.gamecenter.eventbus.EBSkip
import com.gh.gamecenter.fragment.MainWrapperFragment
import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailActivity
import com.gh.gamecenter.game.upload.GameSubmissionActivity
import com.gh.gamecenter.gamedetail.GameDetailFragment
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.mygame.PlayedGameActivity
@ -131,36 +124,30 @@ object DirectUtils {
when (linkEntity.type) {
"article", "news", "文章" -> {
NewsUtils.statNewsViews(context, linkEntity.link) // 统计阅读量
directToArticle(context, linkEntity.link
?: "", BaseActivity.mergeEntranceAndPath(entrance, path))
context.startActivity(NewsDetailActivity.getIntentById(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path)))
}
"game", "游戏" -> {
if (exposureEvent != null) {
directToGameDetail(context, linkEntity.link
?: "", BaseActivity.mergeEntranceAndPath(entrance, path), traceEvent = exposureEvent)
GameDetailActivity.startGameDetailActivity(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path), exposureEvent)
} else {
directToGameDetail(context, linkEntity.link
?: "", BaseActivity.mergeEntranceAndPath(entrance, path))
GameDetailActivity.startGameDetailActivity(context, linkEntity.link, BaseActivity.mergeEntranceAndPath(entrance, path))
}
}
"column", "游戏专题" -> directToSubject(context, linkEntity.link
?: "", linkEntity.text, BaseActivity.mergeEntranceAndPath(entrance, path))
"column", "游戏专题" -> SubjectActivity.startSubjectActivity(context, linkEntity.link, linkEntity.text, false, BaseActivity.mergeEntranceAndPath(entrance, path))
"question", "社区问题" -> directToQuestionDetail(context, linkEntity.link
?: "", entrance, path)
"question", "社区问题" -> context.startActivity(QuestionsDetailActivity.getIntent(context, linkEntity.link, entrance, path))
"answer", "社区回答" -> directToAnswerDetail(context, linkEntity.link ?: "", entrance, path)
"answer", "社区回答" -> context.startActivity(AnswerDetailActivity.getIntent(context, linkEntity.link, entrance, path))
"community", "问答社区" -> directToCommunity(context, CommunityEntity(linkEntity.link!!, linkEntity.text!!))
"community_article", "社区文章" -> directToCommunityArticle(context, linkEntity.community!!, linkEntity.link!!, entrance, path)
"community_article", "社区文章" -> context.startActivity(ArticleDetailActivity.getIntent(context, linkEntity.community!!, linkEntity.link!!, entrance, path))
"community_column", "社区专题" -> directToCommunityColumn(context, linkEntity.community, linkEntity.link!!, entrance, path)
"community_special_column" -> directAskColumnDetail(context, linkEntity.link
?: "", linkEntity.community!!, entrance, path)
"community_special_column" -> context.startActivity(AskColumnDetailActivity.getIntentByColumnId(context, linkEntity.link, linkEntity.community!!, entrance, path))
"web", "inurl", "web链接" -> {
when {
@ -179,28 +166,37 @@ object DirectUtils {
"tag" -> context.startActivity(TagsActivity.getIntent(context, linkEntity.text!!, linkEntity.title, entrance, path))
"all_community_article" -> directSimpleArticleList(context, linkEntity.link
?: "", entrance, path)
"all_community_article" -> {
context.startActivity(SimpleArticleListActivity.getIntent(
context,
linkEntity.link ?: "",
entrance,
path))
}
"category", "分类" -> directCategoryDirectory(context, linkEntity.link!!, linkEntity.text!!)
"category", "分类" -> {
context.startActivity(CategoryDirectoryActivity.getIntent(context, linkEntity.link!!, linkEntity.text!!))
}
"block", "版块" -> {
directToBlock(context, SubjectRecommendEntity(
context.startActivity(BlockActivity.getIntent(context, SubjectRecommendEntity(
link = linkEntity.link,
text = linkEntity.text,
name = linkEntity.name,
display = linkEntity.display ?: Display()))
display = linkEntity.display ?: Display())))
}
"column_collection", "专题合集" -> directToColumnCollection(context, linkEntity.link!!, -1, entrance)
"server", "game_server", "开服表" -> directToGameServers(context, entrance, path)
"server", "game_server" -> {
context.startActivity(GameServersActivity.getIntent(context, entrance, path))
}
"top_game_comment" -> directToAmway(context, null, entrance, path)
"wechat_bind" -> context.startActivity(WebActivity.getBindWechatIntent(context))
"video", "video_stream", "视频" -> directToVideoDetail(context,
"video", "video_stream" -> directToVideoDetail(context,
videoId = linkEntity.link!!,
fromLocation = VideoDetailContainerViewModel.Location.VIDEO_CHOICENESS.value,
entrance = entrance,
@ -208,21 +204,16 @@ object DirectUtils {
"game_video" -> directToGameVideo(context, linkEntity.link ?: "", entrance, path)
"libao", "礼包" -> directToGiftDetail(context, linkEntity.link ?: "", entrance)
"libao" -> directToGiftDetail(context, linkEntity.link ?: "", entrance)
"feedback" -> directToFeedback(context, linkEntity.name, linkEntity.text, entrance)
"qa", "Q&A" -> directToQa(context, linkEntity.text ?: "", linkEntity.link ?: "")
"qa" -> directToQa(context, linkEntity.text ?: "", linkEntity.link ?: "")
"qa_collection", "Q&A合集" -> directToQaCollection(context, linkEntity.text
?: "", linkEntity.link
"qa_collection" -> directToQaCollection(context, linkEntity.text ?: "", linkEntity.link
?: "")
"anliwall", "安利墙" -> directToAmway(context, fixedTopAmwayCommentId = null, entrance = entrance, path = path)
"game_detail_comment" -> directToGameDetail(context, linkEntity.link ?: "", entrance)
"game_upload", "游戏投稿" -> directGameUpload(context, entrance, path)
"anliwall" -> directToAmway(context, fixedTopAmwayCommentId = null, entrance = entrance, path = path)
//"h5_game_center" -> directLetoGameCenter(context)
@ -242,27 +233,15 @@ object DirectUtils {
/**
* 跳转至QA
*/
@JvmStatic
fun directToQa(context: Context, text: String, id: String) {
// context.startActivity(QaActivity.getIntent(context, navigationTitle = text, qaId = id))
val bundle = Bundle()
bundle.putString(KEY_TO, QaActivity::class.java.simpleName)
bundle.putString(KEY_NAVIGATION_TITLE, text)
bundle.putString(KEY_QA_ID, id)
jumpActivity(context, bundle)
context.startActivity(QaActivity.getIntent(context, navigationTitle = text, qaId = id))
}
/**
* 跳转至QA合集
*/
@JvmStatic
fun directToQaCollection(context: Context, text: String, id: String) {
// context.startActivity(QaActivity.getIntent(context, navigationTitle = text, qaCollectionId = id))
val bundle = Bundle()
bundle.putString(KEY_TO, QaActivity::class.java.simpleName)
bundle.putString(KEY_NAVIGATION_TITLE, text)
bundle.putString(KEY_QA_COLLECTION_ID, id)
jumpActivity(context, bundle)
context.startActivity(QaActivity.getIntent(context, navigationTitle = text, qaCollectionId = id))
}
/**
@ -270,14 +249,7 @@ object DirectUtils {
*/
@JvmStatic
fun directToColumnCollection(context: Context, id: String, position: Int = -1, entrance: String, columnName: String = "") {
// context.startActivity(ColumnCollectionDetailActivity.getIntent(context, id, position, entrance, columnName))
val bundle = Bundle()
bundle.putString(KEY_TO, ColumnCollectionDetailActivity::class.java.name)
bundle.putString(KEY_ENTRANCE, entrance)
bundle.putString(KEY_COLLECTION_ID,id)
bundle.putString(KEY_COLUMNNAME,columnName)
bundle.putInt(KEY_POSITION,position)
jumpActivity(context, bundle)
context.startActivity(ColumnCollectionDetailActivity.getIntent(context, id, position, entrance, columnName))
}
/**
@ -327,7 +299,7 @@ object DirectUtils {
* 跳转到游戏详情
*/
@JvmStatic
fun directToGameDetail(context: Context, id: String, entrance: String? = null, autoDownload: Boolean? = null, scrollToLibao: Boolean = false, traceEvent: ExposureEvent? = null) {
fun directToGameDetail(context: Context, id: String, entrance: String? = null, autoDownload: Boolean? = null, scrollToLibao: Boolean = false) {
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_TO, GameDetailActivity::class.java.simpleName)
@ -336,11 +308,6 @@ object DirectUtils {
bundle.putInt(KEY_TARGET, GameDetailFragment.INDEX_TRENDES)
bundle.putBoolean(KEY_SCROLL_TO_LIBAO, scrollToLibao)
}
if (traceEvent != null) {
val clickEvent = createEvent(GameEntity(id), traceEvent.source, appendTrace(traceEvent), ExposureType.CLICK)
log(clickEvent)
bundle.putParcelable(KEY_TRACE_EVENT, clickEvent)
}
bundle.putBoolean(KEY_AUTO_DOWNLOAD, autoDownload ?: false)
jumpActivity(context, bundle)
}
@ -483,9 +450,6 @@ object DirectUtils {
@JvmStatic
fun directToExternalBrowser(context: Context, url: String) {
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
if (context !is AppCompatActivity){
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(browserIntent)
}
@ -506,11 +470,7 @@ object DirectUtils {
chatType = "wpa"
}
val str = "mqqwpa://im/chat?chat_type=$chatType&uin=$qq&version=1&src_type=web"
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(str))
if (context !is AppCompatActivity){
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(intent)
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(str)))
} else {
// 没有安装QQ 复制账号
Util_System_ClipboardManager.setText(context, qq)
@ -521,24 +481,17 @@ object DirectUtils {
// 跳转 QQ 群
@JvmStatic
fun directToQqGroup(context: Context, groupNumber: String? = null): Boolean {
if (ShareUtils.isQQClientAvailable(context)) {
val intent = Intent()
intent.data = Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D$groupNumber")
// 此Flag可根据具体产品需要自定义如设置则在加群界面按返回返回手Q主界面不设置按返回会返回到呼起产品界面 //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
return try {
if (context !is AppCompatActivity){
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(intent)
true
} catch (e: Exception) {
false
}
}else{
val intent = Intent()
intent.data = Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D$groupNumber")
// 此Flag可根据具体产品需要自定义如设置则在加群界面按返回返回手Q主界面不设置按返回会返回到呼起产品界面 //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
try {
context.startActivity(intent)
return true
} catch (e: Exception) {
// 未安装手Q或安装的版本不支持
Utils.toast(context, "请安装QQ客户端")
return false
}
}
/**
@ -598,17 +551,6 @@ object DirectUtils {
jumpActivity(context, bundle)
}
@JvmStatic
fun directToCommunityArticle(context: Context, community: CommunityEntity?, articleId: String?, entrance: String?, path: String?) {
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_PATH, path)
bundle.putString(KEY_TO, ArticleDetailActivity::class.java.name)
bundle.putString(KEY_COMMUNITY_ARTICLE_ID, articleId)
bundle.putParcelable(KEY_COMMUNITY_DATA, community)
jumpActivity(context, bundle)
}
/**
* 跳转到社区专题
*/
@ -774,51 +716,4 @@ object DirectUtils {
bundle.putString(KEY_PATH, path)
jumpActivity(context, bundle)
}
/**
* 跳转到板块
*/
@JvmStatic
fun directToBlock(context: Context, blockData: SubjectRecommendEntity) {
val bundle = Bundle()
bundle.putString(KEY_TO, BlockActivity::class.java.name)
bundle.putParcelable(KEY_BLOCK_DATA, blockData)
jumpActivity(context, bundle)
}
/**
* 跳转到开服表
*/
@JvmStatic
fun directToGameServers(context: Context, entrance: String, path: String) {
val bundle = Bundle()
bundle.putString(KEY_TO, GameServersActivity::class.java.name)
bundle.putString(KEY_ENTRANCE, ToolBarActivity.mergeEntranceAndPath(entrance, path))
jumpActivity(context, bundle)
}
/**
* 跳转到游戏上传
*/
@JvmStatic
fun directGameUpload(context: Context, entrance: String? = null, path: String? = "") {
val bundle = Bundle()
bundle.putString(KEY_TO, GameSubmissionActivity::class.java.name)
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_PATH, path)
jumpActivity(context, bundle)
}
/**
* 社区文章
*/
@JvmStatic
fun directSimpleArticleList(context: Context, sortType: String, entrance: String? = null, path: String? = "") {
val bundle = Bundle()
bundle.putString(KEY_TO, SimpleArticleListActivity::class.java.name)
bundle.putString(KEY_TYPE, sortType)
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_PATH, path)
jumpActivity(context, bundle)
}
}

View File

@ -271,16 +271,6 @@ public class DisplayUtils {
return metrics.heightPixels;
}
public static int getToastOffset() {
int i = Resources.getSystem().getIdentifier("toast_y_offset", "dimen", "android");
return HaloApp.getInstance().getApplication().getResources().getDimensionPixelSize(i);
}
public static int getToastDefaultGravity() {
int i = Resources.getSystem().getIdentifier("config_toastDefaultGravity", "integer", "android");
return HaloApp.getInstance().getApplication().getResources().getInteger(i);
}
public static boolean hasSoftKeys(Context context) {
if (!(context instanceof Activity)) return false;

View File

@ -1,6 +1,5 @@
package com.gh.common.util
import com.gh.common.filter.RegionSettingHelper
import com.gh.download.DownloadManager
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.retrofit.Response
@ -19,12 +18,8 @@ object DownloadHelper {
* @param block 成功添加下载任务后执行的代码块
*/
fun createABrandNewDownloadTaskQuietly(gameId: String? = "", packageName: String? = "", block: () -> Unit) {
if (RegionSettingHelper.shouldThisGameBeFiltered(gameId)) {
return
}
RetrofitManager.getInstance(HaloApp.getInstance().application)
.sensitiveApi
.api
.getGameDigest(gameId)
.map(ApkActiveUtils.filterMapper)
.subscribeOn(Schedulers.io())

View File

@ -8,12 +8,6 @@ import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.collection.ArrayMap;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.gh.common.constant.Config;
import com.gh.common.dialog.CertificationDialog;
import com.gh.common.dialog.DeviceRemindDialog;
@ -40,6 +34,12 @@ import com.lightgame.utils.Utils;
import java.util.concurrent.LinkedBlockingQueue;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.collection.ArrayMap;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
/**
* todo 下载判断不能以按钮文案为判断条件,否则按钮文案修改时又要修改判断逻辑
*/
@ -134,23 +134,16 @@ public class DownloadItemUtils {
public static void updateItem(Context context, GameEntity gameEntity, GameViewHolder holder,
boolean isShowPlatform) {
updateItem(context, gameEntity, holder, isShowPlatform, PluginLocation.only_game, false, null);
updateItem(context, gameEntity, holder, isShowPlatform, PluginLocation.only_game, false);
}
public static void updateItem(Context context, GameEntity gameEntity, GameViewHolder holder,
boolean isShowPlatform, boolean hideDownloadBtnIfNoAvailableContent) {
updateItem(context, gameEntity, holder, isShowPlatform, PluginLocation.only_game, hideDownloadBtnIfNoAvailableContent, null);
updateItem(context, gameEntity, holder, isShowPlatform, PluginLocation.only_game, hideDownloadBtnIfNoAvailableContent);
}
public static void updateItem(Context context, GameEntity gameEntity, GameViewHolder holder,
boolean isShowPlatform, String briefStyle) {
updateItem(context, gameEntity, holder, isShowPlatform, PluginLocation.only_game, false, briefStyle);
}
public static void updateItem(Context context, GameEntity gameEntity, GameViewHolder holder,
boolean isShowPlatform, PluginLocation pluginLocation,
boolean hideDownloadBtnIfNoAvailableContent,
@Nullable String briefStyle) {
boolean isShowPlatform, PluginLocation pluginLocation, boolean hideDownloadBtnIfNoAvailableContent) {
// 控制是否显示下载按钮
if (!Config.isShowDownload(gameEntity.getId()) || context.getString(R.string.app_name).equals(gameEntity.getName())) {
@ -161,7 +154,9 @@ public class DownloadItemUtils {
// 显示预约
if (gameEntity.isReservable()) {
updateItemViewStatus(holder, false, briefStyle);
holder.gameDes.setVisibility(View.VISIBLE);
holder.gameProgressbar.setVisibility(View.GONE);
holder.gameInfo.setVisibility(View.GONE);
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.getId())) {
holder.gameDownloadBtn.setText("预约");
holder.gameDownloadBtn.setTextColor(Color.WHITE);
@ -179,7 +174,9 @@ public class DownloadItemUtils {
LinkEntity h5LinkEntity = gameEntity.getH5Link();
String offStatus = gameEntity.getDownloadOffStatus();
updateItemViewStatus(holder, false, briefStyle);
holder.gameDes.setVisibility(View.VISIBLE);
holder.gameProgressbar.setVisibility(View.GONE);
holder.gameInfo.setVisibility(View.GONE);
if (h5LinkEntity != null) {
if ("play".equals(h5LinkEntity.getType())) {
@ -204,16 +201,16 @@ public class DownloadItemUtils {
holder.gameDownloadBtn.setClickable(false);
}
} else if (gameEntity.getApk().size() == 1) {
updateNormalItem(context, holder, gameEntity, isShowPlatform, pluginLocation, briefStyle);
updateNormalItem(context, holder, gameEntity, isShowPlatform, pluginLocation);
} else {
updatePluginItem(context, holder, gameEntity, isShowPlatform, pluginLocation, briefStyle);
updatePluginItem(context, holder, gameEntity, isShowPlatform, pluginLocation);
}
}
// 更新正常的条目只有一个apk包
static void updateNormalItem(Context context, GameViewHolder holder, GameEntity gameEntity,
boolean isShowPlatform, PluginLocation pluginLocation, String briefStyle) {
boolean isShowPlatform, PluginLocation pluginLocation) {
final ArrayMap<String, DownloadEntity> entryMap = gameEntity.getEntryMap();
final ApkEntity apkEntity = gameEntity.getApk().get(0);
@ -229,12 +226,14 @@ public class DownloadItemUtils {
GameUtils.setDownloadBtnStatus(context, gameEntity, holder.gameDownloadBtn, pluginLocation);
updateItemViewStatus(holder, false, briefStyle);
holder.gameDes.setVisibility(View.VISIBLE);
holder.gameProgressbar.setVisibility(View.GONE);
holder.gameInfo.setVisibility(View.GONE);
}
// 更新插件的条目有多个apk包
private static void updatePluginItem(Context context, GameViewHolder holder, GameEntity gameEntity,
boolean isShowPlatform, PluginLocation pluginLocation, String briefStyle) {
boolean isShowPlatform, PluginLocation pluginLocation) {
GameUtils.setDownloadBtnStatus(context, gameEntity, holder.gameDownloadBtn, pluginLocation);
ArrayMap<String, DownloadEntity> entryMap = gameEntity.getEntryMap();
@ -253,14 +252,18 @@ public class DownloadItemUtils {
return;
}
}
updateItemViewStatus(holder, false, briefStyle);
holder.gameDes.setVisibility(View.VISIBLE);
holder.gameProgressbar.setVisibility(View.GONE);
holder.gameInfo.setVisibility(View.GONE);
}
// 更改进度条和提示文本的状态
public static void changeStatus(Context context, GameViewHolder holder, DownloadEntity downloadEntity,
boolean isShowPlatform, boolean isNormal) {
updateItemViewStatus(holder, true, null);
holder.gameDes.setVisibility(View.GONE);
holder.gameProgressbar.setVisibility(View.VISIBLE);
holder.gameInfo.setVisibility(View.VISIBLE);
String platform = PlatformUtils.getInstance(context).getPlatformName(downloadEntity.getPlatform());
@ -342,29 +345,6 @@ public class DownloadItemUtils {
}
}
private static void updateItemViewStatus(GameViewHolder holder, boolean hasDownload, @Nullable String briefStyle) {
if (hasDownload) {
if (holder.gameRating != null) holder.gameRating.setVisibility(View.GONE);
holder.gameDes.setVisibility(View.GONE);
holder.gameProgressbar.setVisibility(View.VISIBLE);
holder.gameInfo.setVisibility(View.VISIBLE);
} else {
holder.gameProgressbar.setVisibility(View.GONE);
holder.gameInfo.setVisibility(View.GONE);
if (briefStyle != null && briefStyle.contains("star")) {
if (holder.gameRating != null) holder.gameRating.setVisibility(View.VISIBLE);
} else {
if (holder.gameRating != null) holder.gameRating.setVisibility(View.GONE);
}
if (TextUtils.isEmpty(briefStyle) || briefStyle.contains("brief")) {
holder.gameDes.setVisibility(View.VISIBLE);
} else {
holder.gameDes.setVisibility(View.GONE);
}
}
}
public static void setOnClickListener(final Context context,
final TextView downloadBtn,
final GameEntity gameEntity,
@ -449,7 +429,7 @@ public class DownloadItemUtils {
LinkEntity linkEntity = gameEntity.getH5Link();
boolean isPlay = "play".equals(linkEntity.getType()); // 是否为开始玩
boolean isPlay = "play".equals(linkEntity.getType()); // 是否为开始玩
if (isPlay) {
HistoryHelper.insertGameEntity(gameEntity);
}

View File

@ -88,33 +88,30 @@ object DownloadNotificationHelper {
else -> builder.setSortKey("C")
}
tryCatchInRelease {
val notification = builder.build() // 可能会抛出异常
notification.flags = notification.flags or Notification.FLAG_NO_CLEAR
val notification = builder.build()
notification.flags = notification.flags or Notification.FLAG_NO_CLEAR
if (entity.status == DownloadStatus.delete
|| entity.status == DownloadStatus.cancel
|| entity.status == DownloadStatus.hijack
|| entity.status == DownloadStatus.notfound
|| entity.status == DownloadStatus.overflow
|| (entity.status == DownloadStatus.done // 触发安装事件以后也 cancel 掉通知
&& !entity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION].isNullOrEmpty())) {
requireUpdateNotificationGroupDelay = true
notificationManager.cancel(entity.path, DOWNLOAD_NOTIFICATION_ID)
if (entity.status == DownloadStatus.delete
|| entity.status == DownloadStatus.cancel
|| entity.status == DownloadStatus.hijack
|| entity.status == DownloadStatus.notfound
|| entity.status == DownloadStatus.overflow
|| (entity.status == DownloadStatus.done // 触发安装事件以后也 cancel 掉通知
&& !entity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION].isNullOrEmpty())) {
requireUpdateNotificationGroupDelay = true
notificationManager.cancel(entity.path, DOWNLOAD_NOTIFICATION_ID)
} else {
if (entity.status != DownloadStatus.downloading) {
notificationManager.notify(entity.path, DOWNLOAD_NOTIFICATION_ID, notification)
} else {
if (entity.status != DownloadStatus.downloading) {
val time = mNotifyMap[entity.path]
val curTime = System.currentTimeMillis()
if (time == null || curTime - time > 2000) {
mNotifyMap[entity.path] = curTime
notificationManager.notify(entity.path, DOWNLOAD_NOTIFICATION_ID, notification)
} else {
val time = mNotifyMap[entity.path]
val curTime = System.currentTimeMillis()
if (time == null || curTime - time > 2000) {
mNotifyMap[entity.path] = curTime
notificationManager.notify(entity.path, DOWNLOAD_NOTIFICATION_ID, notification)
}
}
}
}
if (requireUpdateNotificationGroupDelay) {
// 虽然运行到这里时 notification 已经被 cancel 了,但在下面的 notificationManager.getActiveNotifications 里它有可能还是 active 状态,
// 这里延时 100 ms 避免出现所有的任务都取消了以后依旧有一条 notification group 常驻

View File

@ -55,9 +55,9 @@ object DownloadObserver {
processHijack(downloadEntity)
val nameAndPlatform = (downloadEntity.name + ":"
+ PlatformUtils.getInstance(mApplication).getPlatformName(downloadEntity.platform))
// MtaHelper.onEvent("下载劫持",
// "游戏名字", nameAndPlatform,
// "网络状态", DeviceUtils.getNetwork(mApplication))
MtaHelper.onEvent("下载劫持",
"游戏名字", nameAndPlatform,
"网络状态", DeviceUtils.getNetwork(mApplication))
return
} else if (DownloadStatus.notfound == downloadEntity.status) {
// 404 Not Found
@ -66,9 +66,9 @@ object DownloadObserver {
downloadManager.cancel(downloadEntity.url)
Utils.toast(mApplication, "该链接已失效!请联系管理员。")
// MtaHelper.onEventWithBasicDeviceInfo("下载失败弹窗",
// "游戏", downloadEntity.name,
// "平台", downloadEntity.platform)
MtaHelper.onEventWithBasicDeviceInfo("下载失败弹窗",
"游戏", downloadEntity.name,
"平台", downloadEntity.platform)
DialogUtils.showAlertDialog(AppManager.getInstance().currentActivity(), "下载失败", "下载链接已失效,建议提交反馈", "立即反馈", "取消", {
SuggestionActivity.startSuggestionActivity(AppManager.getInstance().currentActivity(),
@ -90,9 +90,9 @@ object DownloadObserver {
Utils.toast(mApplication, "网络不稳定,下载任务已暂停")
DataLogUtils.uploadNeterrorLog(mApplication, downloadEntity)
// MtaHelper.onEventWithBasicDeviceInfo("下载自动暂停",
// "游戏", downloadEntity.name,
// "平台", downloadEntity.platform)
MtaHelper.onEventWithBasicDeviceInfo("下载自动暂停",
"游戏", downloadEntity.name,
"平台", downloadEntity.platform)
debugOnly {
Utils.log("DownloadObserver", "下载自动暂停->" + downloadEntity.toJson())
}
@ -149,11 +149,11 @@ object DownloadObserver {
val pm = mApplication.packageManager
val packageInfo = pm.getPackageArchiveInfo(downloadEntity.path, PackageManager.GET_ACTIVITIES)
if (packageInfo == null) {
// MtaHelper.onEventWithBasicDeviceInfo("解析包错误分析",
// "游戏名字", downloadEntity.name + ":" + PlatformUtils.getInstance(mApplication).getPlatformName(downloadEntity.platform))
//
// MtaHelper.onEventWithBasicDeviceInfo("解析包错误_新",
// "游戏", downloadEntity.name + ":" + PlatformUtils.getInstance(mApplication).getPlatformName(downloadEntity.platform))
MtaHelper.onEventWithBasicDeviceInfo("解析包错误分析",
"游戏名字", downloadEntity.name + ":" + PlatformUtils.getInstance(mApplication).getPlatformName(downloadEntity.platform))
MtaHelper.onEventWithBasicDeviceInfo("解析包错误_新",
"游戏", downloadEntity.name + ":" + PlatformUtils.getInstance(mApplication).getPlatformName(downloadEntity.platform))
}
}
@ -199,13 +199,13 @@ object DownloadObserver {
type = ExposureUtils.DownloadType.DOWNLOAD
}
// val kv2 = HashMap<String, Any>()
// kv2["版本"] = downloadEntity.platform
// kv2["状态"] = "下载完成"
// kv2["位置"] = downloadEntity.entrance ?: "null"
// kv2["游戏分平台"] = downloadEntity.name + "-" + platform
// kv2["光环助手版本"] = BuildConfig.VERSION_NAME
// DataUtils.onEvent(mApplication, "游戏下载位置", downloadEntity.name, kv2)
val kv2 = HashMap<String, Any>()
kv2["版本"] = downloadEntity.platform
kv2["状态"] = "下载完成"
kv2["位置"] = downloadEntity.entrance ?: "null"
kv2["游戏分平台"] = downloadEntity.name + "-" + platform
kv2["光环助手版本"] = BuildConfig.VERSION_NAME
DataUtils.onEvent(mApplication, "游戏下载位置", downloadEntity.name, kv2)
if (downloadEntity.isPluggable) {
val kv3 = HashMap<String, Any>()
@ -215,18 +215,16 @@ object DownloadObserver {
type = ExposureUtils.DownloadType.PLUGIN_DOWNLOAD
DataUtils.onEvent(mApplication, "插件化", downloadEntity.name, kv3)
// MtaHelper.onEvent(
// "插件化_新",
// "位置", downloadEntity.entrance,
// "游戏", downloadEntity.name + "-" + downloadEntity.platform,
// "操作", "下载完成",
// "网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().application))
MtaHelper.onEvent(
"插件化_新",
"位置", downloadEntity.entrance,
"游戏", downloadEntity.name + "-" + downloadEntity.platform,
"操作", "下载完成",
"网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().application))
}
ExposureUtils.logADownloadCompleteExposureEvent(
GameEntity(id = downloadEntity.getRealGameId(Constants.GAME_ID_DIVIDER),
mName = downloadEntity.name.removeSuffix(Constants.GAME_NAME_DECORATOR),
gameVersion = downloadEntity.versionName ?: ""),
GameEntity(id = downloadEntity.getRealGameId(Constants.GAME_ID_DIVIDER), mName = downloadEntity.name.removeSuffix(Constants.GAME_NAME_DECORATOR)),
downloadEntity.platform,
downloadEntity.exposureTrace,
type)

View File

@ -4,6 +4,8 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.gh.common.avoidcallback.AvoidOnResultManager;
import com.gh.common.avoidcallback.Callback;
import com.gh.gamecenter.MainActivity;
@ -11,8 +13,6 @@ import com.gh.gamecenter.NormalActivity;
import com.gh.gamecenter.SplashScreenActivity;
import com.gh.gamecenter.normal.NormalFragment;
import androidx.appcompat.app.AppCompatActivity;
/**
* @author CsHeng
* @Date 2017/4/25
@ -28,7 +28,6 @@ public class EntranceUtils {
public static final String KEY_ID = "id";
public static final String KEY_URL = "url";
public static final String KEY_GAMENAME = "gameName";
public static final String KEY_PACKAGE_MD5 = "package_md5";
public static final String HOST_ARTICLE = "article";
public static final String HOST_UPLOAD_VIDEO = "upload_video";//上传视频
public static final String HOST_VIDEO_SINGLE = "video_single";//指定视频-不能划动
@ -42,12 +41,6 @@ public class EntranceUtils {
public static final String HOST_COLUMN_COLLECTION = "column_collection";//专题合集
public static final String HOST_COMMUNITY_QUESTION_LABEL_DETAIL = "community_question_label_detail";//问题标签详情
public static final String HOST_COMMUNITY_COLUMN_DETAIL = "community_column_detail";//专栏详情
public static final String HOST_BLOCK = "block";//板块
public static final String HOST_SERVER_BLOCK = "server";//开服表板块
public static final String HOST_AMWAY_BLOCK = "amway";//安利墙板块
public static final String HOST_HELP = "help";//Q&A
public static final String HOST_HELP_COLLECTION = "help_collection";//Q&A合集
public static final String HOST_GAME_UPLOAD = "game_upload";//游戏上传
public static final String HOST_COMMUNITY_ARTICLE = "community_article";
public static final String HOST_COMMUNITY_COLUMN = "community_column";
public static final String HOST_GAME = "game";
@ -168,7 +161,6 @@ public class EntranceUtils {
public static final String KEY_SHOW_EDIT_DRAFT = "showEditDraft";
public static final String KEY_ARTICLE_OPEN_IN_NEW_PAGE = "openArticleInNewPage";
public static final String KEY_ONLY_CREATE_DRAFT = "onlyCreateDraft";
public static final String KEY_KAIFU_SELECT_TIME = "kaifuSelectTime";
public static void jumpActivity(Context context, Bundle bundle) {
bundle.putBoolean(KEY_REQUIRE_REDIRECT, true);

View File

@ -3,11 +3,10 @@ package com.gh.common.util
import android.animation.Animator
import android.content.ClipboardManager
import android.content.Context
import android.os.Build
import android.text.*
import android.text.style.ClickableSpan
import android.text.style.ImageSpan
import android.text.style.URLSpan
import android.text.Editable
import android.text.Html
import android.text.Spanned
import android.text.TextWatcher
import android.util.TypedValue
import android.view.Gravity
import android.view.View
@ -23,15 +22,10 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager.widget.ViewPager
import com.airbnb.lottie.LottieAnimationView
import com.facebook.drawee.view.SimpleDraweeView
import com.gh.common.DefaultUrlHandler
import com.gh.common.constant.Config
import com.gh.common.constant.Constants
import com.gh.common.view.CenterImageSpan
import com.gh.common.view.CustomLinkMovementMethod
import com.gh.common.view.ExpandTextView
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.R
import com.gh.gamecenter.WebActivity
import com.google.gson.reflect.TypeToken
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
@ -42,7 +36,6 @@ import okhttp3.MediaType
import okhttp3.RequestBody
import java.net.URI
import java.util.concurrent.TimeUnit
import java.util.regex.Pattern
import kotlin.math.abs
/**
@ -198,28 +191,6 @@ inline fun <reified T : Any> T.toJson(): String {
return GsonUtils.toJson(this)
}
fun String.insert(index: Int, string: String): String {
return this.substring(0, index) + string + this.substring(index, this.length)
}
/**
* TextView 内部处理 ul li ol 得跟 Android 版本走,这里换成专属的标签手动处理
*/
fun String.replaceUnsupportedHtmlTag(): String {
return this.replace("<ul", "<hul")
.replace("</ul>", "</hul>")
.replace("<li", "<hli")
.replace("</li>", "</hli>")
.replace("<ol", "<hol")
.replace("</ol>", "</hol>")
}
fun String.containHtmlTag(): Boolean {
val pattern = Pattern.compile("<(\"[^\"]*\"|'[^']*'|[^'\">])*>")
val matcher = pattern.matcher(this)
return matcher.find()
}
/**
* 在限定 interval 里只触发一次 action
*/
@ -314,13 +285,6 @@ fun String.subStringIfPossible(length: Int): String {
}
}
fun String.getFirstElementDividedByDivider(divider: String): String {
if (this.contains(divider)) {
return this.split(divider.toRegex()).toTypedArray()[0]
}
return this
}
fun String.copyTextAndToast(toastText: String = "复制成功") {
val application = HaloApp.getInstance().application
val cmb = application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
@ -478,75 +442,6 @@ fun TextView.setTextChangedListener(action: (s: CharSequence, start: Int, before
})
}
/**
* 拦截 TextView 中的 Url Span用应用内页面的形式打开链接
* @param shrankText 未展开时的文字
* @param expandedText 展开后的文字
*/
fun ExpandTextView.setTextWithInterceptingInternalUrl(shrankText: CharSequence, expandedText: CharSequence) {
var shrankSsb = shrankText.interceptUrlSpanAndRoundImageSpan()
var expandedSsb = expandedText.interceptUrlSpanAndRoundImageSpan()
// 去掉旧版本 Android 系统 [Html.FROM_HTML_MODE_LEGACY] 产生的两个换行符 (丑陋的代码)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
while (shrankSsb.contains("\n\n")) {
val index = shrankSsb.indexOf("\n\n", 0, true)
shrankSsb = SpannableStringBuilder(shrankSsb.subSequence(0, index)).append(shrankSsb.subSequence(index + "\n".length, shrankSsb.length))
}
while (expandedSsb.contains("\n\n")) {
val index = expandedSsb.indexOf("\n\n", 0, true)
expandedSsb = SpannableStringBuilder(expandedSsb.subSequence(0, index)).append(expandedSsb.subSequence(index + "\n".length, expandedSsb.length))
}
}
// 去掉多余的 P 标签换行
if (expandedSsb.endsWith("\n", true)) {
expandedSsb = SpannableStringBuilder((expandedSsb.subSequence(0, expandedSsb.length - "\n".length)))
}
movementMethod = CustomLinkMovementMethod.getInstance()
shrankSsb = TextHelper.updateSpannableStringWithHighlightedSpan(context, shrankSsb, highlightedTextClickListener = null)
expandedSsb = TextHelper.updateSpannableStringWithHighlightedSpan(context, expandedSsb, highlightedTextClickListener = null)
setShrankTextAndExpandedText(shrankSsb, expandedSsb)
}
fun CharSequence.interceptUrlSpanAndRoundImageSpan(): SpannableStringBuilder {
return SpannableStringBuilder.valueOf(this).apply {
getSpans(0, length, URLSpan::class.java).forEach {
setSpan(
object : ClickableSpan() {
override fun updateDrawState(ds: TextPaint) {
super.updateDrawState(ds)
ds.color = ContextCompat.getColor(HaloApp.getInstance().application, R.color.theme_font)
ds.isUnderlineText = false
}
override fun onClick(widget: View) {
if (!DefaultUrlHandler.interceptUrl(widget.context, it.url, "")) {
widget.context.startActivity(WebActivity.getIntent(widget.context, it.url, true))
}
}
},
getSpanStart(it),
getSpanEnd(it),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
removeSpan(it)
}
getSpans(0, length, ImageSpan::class.java).forEach {
setSpan(
CenterImageSpan(it.drawable),
getSpanStart(it),
getSpanEnd(it),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
removeSpan(it)
}
}
}
fun Int.toColor(): Int {
return ContextCompat.getColor(HaloApp.getInstance().application, this)
}
@ -578,20 +473,7 @@ inline fun Context.doOnMainProcessOnly(f: () -> Unit) {
if (processName == null || BuildConfig.APPLICATION_ID == processName) {
f.invoke()
} else {
tryWithDefaultCatch {
Utils.log("Block one useless sub process method call from ${Thread.currentThread().stackTrace[3].methodName} -> ${Thread.currentThread().stackTrace[2].methodName}.")
}
}
}
inline fun doOnMainProcessOnly(f: () -> Unit) {
val processName = PackageUtils.obtainProcessName(HaloApp.getInstance().application)
if (processName == null || BuildConfig.APPLICATION_ID == processName) {
f.invoke()
} else {
tryWithDefaultCatch {
Utils.log("Block one useless sub process method call from ${Thread.currentThread().stackTrace[3].methodName} -> ${Thread.currentThread().stackTrace[2].methodName}.")
}
Utils.log("Block one useless sub process method call.")
}
}
@ -680,30 +562,4 @@ fun LottieAnimationView.doOnAnimationEnd(action: () -> Unit) {
}
})
}
/**
* 检查内容是否一致
* @return true:相同 false:不同
*/
fun List<String>?.checkSameFromStringArray(check2: List<String>?): Boolean {
if (this == check2) {
return true
}
if (this == null && check2 == null) {
return true
}
if (this == null || check2 == null) {
return false
}
if (this.size != check2.size) {
return false
}
for (tag in this) {
if (!check2.contains(tag)) return false
}
for (tag in check2) {
if (!this.contains(tag)) return false
}
return true
}

View File

@ -1,183 +0,0 @@
package com.gh.common.util
import android.text.Editable
import android.text.Html.TagHandler
import android.text.Spanned
import android.text.style.BulletSpan
import android.text.style.LeadingMarginSpan
import android.util.Log
import org.xml.sax.XMLReader
import java.util.*
/**
* Implements support for ordered (`<ol>`) and unordered (`<ul>`) lists in to Android TextView.
*
*
* This can be used as follows:<br></br>
* `textView.setText(Html.fromHtml("<ul><li>item 1</li><li>item 2</li></ul>", null, new HtmlListTagHandler()));`
*
*
* Implementation based on code by Juha Kuitunen (https://bitbucket.org/Kuitsi/android-textview-html-list),
* released under Apache License v2.0. Refactored & improved by Matthias Stevens (InThePocket.mobi).
*
*
* **Known issues:**
* * The indentation on nested `<ul>`s isn't quite right (TODO fix this)
* * the `start` attribute of `<ol>` is not supported. Doing so is tricky because
* [Html.TagHandler.handleTag] does not expose tag attributes.
* The only way to do it would be to use reflection to access the attribute information kept by the XMLReader
* (see: http://stackoverflow.com/a/24534689/1084488).
*
* https://bitbucket.org/Kuitsi/android-textview-html-list/src/master/app/src/main/java/fi/iki/kuitsi/listtest/MyTagHandler.java
*
*/
class ExtraTagHandler : TagHandler {
/**
* Keeps track of lists (ol, ul). On bottom of Stack is the outermost list
* and on top of Stack is the most nested list
*/
private val lists = Stack<ListTag>()
/**
* @see android.text.Html.TagHandler.handleTag
*/
override fun handleTag(opening: Boolean, tag: String, output: Editable, xmlReader: XMLReader) {
if (UL_TAG.equals(tag, ignoreCase = true)) {
if (opening) { // handle <ul>
lists.push(Ul())
} else { // handle </ul>
lists.pop()
}
} else if (OL_TAG.equals(tag, ignoreCase = true)) {
if (opening) { // handle <ol>
lists.push(Ol()) // use default start index of 1
} else { // handle </ol>
lists.pop()
}
} else if (LI_TAG.equals(tag, ignoreCase = true)) {
if (opening) { // handle <li>
lists.peek().openItem(output)
} else { // handle </li>
lists.peek().closeItem(output, lists.size)
}
} else {
Log.d("TagHandler", "Found an unsupported tag $tag")
}
}
/**
* Abstract super class for [Ul] and [Ol].
*/
private abstract class ListTag {
/**
* Opens a new list item.
*
* @param text
*/
open fun openItem(text: Editable) {
if (text.length > 0 && text[text.length - 1] != '\n') {
text.append("\n")
}
val len = text.length
text.setSpan(this, len, len, Spanned.SPAN_MARK_MARK)
}
/**
* Closes a list item.
*
* @param text
* @param indentation
*/
fun closeItem(text: Editable, indentation: Int) {
if (text.length > 0 && text[text.length - 1] != '\n') {
text.append("\n")
}
val replaces = getReplaces(text, indentation)
val len = text.length
val listTag = getLast(text)
val where = text.getSpanStart(listTag)
text.removeSpan(listTag)
if (where != len) {
for (replace in replaces) {
text.setSpan(replace, where, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
}
}
protected abstract fun getReplaces(text: Editable?, indentation: Int): Array<Any>
/**
* Note: This knows that the last returned object from getSpans() will be the most recently added.
*
* @see Html
*/
private fun getLast(text: Spanned): ListTag? {
val listTags = text.getSpans(0, text.length, ListTag::class.java)
return if (listTags.size == 0) {
null
} else listTags[listTags.size - 1]
}
}
/**
* Class representing the unordered list (`<ul>`) HTML tag.
*/
private class Ul : ListTag() {
override fun getReplaces(text: Editable?, indentation: Int): Array<Any> {
// Nested BulletSpans increases distance between BULLET_SPAN and text, so we must prevent it.
var bulletMargin = INDENT_PX
if (indentation > 1) {
bulletMargin = INDENT_PX - BULLET_SPAN.getLeadingMargin(true)
if (indentation > 2) {
// This get's more complicated when we add a LeadingMarginSpan into the same line:
// we have also counter it's effect to BulletSpan
bulletMargin -= (indentation - 2) * LIST_ITEM_INDENT_PX
}
}
return arrayOf(
LeadingMarginSpan.Standard(LIST_ITEM_INDENT_PX * (indentation - 1)),
BulletSpan(bulletMargin)
)
}
}
/**
* Class representing the ordered list (`<ol>`) HTML tag.
*/
private class Ol
/**
* Creates a new `<ul>` with start index of 1.
*/ @JvmOverloads constructor(private var nextIdx: Int = 1) : ListTag() {
override fun openItem(text: Editable) {
super.openItem(text)
text.append(Integer.toString(nextIdx++)).append(". ")
}
override fun getReplaces(text: Editable?, indentation: Int): Array<Any> {
var numberMargin = LIST_ITEM_INDENT_PX * (indentation - 1)
if (indentation > 2) {
// Same as in ordered lists: counter the effect of nested Spans
numberMargin -= (indentation - 2) * LIST_ITEM_INDENT_PX
}
return arrayOf(LeadingMarginSpan.Standard(numberMargin))
}
/**
* Creates a new `<ul>` with given start index.
*
* @param nextIdx
*/
}
companion object {
private const val OL_TAG = "hol"
private const val UL_TAG = "hul"
private const val LI_TAG = "hli"
/**
* List indentation in pixels. Nested lists use multiple of this.
*/
private const val INDENT_PX = 10
private const val LIST_ITEM_INDENT_PX = INDENT_PX * 2
private val BULLET_SPAN = BulletSpan(INDENT_PX)
}
}

View File

@ -1,28 +1,19 @@
package com.gh.common.util
import android.annotation.SuppressLint
import android.content.Context
import android.text.TextUtils
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.retrofit.BiResponse
import com.gh.gamecenter.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import io.reactivex.schedulers.Schedulers
/**
* 首页补充游戏库辅助类
*/
object GameSubstituteRepositoryHelper {
object GameRepositoryHelper {
private const val KEY_GAME_REPOSITORY = "game_substitute_repository"
private var mSubstitutableGameIdSet = hashSetOf<String>()
private var mApi = RetrofitManager.getInstance(HaloApp.getInstance().application).api
private val mSensitiveApi = RetrofitManager.getInstance(HaloApp.getInstance().application).sensitiveApi
private var mApplicationContext = HaloApp.getInstance().application
private const val KEY_GAME_REPOSITORY = "game_repository"
var gameCollectionList: List<SubjectEntity> = arrayListOf()
@ -34,8 +25,11 @@ object GameSubstituteRepositoryHelper {
* 获取游戏补充库
*/
@JvmStatic
fun updateGameSubstituteRepository() {
mSensitiveApi.reserveColumns
fun getGameRepository(context: Context) {
RetrofitManager.getInstance(context)
.api
.reserveColumns
.subscribeOn(Schedulers.io())
.subscribe(object : Response<List<SubjectEntity>>() {
override fun onResponse(response: List<SubjectEntity>?) {
@ -44,41 +38,27 @@ object GameSubstituteRepositoryHelper {
updateGameRepository(response)
}
})
}
@JvmStatic
@SuppressLint("CheckResult")
fun updateSubstitutableGames() {
mApplicationContext.doOnMainProcessOnly {
val single = if (UserManager.getInstance().isLoggedIn) {
mApi.getIdListOfPlayedGames(UserManager.getInstance().userId, Utils.getTime(mApplicationContext))
} else {
mApi.getIdListOfDownloadedGames(HaloApp.getInstance().gid, Utils.getTime(mApplicationContext))
}
single.subscribeOn(Schedulers.io()).subscribe(object : BiResponse<List<String>>() {
override fun onSuccess(data: List<String>) {
mSubstitutableGameIdSet = data.toHashSet()
}
})
}
}
/**
* 刷新内存中的游戏库即从 SP 中再读一次
*/
@JvmStatic
fun refreshRepositoryFromLocal() = loadSavedRepository()
fun refreshGameRepository() = loadSavedRepository()
private fun loadSavedRepository() {
gameCollectionList = SPUtils.getString(KEY_GAME_REPOSITORY).toObject() ?: arrayListOf()
}
private fun updateGameRepository(subjects: List<SubjectEntity>?) {
fun updateGameRepository(subjects: List<SubjectEntity>?) {
if (subjects == null) return
SPUtils.setString(KEY_GAME_REPOSITORY, subjects.toJson())
gameCollectionList = subjects
}
/**
@ -86,7 +66,7 @@ object GameSubstituteRepositoryHelper {
* @param collectionId 补充游戏库相应专题 ID
* @param gameIdList 该专题里已经包含的游戏 ID 列表
*/
private fun getOneUniqueGame(collectionId: String?, gameIdList: HashSet<String>): GameEntity? {
fun getOneUniqueGame(collectionId: String?, gameIdList: HashSet<String>): GameEntity? {
collectionId?.let {
val collection = gameCollectionList.find { it.id == collectionId }
collection?.let {
@ -102,13 +82,10 @@ object GameSubstituteRepositoryHelper {
return null
}
/**
* 替换游戏包括 已安装历史下载历史已安装等类型
*/
fun replaceGames(gameList: MutableList<GameEntity>,
alreadyDisplayedGameIdSet: HashSet<String>,
relatedCollectionId: String,
shouldLogReplaceEvent: Boolean) {
fun replaceInstalledApp(gameList: MutableList<GameEntity>,
alreadyDisplayedGameIdSet: HashSet<String>,
relatedCollectionId: String,
shouldLogReplaceEvent: Boolean) {
val positionOfTheGameToReplaceList = arrayListOf<Int>()
// 标记需要替换的已安装游戏
@ -119,32 +96,23 @@ object GameSubstituteRepositoryHelper {
continue
}
var isThisPositionLabeled = false
// 从 游戏ID 判断当前游戏是否需要被替换
if (mSubstitutableGameIdSet.contains(game.id)) {
positionOfTheGameToReplaceList.add(index)
isThisPositionLabeled = true
}
var isThisPositionAdded = false
// 检查是否已安装该游戏里同包名的 APK
if (!isThisPositionLabeled) {
for (apk in game.getApk()) {
if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {
// 将该位置的游戏标记为需要替换
positionOfTheGameToReplaceList.add(index)
isThisPositionLabeled = true
break
}
for (apk in game.getApk()) {
if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {
// 将该位置的游戏标记为需要替换
positionOfTheGameToReplaceList.add(index)
isThisPositionAdded = true
break
}
}
// 若此游戏所包含的 apk 没有已安装,那么再检查是否已安装有预设相关包名
if (!isThisPositionLabeled) {
if (!isThisPositionAdded) {
var relatedPackageList = arrayListOf<String>()
for (entity in PackageHelper.relatedPackageList) {
if (entity.gameId == game.id) {
relatedPackageList = ArrayList(entity.packages!!)
relatedPackageList = ArrayList(entity.packages)
break
}
}
@ -171,17 +139,14 @@ object GameSubstituteRepositoryHelper {
}
}
private fun isThisGameUnique(game: GameEntity, gameIdList: HashSet<String>): Boolean {
// 判断该游戏是否出现在已安装列表
if (mSubstitutableGameIdSet.contains(game.id)) return false
// 该补充游戏是否已经存在关联关系
private fun isThisGameUnique(game: GameEntity, gameIdList: HashSet<String>): Boolean {
// 若该补充游戏已经存在关联关系,判定为非唯一
for (relatedId in game.relatedGameIds!!) {
if (gameIdList.contains(relatedId)) {
return false
}
}
for (apk in game.getApk()) {
// 检查本地是否已安装该游戏,已过滤那部分框架服务的包名
if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {

View File

@ -1,50 +0,0 @@
package com.gh.common.util
import com.gh.gamecenter.entity.GameEntity
import com.gh.gamecenter.entity.HomePluggableFilterEntity
import com.gh.gamecenter.room.AppDatabase
import com.halo.assistant.HaloApp
object HomePluggableHelper {
private val mHomePluggableFilterDao = AppDatabase.getInstance(HaloApp.getInstance().application).homePluggableFilterDao()
@JvmStatic
fun setHomePluggableFilterData(gameEntity: GameEntity, isNever: Boolean) {
val apkList = gameEntity.getApk()
if (apkList.isNotEmpty()) {
val apk = apkList.first()
val tag = if (isNever) "never" else apk.version ?: ""
mHomePluggableFilterDao.addData(HomePluggableFilterEntity(pkgName = apk.packageName, tag = tag, active = isNever))
}
}
@JvmStatic
fun showHomePluggable(gameEntity: GameEntity): Boolean {
val apkList = gameEntity.getApk()
if (apkList.isNotEmpty()) {
val apk = apkList.first()
val filterData = mHomePluggableFilterDao.getDataByPkgName(apk.packageName)
if (filterData?.active == true) {
val filterTag = filterData.tag
return filterTag != "never" && apk.version != filterTag
}
}
return true
}
@JvmStatic
fun getPermanentInactivePluggablePackage() = mHomePluggableFilterDao.getDataByTag("never")
@JvmStatic
fun activationFilterData() {
val filterList = mHomePluggableFilterDao.getDataByActive(false)
if (filterList != null) {
for (entity in filterList) {
entity.active = true
}
mHomePluggableFilterDao.addData(filterList)
}
}
}

View File

@ -283,7 +283,7 @@ public class LogUtils {
uploadToReservation(object);
}
private static void uploadToCommunity(JSONObject object) {
uploadToCommunity(object, false);
}
@ -419,89 +419,4 @@ public class LogUtils {
}
uploadVideoStreaming(object);
}
private static void uploadShare(JSONObject object) {
Meta meta = MetaUtil.INSTANCE.getMeta();
JSONObject metaObject = new JSONObject();
try {
metaObject.put("android_id", meta.getAndroid_id());
metaObject.put("android_sdk", meta.getAndroid_sdk());
metaObject.put("android_version", meta.getAndroid_version());
metaObject.put("appVersion", meta.getAppVersion());
metaObject.put("channel", meta.getChannel());
metaObject.put("gid", meta.getGid());
metaObject.put("imei", meta.getImei());
metaObject.put("mac", meta.getMac());
metaObject.put("manufacturer", meta.getManufacturer());
metaObject.put("model", meta.getModel());
metaObject.put("network", meta.getNetwork());
metaObject.put("os", meta.getOs());
metaObject.put("userId", meta.getUserId());
object.put("event", "SHARE");
object.put("meta", metaObject);
object.put("timestamp", System.currentTimeMillis() / 1000);
} catch (JSONException e) {
e.printStackTrace();
}
if (BuildConfig.DEBUG) {
Utils.log("LogUtils->" + object.toString());
}
LoghubUtils.log(object, "event", false);
}
public static void uploadShareEnter(String entrance, String url, String title, String summary, String resourceId) {
JSONObject object = new JSONObject();
JSONObject payloadObject = new JSONObject();
try {
object.put("action", "entrance_source");
payloadObject.put("entrance", entrance);
payloadObject.put("url", url);
payloadObject.put("title", title);
payloadObject.put("summary", summary);
payloadObject.put("resource_id", resourceId);
object.put("payload", payloadObject);
} catch (JSONException e) {
e.printStackTrace();
}
uploadShare(object);
}
public static void uploadShareType(String shareType, String entrance, String url, String title, String summary, String resourceId) {
JSONObject object = new JSONObject();
JSONObject payloadObject = new JSONObject();
try {
object.put("action", "share_type");
payloadObject.put("share_type", shareType);
payloadObject.put("entrance", entrance);
payloadObject.put("url", url);
payloadObject.put("title", title);
payloadObject.put("summary", summary);
payloadObject.put("resource_id", resourceId);
object.put("payload", payloadObject);
} catch (JSONException e) {
e.printStackTrace();
}
uploadShare(object);
}
public static void uploadShareResult(String shareType, String entrance, String shareResult, String url, String title, String summary, String resourceId) {
JSONObject object = new JSONObject();
JSONObject payloadObject = new JSONObject();
try {
object.put("action", "share_result");
payloadObject.put("share_type", shareType);
payloadObject.put("entrance", entrance);
payloadObject.put("share_result", shareResult);
payloadObject.put("url", url);
payloadObject.put("title", title);
payloadObject.put("summary", summary);
payloadObject.put("resource_id", resourceId);
object.put("payload", payloadObject);
} catch (JSONException e) {
e.printStackTrace();
}
uploadShare(object);
}
}

View File

@ -23,7 +23,7 @@ import com.tencent.tauth.Tencent
import com.tencent.tauth.UiError
import org.json.JSONException
import org.json.JSONObject
import java.lang.ref.WeakReference
/**
* 第三方登录辅助类
@ -37,12 +37,12 @@ object LoginHelper {
private var mTencent: Tencent // QQ
private var mIWXAPI: IWXAPI // 微信
private var mSsoHandler: WeakReference<SsoHandler>? = null // 微博
private var mSsoHandler: SsoHandler? = null // 微博 // TODO 完成回调时清掉这个 handler
private var mQqLoginListener: IUiListener
private var mAccessToken: Oauth2AccessToken? = null // weibo
private var mLoginCallback: WeakReference<LoginCallback>? = null
private var mLoginCallback: LoginCallback? = null
init {
val context = HaloApp.getInstance().application.applicationContext
@ -64,11 +64,11 @@ object LoginHelper {
content.put("access_token_expire", Utils.getTime(context) + o.getLong("expires_in"))
content.put("access_token", o.getString("access_token"))
mLoginCallback?.get()?.onLoginSuccess(LoginTag.qq, content) // 回调QQ登录成功
mLoginCallback?.onLoginSuccess(LoginTag.qq, content) // 回调QQ登录成功
} catch (e: JSONException) {
val errorString = "QQ登录数据回调异常$e"
mLoginCallback?.get()?.onLoginFailure(LoginTag.qq, errorString) // 回调QQ登录失败
mLoginCallback?.onLoginFailure(LoginTag.qq, errorString) // 回调QQ登录失败
Utils.log(errorString)
e.printStackTrace()
@ -77,12 +77,12 @@ object LoginHelper {
}
override fun onCancel() {
mLoginCallback?.get()?.onLoginFailure(LoginTag.qq, "登录取消")
mLoginCallback?.onLoginFailure(LoginTag.qq,"登录取消")
Utils.log("QQ 登录取消")
}
override fun onError(p0: UiError?) {
mLoginCallback?.get()?.onLoginFailure(LoginTag.qq, "登录失败")
mLoginCallback?.onLoginFailure(LoginTag.qq,"登录失败")
Utils.log("QQ 登录失败")
}
}
@ -99,23 +99,23 @@ object LoginHelper {
@JvmStatic
fun onWechatLoginSuccess(content: JSONObject) {
mLoginCallback?.get()?.onLoginSuccess(LoginTag.wechat, content)
mLoginCallback?.onLoginSuccess(LoginTag.wechat, content)
}
@JvmStatic
fun onWechatLoginFailure(error: String) {
mLoginCallback?.get()?.onLoginFailure(LoginTag.wechat, error)
mLoginCallback?.onLoginFailure(LoginTag.wechat, error)
}
@JvmStatic
fun onWeiboLoginCallback(requestCode: Int, resultCode: Int, data: Intent?) {
mSsoHandler?.get()?.authorizeCallBack(requestCode, resultCode, data)
mSsoHandler?.authorizeCallBack(requestCode, resultCode, data)
}
// QQ登录
@JvmStatic
fun loginWithQQ(loginCallback: LoginCallback, activity: Activity) {
mLoginCallback = WeakReference(loginCallback)
mLoginCallback = loginCallback
if (!mTencent.isSessionValid) {
Utils.log("QQLogin")
mTencent.login(activity, "all", mQqLoginListener)
@ -132,7 +132,7 @@ object LoginHelper {
// 微信登录
@JvmStatic
fun loginWithWechat(loginCallback: LoginCallback) {
mLoginCallback = WeakReference(loginCallback)
mLoginCallback = loginCallback
val register = mIWXAPI.registerApp(Config.WECHAT_APPID)
val req = SendAuth.Req()
@ -149,9 +149,9 @@ object LoginHelper {
// 微博登录
@JvmStatic
fun loginWithWeibo(loginCallback: LoginCallback, context: Activity) {
mLoginCallback = WeakReference(loginCallback)
mSsoHandler = WeakReference(SsoHandler(context))
mSsoHandler?.get()?.authorizeClientSso(object : WbAuthListener {
mLoginCallback = loginCallback
mSsoHandler = SsoHandler(context)
mSsoHandler?.authorizeClientSso(object : WbAuthListener {
override fun onSuccess(token: Oauth2AccessToken?) {
token?.let {
RuntimeUtils.getInstance().runOnUiThread {
@ -170,17 +170,17 @@ object LoginHelper {
content.put("access_token_expire", Utils.getTime(context) + token.expiresTime)
content.put("refresh_token", token.refreshToken)
// content.put("refresh_token_expire", Utils.getTime(mContext) + 86400 * 30); // refresh_token 有效期30天
mLoginCallback?.get()?.onLoginSuccess(LoginTag.weibo, content)// 微博 登录回调
mLoginCallback?.onLoginSuccess(LoginTag.weibo, content)// 微博 登录回调
}
}
}
override fun onFailure(p0: WbConnectErrorMessage?) {
mLoginCallback?.get()?.onLoginFailure(LoginTag.weibo, "微博登录需要客户端支持,请先安装微博")
mLoginCallback?.onLoginFailure(LoginTag.weibo, "微博登录需要客户端支持,请先安装微博")
}
override fun cancel() {
mLoginCallback?.get()?.onLoginFailure(LoginTag.weibo, "取消授权")
mLoginCallback?.onLoginFailure(LoginTag.weibo, "取消授权")
}
})
// 第一次启动本应用AccessToken 不可用

View File

@ -4,8 +4,6 @@ import android.content.Context;
import android.graphics.Color;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.gh.gamecenter.R;
import com.gh.gamecenter.entity.NewsEntity;
import com.gh.gamecenter.retrofit.Response;
@ -80,7 +78,7 @@ public class NewsUtils {
/**
* 设置新闻类型
*/
public static void setNewsType(TextView textView, @Nullable String type, int priority, int position) {
public static void setNewsType(TextView textView, String type, int priority, int position) {
if (priority != 0) {
if (position == 0) {
textView.setText(R.string.article_top);
@ -94,7 +92,7 @@ public class NewsUtils {
}
textView.setTextColor(Color.WHITE);
switch (type != null ? type : "") {
switch (type) {
case "活动":
textView.setBackgroundResource(R.drawable.textview_orange_style);
break;

View File

@ -1,88 +0,0 @@
package com.gh.common.util
import com.alibaba.sdk.android.oss.ClientConfiguration
import com.alibaba.sdk.android.oss.ClientException
import com.alibaba.sdk.android.oss.OSSClient
import com.alibaba.sdk.android.oss.ServiceException
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback
import com.alibaba.sdk.android.oss.common.auth.OSSStsTokenCredentialProvider
import com.alibaba.sdk.android.oss.internal.OSSAsyncTask
import com.alibaba.sdk.android.oss.model.PutObjectRequest
import com.alibaba.sdk.android.oss.model.PutObjectResult
import com.gh.gamecenter.entity.OssEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
object OssUploadUtils {
//上传文件类型
enum class UploadType(val value: String) {
GAME("game")//后缀apk
}
//获取Oss配置
private fun getOssUpdateConfig(type: UploadType): Single<OssEntity> {
return RetrofitManager.getInstance(HaloApp.getInstance().application)
.api
.getOssUpdateConfig(type.value)
.subscribeOn(Schedulers.io())
}
//异步上传文件
@JvmStatic
fun uploadFile(path: String, uploadType: UploadType, listener: OnUploadFileListener?): Disposable {
return getOssUpdateConfig(uploadType)
.subscribeOn(Schedulers.io())
.flatMap { mOssEntity ->
Single.create<String> {
val conf = ClientConfiguration()
conf.connectionTimeout = 15 * 1000
conf.socketTimeout = 15 * 1000
conf.maxConcurrentRequest = 5
conf.maxErrorRetry = 2
val credentialProvider = OSSStsTokenCredentialProvider(mOssEntity.accessKeyId, mOssEntity.accessKeySecret, mOssEntity.securityToken)
val oss = OSSClient(HaloApp.getInstance().application, mOssEntity.endPoint, credentialProvider, conf)
// 构造上传请求
val put = PutObjectRequest(mOssEntity.bucket, mOssEntity.key, path)
val task: OSSAsyncTask<*> = oss.asyncPutObject(put, object : OSSCompletedCallback<PutObjectRequest?, PutObjectResult> {
override fun onSuccess(request: PutObjectRequest?, result: PutObjectResult) {
it.onSuccess(mOssEntity.domain + mOssEntity.key)
}
override fun onFailure(request: PutObjectRequest?, clientExcepion: ClientException?, serviceException: ServiceException?) {
clientExcepion?.printStackTrace()
serviceException?.printStackTrace()
if (serviceException != null) {
it.onError(Throwable(message = clientExcepion?.message + "/" + serviceException.message))
}
}
})
}
}.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { url, throwable ->
if (url.isNotEmpty()) {
listener?.onSuccess(url)
return@subscribe
}
if (throwable != null) {
listener?.onError(throwable)
}
}
}
interface OnUploadFileListener {
fun onSuccess(url: String)
fun onError(e: Throwable?)
}
}

View File

@ -1,135 +0,0 @@
package com.gh.common.util;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.Html;
import android.widget.TextView;
import androidx.core.content.res.ResourcesCompat;
import com.gh.gamecenter.R;
import com.halo.assistant.HaloApp;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.Target;
import com.squareup.picasso.Transformation;
public class PicassoImageGetter implements Html.ImageGetter {
private TextView textView = null;
public PicassoImageGetter() {
}
public PicassoImageGetter(TextView target) {
textView = target;
}
@Override
public Drawable getDrawable(String source) {
BitmapDrawablePlaceHolder drawable = new BitmapDrawablePlaceHolder();
Context context = HaloApp.getInstance().getApplication();
Picasso.with(context)
.load(source)
.transform(new CircleTransformation())
.placeholder(ResourcesCompat.getDrawable(context.getResources(), R.drawable.personal_user_default_icon, context
.getTheme()))
.into(drawable);
return drawable;
}
private class BitmapDrawablePlaceHolder extends BitmapDrawable implements Target {
protected Drawable drawable;
@Override
public void draw(final Canvas canvas) {
if (drawable != null) {
Paint.FontMetricsInt fmPaint = textView.getPaint().getFontMetricsInt();
float fontHeight = fmPaint.descent - fmPaint.ascent;
float textSize = textView.getTextSize();
if (fontHeight - textSize > 0) {
canvas.translate((fontHeight - textSize) / 2, 0);
}
drawable.draw(canvas);
}
}
@SuppressWarnings("SuspiciousNameCombination")
public void setDrawable(Drawable drawable) {
try {
this.drawable = drawable;
Paint.FontMetricsInt fmPaint = textView.getPaint().getFontMetricsInt();
int fontHeight = fmPaint.descent - fmPaint.ascent;
int textSize = (int) textView.getTextSize();
drawable.setBounds(0, 0, textSize, textSize);
setBounds(0, 0, fontHeight, fontHeight);
if (textView != null) {
textView.setText(textView.getText());
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
setDrawable(new BitmapDrawable(HaloApp.getInstance()
.getApplication()
.getResources(), bitmap));
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
setDrawable(placeHolderDrawable);
}
}
private class CircleTransformation implements Transformation {
@Override
public Bitmap transform(Bitmap source) {
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
if (squaredBitmap != source) {
source.recycle();
}
Bitmap.Config config = source.getConfig() != null ? source.getConfig() : Bitmap.Config.ARGB_8888;
Bitmap bitmap = Bitmap.createBitmap(size, size, config);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
BitmapShader shader = new BitmapShader(squaredBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
squaredBitmap.recycle();
return bitmap;
}
@Override
public String key() {
return "circle";
}
}
}

View File

@ -36,23 +36,43 @@ import io.reactivex.schedulers.Schedulers;
import retrofit2.HttpException;
public class PlatformUtils {
private static PlatformUtils mInstance;
private Context context;
private ArrayMap<String, String> platformMap;
private ArrayMap<String, Integer> platformPicMap;
private ArrayMap<String, String> platformPicUrlMap;
private ArrayMap<String, String> platformColorMap;
private boolean isCheck = false;
private boolean isUpdate = false;
private PlatformUtils(Context con) {
this.context = con.getApplicationContext();
initMap();
}
private void initMap() {
ArrayMap<String, Integer> platformPicMap = new ArrayMap<>();
platformPicMap.put("360", R.drawable.platform_360);
platformPicMap.put("37wan", R.drawable.platform_37);
platformPicMap.put("91", R.drawable.platform_91);
platformPicMap.put("9u", R.drawable.platform_9u);
platformPicMap.put("anzhi", R.drawable.platform_anzhi);
platformPicMap.put("baidu", R.drawable.platform_baidu);
platformPicMap.put("dangle", R.drawable.platform_dl);
platformPicMap.put("ewan", R.drawable.platform_ewan);
platformPicMap.put("gf", R.drawable.platform_gf);
platformPicMap.put("gf-w", R.drawable.platform_gfw);
platformPicMap.put("huawei", R.drawable.platform_hw);
platformPicMap.put("mi", R.drawable.platform_mi);
platformPicMap.put("oppo", R.drawable.platform_oppo);
platformPicMap.put("ouwan", R.drawable.platform_ouwan);
platformPicMap.put("pps", R.drawable.platform_pps);
platformPicMap.put("vivo", R.drawable.platform_vivo);
platformPicMap.put("wdj", R.drawable.platform_wdj);
ArrayMap<String, String> platformColorMap = new ArrayMap<>();
platformColorMap.put("360", "#218FA4");
platformColorMap.put("37wan", "#F5BD20");
@ -71,20 +91,24 @@ public class PlatformUtils {
platformColorMap.put("pps", "#FF8C27");
platformColorMap.put("vivo", "#3FA5E3");
platformColorMap.put("wdj", "#5ABA3F");
ArrayMap<String, String> platformMap = new ArrayMap<>();
ArrayMap<String, String> platformPicUrlMap = new ArrayMap<>();
SharedPreferences sharedPreferences = context.getSharedPreferences("gh_platform", Context.MODE_PRIVATE);
SharedPreferences sharedPreferences = context.getSharedPreferences(
"gh_platform", Context.MODE_PRIVATE);
Set<String> set = sharedPreferences.getStringSet("platform", null);
if (set == null) {
Properties properties = new Properties();
try {
properties.load(context.getAssets().open("platform.properties"));
properties
.load(context.getAssets().open("platform.properties"));
Set<String> pset = new HashSet<>();
for (Object object : properties.keySet()) {
platformMap.put(object.toString(), (String) properties.get(object));
pset.add(object.toString() + "=" + (String) properties.get(object) + "=" + "=");
platformMap.put(object.toString(),
(String) properties.get(object));
pset.add(object.toString() + "="
+ (String) properties.get(object) + "=" + "=");
}
Editor editor = sharedPreferences.edit();
editor.putStringSet("platform", pset);
@ -109,10 +133,11 @@ public class PlatformUtils {
// checkPlatformPic(urls);
}
}
updatePlatform(platformMap, platformPicUrlMap, platformColorMap);
updatePlatform(platformMap, platformPicMap, platformPicUrlMap,
platformColorMap);
}
private void checkPlatformPic(final ArrayList<String> urls) {
isCheck = true;
File file = new File(FileUtils.getPlatformPicDir(context));
@ -129,41 +154,53 @@ public class PlatformUtils {
}
}
if (urls.size() != 0) {
AppExecutor.getIoExecutor().execute(() -> {
int success = 0;
for (int i = 0; i < urls.size(); i++) {
String url = urls.get(i);
String savePath = FileUtils.getPlatformPicDir(context) + File.separator + url
.substring(url.lastIndexOf("/") + 1);
int code = FileUtils.downloadFile(url, savePath);
if (code == HttpURLConnection.HTTP_OK) {
success++;
AppExecutor.getIoExecutor().execute(new Runnable() {
@Override
public void run() {
int success = 0;
for (int i = 0; i < urls.size(); i++) {
String url = urls.get(i);
String savePath = FileUtils.getPlatformPicDir(context)
+ File.separator
+ url.substring(url.lastIndexOf("/") + 1);
int code = FileUtils.downloadFile(url, savePath);
if (code == HttpURLConnection.HTTP_OK) {
success++;
}
}
if (success == urls.size()) {
Handler handler = new Handler(context.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
EventBus.getDefault().post(new EBReuse("PlatformChanged"));
}
});
}
isCheck = false;
}
if (success == urls.size()) {
Handler handler = new Handler(context.getMainLooper());
handler.post(() -> EventBus.getDefault().post(new EBReuse("PlatformChanged")));
}
isCheck = false;
});
} else {
isCheck = false;
}
}
private void updatePlatform(ArrayMap<String, String> pMap, ArrayMap<String, String> pUMap, ArrayMap<String, String> pCMap) {
private void updatePlatform(ArrayMap<String, String> pMap,
ArrayMap<String, Integer> pPMap, ArrayMap<String, String> pUMap,
ArrayMap<String, String> pCMap) {
platformMap = pMap;
platformPicMap = pPMap;
platformPicUrlMap = pUMap;
platformColorMap = pCMap;
}
public static PlatformUtils getInstance(Context context) {
if (mInstance == null) {
mInstance = new PlatformUtils(context);
}
return mInstance;
}
public String getPlatformColor(String platform) {
if ("".equals(platform) || "官方版".equals(platform)) {
return "#BB3D42";
@ -172,16 +209,26 @@ public class PlatformUtils {
if (color != null) {
return color;
}
int themeColor = ContextCompat.getColor(HaloApp.getInstance()
.getApplication(), R.color.theme);
int themeColor = ContextCompat.getColor(HaloApp.getInstance().getApplication(), R.color.theme);
return String.format("#%06X", 0xFFFFFF & themeColor);
}
public int getPlatformPic(String platform) {
if ("".equals(platform) || "官方版".equals(platform)) {
return R.drawable.platform_gf;
}
Integer id = platformPicMap.get(platform);
if (id != null) {
return id;
}
return 0;
}
public String getPlatformPicUrl(String platform) {
return platformPicUrlMap.get(platform);
}
public String getPlatformName(String platform) {
if ("".equals(platform) || "官方版".equals(platform)) {
return "官方版";
@ -195,40 +242,38 @@ public class PlatformUtils {
}
return platform;
}
public void getPlatform() {
if (isUpdate) {
return;
}
isUpdate = true;
RetrofitManager.getInstance(context)
.getApi()
.getGamePlatform()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<List<PlatformEntity>>() {
@Override
public void onResponse(List<PlatformEntity> response) {
Set<String> platformSet = new HashSet<>();
for (PlatformEntity platformEntity : response) {
platformSet.add(platformEntity.toString());
RetrofitManager.getInstance(context).getApi().getGamePlatform()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<List<PlatformEntity>>() {
@Override
public void onResponse(List<PlatformEntity> response) {
Set<String> platformSet = new HashSet<>();
for (PlatformEntity platformEntity : response) {
platformSet.add(platformEntity.toString());
}
SharedPreferences sp = context.getSharedPreferences("gh_platform", Context.MODE_PRIVATE);
sp.edit().putStringSet("platform", platformSet).apply();
initMap();
EventBus.getDefault().post(new EBReuse("PlatformChanged"));
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
String today = format.format(new Date());
sp.edit().putString("refresh_time", today).apply();
isUpdate = false;
}
SharedPreferences sp = context.getSharedPreferences("gh_platform", Context.MODE_PRIVATE);
sp.edit().putStringSet("platform", platformSet).apply();
initMap();
EventBus.getDefault().post(new EBReuse("PlatformChanged"));
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
String today = format.format(new Date());
sp.edit().putString("refresh_time", today).apply();
isUpdate = false;
}
@Override
public void onFailure(HttpException e) {
isUpdate = false;
}
});
@Override
public void onFailure(HttpException e) {
isUpdate = false;
}
});
}
}

View File

@ -48,9 +48,9 @@ object ReservationHelper {
ReservationRepository.removeReservationFromMemoryAndRefresh(game.id)
if (deleteReservation) {
// MtaHelper.onEvent("预约游戏", "取消预约", game.name)
MtaHelper.onEvent("预约游戏", "取消预约", game.name)
} else {
// MtaHelper.onEvent("预约游戏", "删除预约", game.name)
MtaHelper.onEvent("预约游戏", "删除预约", game.name)
}
refreshCallback.onCallback()
@ -73,10 +73,9 @@ object ReservationHelper {
"暂不删除",
{ emptyCallback.onCallback() },
null,
trackMtaEvent = true
// , mtaEvent = "预约游戏",
// mtaKey = "删除预约弹窗"
)
trackMtaEvent = true,
mtaEvent = "预约游戏",
mtaKey = "删除预约弹窗")
}
@JvmStatic
@ -89,10 +88,9 @@ object ReservationHelper {
"暂不取消",
{ emptyCallback.onCallback() },
null,
trackMtaEvent = true
// , mtaEvent = "预约游戏",
// mtaKey = "取消预约弹窗"
)
trackMtaEvent = true,
mtaEvent = "预约游戏",
mtaKey = "取消预约弹窗")
}

View File

@ -31,7 +31,6 @@ import com.facebook.imagepipeline.image.CloseableImage;
import com.gh.common.constant.Config;
import com.gh.gamecenter.R;
import com.gh.gamecenter.WeiBoShareActivity;
import com.gh.gamecenter.entity.ShareEntity;
import com.gh.gamecenter.eventbus.EBShare;
import com.lightgame.utils.Utils;
import com.sina.weibo.sdk.WbSdk;
@ -84,39 +83,24 @@ public class ShareUtils {
R.drawable.share_cancel_logo
};
public enum ShareEntrance {
news("资讯文章"),
game("游戏详情"), // 普通游戏
plugin("游戏详情"), // 插件游戏
tools("工具箱"),
askInvite("邀请回答"),
askNormal("问题详情"), //问答问题
answerNormal("回答详情"), //问答答案
shareGh("APP分享"),
communityArticle("文章详情"),
video("视频"),
web("web链接");
private String name;
ShareEntrance(String name) {
this.name = name;
}
public String getName() {
return name;
}
public enum ShareType {
news,
game, // 普通游戏
plugin, // 插件游戏
tools,
askInvite,
askNormal, // 问答问题/答案
shareGh,
communityArticle,
video
}
private String[] arrLabel = {"微信好友", "朋友圈", "QQ好友", "QQ空间", "新浪微博", "短信", "复制链接", "取消"};
private WeakReference<PopupWindow> popupWindow;
private PopupWindow popupWindow;
private ShareEntrance mShareEntrance;
public static String shareType = "";//分享类型(事件上报用)
public static ShareEntrance shareEntrance;//分享入口(事件上报和视频分享统计用)
public static String resourceId = "";//分享内容的id(事件上报用)
public static ShareEntity shareEntity;//分享信息(事件上报用)
private ShareType mShareType;
public static ShareType shareType;//全局保存shareType分享成功后判断分享的类型
private WeakReference<Activity> mActivity;
@ -126,31 +110,25 @@ public class ShareUtils {
@Override
public void onComplete(Object o) {
Utils.toast(mContext, R.string.share_success_hint);
EventBus.getDefault().post(new EBShare(ShareUtils.shareEntrance));
LogUtils.uploadShareResult(shareType, ShareUtils.shareEntrance.getName(), "success",
ShareUtils.shareEntity.getShareUrl(), ShareUtils.shareEntity.getShareTitle(), ShareUtils.shareEntity.getSummary(), ShareUtils.resourceId);
EventBus.getDefault().post(new EBShare(ShareUtils.shareType));
}
@Override
public void onError(UiError uiError) {
Utils.toast(mContext, R.string.share_fail_hint);
LogUtils.uploadShareResult(shareType, ShareUtils.shareEntrance.getName(), "fail",
ShareUtils.shareEntity.getShareUrl(), ShareUtils.shareEntity.getShareTitle(), ShareUtils.shareEntity.getSummary(), ShareUtils.resourceId);
}
@Override
public void onCancel() {
Utils.toast(mContext, R.string.share_cancel_hint);
LogUtils.uploadShareResult(shareType, ShareUtils.shareEntrance.getName(), "cancel",
ShareUtils.shareEntity.getShareUrl(), ShareUtils.shareEntity.getShareTitle(), ShareUtils.shareEntity.getSummary(), ShareUtils.resourceId);
}
};
private ShareUtils(Context context) {
mTencent = Tencent.createInstance(Config.TENCENT_APPID, context); //初始化QQ分享
mIWXAPI = WXAPIFactory.createWXAPI(context, Config.WECHAT_APPID); //初始化微信分享
WbSdk.install(context, new AuthInfo(context, Config.WEIBO_APPKEY, "http://www.sina.com", WEIBO_SCOPE));
mContext = context.getApplicationContext();
mTencent = Tencent.createInstance(Config.TENCENT_APPID, mContext); //初始化QQ分享
mIWXAPI = WXAPIFactory.createWXAPI(mContext, Config.WECHAT_APPID); //初始化微信分享
WbSdk.install(mContext, new AuthInfo(mContext, Config.WEIBO_APPKEY, "http://www.sina.com", WEIBO_SCOPE));
}
public static ShareUtils getInstance(Context context) {
@ -175,20 +153,17 @@ public class ShareUtils {
return false;
}
public void showShareWindowsCallback(Activity activity, View view, String url, String icon, String shareTitle, String shareSummary, ShareEntrance shareEntrance, String id, ShareCallBack callBack) {
public void showShareWindowsCallback(Activity activity, View view, String url, String icon, String shareTitle, String shareSummary, ShareType shareType, ShareCallBack callBack) {
if (activity.isFinishing()) return;
this.mActivity = new WeakReference<>(activity);
this.shareIcon = icon;
this.shareUrl = url;
this.mSummary = shareSummary;
this.mTitle = shareTitle;
this.mShareEntrance = shareEntrance;
ShareUtils.shareEntrance = mShareEntrance;
ShareUtils.resourceId = id;
ShareUtils.shareEntity = new ShareEntity(shareUrl, mTitle, mSummary);
LogUtils.uploadShareEnter(mShareEntrance.getName(), shareUrl, mTitle, mSummary, id);
this.mShareType = shareType;
ShareUtils.shareType = mShareType;
View contentView = View.inflate(mActivity.get(), R.layout.share_popup_layout, null);
View contentView = View.inflate(activity, R.layout.share_popup_layout, null);
contentView.setFocusable(true);
contentView.setFocusableInTouchMode(true);
RecyclerView shareRecyclerView = contentView.findViewById(R.id.share_rv);
@ -216,7 +191,7 @@ public class ShareUtils {
}
});
if (mShareEntrance == ShareEntrance.shareGh) {
if (mShareType == ShareType.shareGh) {
RelativeLayout layout = (RelativeLayout) view;
layout.addView(contentView);
arrLabel[6] = "邮件";
@ -231,41 +206,41 @@ public class ShareUtils {
arrLogo[7] = R.drawable.share_cancel_logo;
}
popupWindow = new WeakReference<>(new SharePopupWindow(contentView, LinearLayout.LayoutParams.MATCH_PARENT
, LinearLayout.LayoutParams.MATCH_PARENT, true));
popupWindow.get().setAnimationStyle(R.style.popwindow_exit_only_anim_style);
popupWindow = new SharePopupWindow(contentView, LinearLayout.LayoutParams.MATCH_PARENT
, LinearLayout.LayoutParams.MATCH_PARENT, true);
popupWindow.setAnimationStyle(R.style.popwindow_exit_only_anim_style);
//解决PopupWindow无法覆盖状态栏
popupWindow.get().setClippingEnabled(false);
popupWindow.setClippingEnabled(false);
int bottomLocation = -DisplayUtils.retrieveNavigationHeight(activity);
if (!DisplayUtils.isNavigationBarShow(activity)) {
bottomLocation = 0;
}
try {
popupWindow.get().showAtLocation(view, Gravity.NO_GRAVITY, 0, bottomLocation);
popupWindow.showAtLocation(view, Gravity.NO_GRAVITY, 0, bottomLocation);
} catch (Exception e) {
e.printStackTrace();
}
contentView.setOnClickListener(v -> popupWindow.get().dismiss());
contentView.setOnClickListener(v -> popupWindow.dismiss());
contentView.setOnKeyListener((v, keyCode, event) -> {
if (keyCode == KeyEvent.KEYCODE_BACK
&& event.getRepeatCount() == 0
&& popupWindow != null
&& popupWindow.get().isShowing()) {
&& popupWindow.isShowing()) {
if (callBack != null) {
callBack.onCancel();
}
popupWindow.get().dismiss();
popupWindow.dismiss();
}
return false;
});
}
public void showShareWindows(Activity activity, View view, String url, String icon, String shareTitle, String shareSummary, ShareEntrance shareEntrance, String id) {
showShareWindowsCallback(activity, view, url, icon, shareTitle, shareSummary, shareEntrance, id, null);
public void showShareWindows(Activity activity, View view, String url, String icon, String shareTitle, String shareSummary, ShareType shareType) {
showShareWindowsCallback(activity, view, url, icon, shareTitle, shareSummary, shareType, null);
}
//QQ分享
@ -273,12 +248,11 @@ public class ShareUtils {
Utils.toast(mContext, R.string.share_skip);
Bundle params = new Bundle();
switch (mShareEntrance) {
switch (mShareType) {
case plugin:
mSummary += "(光环加速版)";
break;
case askNormal:
case answerNormal:
case video:
case communityArticle:
mTitle += " - 光环助手";
@ -297,8 +271,8 @@ public class ShareUtils {
mTencent.shareToQQ(activity, params, QqShareListener);
}
if (mShareEntrance != ShareEntrance.shareGh) {
popupWindow.get().dismiss();
if (mShareType != ShareType.shareGh) {
popupWindow.dismiss();
}
}
@ -315,12 +289,11 @@ public class ShareUtils {
WXMediaMessage msg = new WXMediaMessage(webpage);
webpage.webpageUrl = shareUrl;
switch (mShareEntrance) {
switch (mShareType) {
case plugin:
mSummary += "(光环加速版)";
break;
case askNormal:
case answerNormal:
case video:
case communityArticle:
mTitle += " - 光环助手";
@ -337,8 +310,8 @@ public class ShareUtils {
req.scene = SendMessageToWX.Req.WXSceneSession;
loadBitMap(shareIcon, msg, req);
if (mShareEntrance != ShareEntrance.shareGh) {
popupWindow.get().dismiss();
if (mShareType != ShareType.shareGh) {
popupWindow.dismiss();
}
}
@ -350,14 +323,14 @@ public class ShareUtils {
ImageUtils.display(mContext, iconUrl, new BaseBitmapDataSubscriber() {
@Override
protected void onNewResultImpl(Bitmap bitmap) {
if (mShareEntrance == ShareEntrance.video) {
if (mShareType == ShareType.video) {
// 分享类型为视频时裁为正方形
int dimension = Math.min(bitmap.getWidth(), bitmap.getHeight());
bitmap = ThumbnailUtils.extractThumbnail(bitmap, dimension, dimension);
}
Bitmap compressBp = compressBitmap(bitmap);
if (mShareEntrance == ShareEntrance.askNormal || mShareEntrance == ShareEntrance.askInvite) {
if (mShareType == ShareType.askNormal || mShareType == ShareType.askInvite) {
msg.thumbData = ImageUtils.bmpToByteArray(compressBp, true);
} else {
Bitmap resultBp = addBackGround(compressBp);
@ -424,12 +397,11 @@ public class ShareUtils {
Utils.toast(mContext, R.string.share_skip);
Bundle params = new Bundle();
switch (mShareEntrance) {
switch (mShareType) {
case plugin:
mSummary += "(光环加速版)";
break;
case askNormal:
case answerNormal:
case video:
case communityArticle:
mTitle += " - 光环助手";
@ -453,8 +425,8 @@ public class ShareUtils {
mTencent.shareToQzone(activity, params, QqShareListener);
}
if (mShareEntrance != ShareEntrance.shareGh) {
popupWindow.get().dismiss();
if (mShareType != ShareType.shareGh) {
popupWindow.dismiss();
}
}
@ -472,7 +444,7 @@ public class ShareUtils {
webpage.webpageUrl = shareUrl;
switch (mShareEntrance) {
switch (mShareType) {
case plugin:
msg.title = mSummary + "(光环加速版)";
break;
@ -480,7 +452,6 @@ public class ShareUtils {
msg.title = mSummary;
break;
case askNormal:
case answerNormal:
case video:
case communityArticle:
msg.title = mTitle + " - 光环助手";
@ -498,8 +469,8 @@ public class ShareUtils {
req.scene = SendMessageToWX.Req.WXSceneTimeline;
loadBitMap(shareIcon, msg, req);
if (mShareEntrance != ShareEntrance.shareGh) {
popupWindow.get().dismiss();
if (mShareType != ShareType.shareGh) {
popupWindow.dismiss();
}
}
@ -514,23 +485,22 @@ public class ShareUtils {
shareIcon,
mTitle,
mSummary,
mShareEntrance.toString());
mShareType.toString());
activity.startActivity(intent);
}
if (mShareEntrance != ShareEntrance.shareGh) {
popupWindow.get().dismiss();
if (mShareType != ShareType.shareGh) {
popupWindow.dismiss();
}
}
//短信分享
private void shortMessageShare() {
String smsBody;
switch (mShareEntrance) {
switch (mShareType) {
case news:
case tools:
case web:
smsBody = mTitle + shareUrl;
break;
case plugin:
@ -544,7 +514,6 @@ public class ShareUtils {
break;
case askInvite:
case askNormal:
case answerNormal:
case video:
case communityArticle:
smsBody = mTitle + " - 光环助手" + shareUrl;
@ -562,20 +531,18 @@ public class ShareUtils {
e.printStackTrace();
}
if (mShareEntrance != ShareEntrance.shareGh) {
popupWindow.get().dismiss();
if (mShareType != ShareType.shareGh) {
popupWindow.dismiss();
}
}
//复制文字链接
private void copyLink(String copyContent) {
shareType = "copy_link";
LogUtils.uploadShareType(shareType, shareEntrance.getName(), shareUrl, mTitle, mSummary, resourceId);
ClipboardManager cmb = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
cmb.setText(copyContent);
if (mShareEntrance != ShareEntrance.shareGh) {
if (mShareType != ShareType.shareGh) {
Utils.toast(mContext, "复制成功");
popupWindow.get().dismiss();
popupWindow.dismiss();
} else {
Utils.toast(mContext, "复制成功,请到微信/QQ粘贴分享");
}
@ -600,7 +567,7 @@ public class ShareUtils {
holder.shareLogo.setImageResource(arrLogo[position]);
holder.shareLabel.setText(arrLabel[position]);
holder.itemView.setOnClickListener(v -> {
if (mShareEntrance == ShareEntrance.shareGh) {
if (mShareType == ShareUtils.ShareType.shareGh) {
MtaHelper.onEvent("我的光环_新", "分享光环", arrLabel[position]);
}
if (listener != null) {
@ -608,33 +575,23 @@ public class ShareUtils {
}
switch (holder.getPosition()) {
case 0:
shareType = "wechat_friend";
MtaHelper.onEvent("内容分享", "微信好友", mTitle);
LogUtils.uploadShareType(shareType, shareEntrance.getName(), shareUrl, mTitle, mSummary, resourceId);
wechatShare();
break;
case 1:
shareType = "wechat_moment";
MtaHelper.onEvent("内容分享", "微信朋友圈", mTitle);
LogUtils.uploadShareType(shareType, shareEntrance.getName(), shareUrl, mTitle, mSummary, resourceId);
wechatMomentsShare();
break;
case 2:
shareType = "qq_friend";
MtaHelper.onEvent("内容分享", "QQ好友", mTitle);
LogUtils.uploadShareType(shareType, shareEntrance.getName(), shareUrl, mTitle, mSummary, resourceId);
qqShare();
break;
case 3:
shareType = "qq_zone";
MtaHelper.onEvent("内容分享", "QQ空间", mTitle);
LogUtils.uploadShareType(shareType, shareEntrance.getName(), shareUrl, mTitle, mSummary, resourceId);
qZoneShare();
break;
case 4:
shareType = "sina_weibo";
MtaHelper.onEvent("内容分享", "新浪微博", mTitle);
LogUtils.uploadShareType(shareType, shareEntrance.getName(), shareUrl, mTitle, mSummary, resourceId);
sinaWeiboShare();
break;
case 5:
@ -643,11 +600,11 @@ public class ShareUtils {
break;
case 6:
MtaHelper.onEvent("内容分享", "复制链接", mTitle);
if (mShareEntrance == ShareEntrance.askInvite) {
if (mShareType == ShareType.askInvite) {
copyLink(mTitle + " - 光环助手" + shareUrl);
} else if (mShareEntrance == ShareEntrance.askNormal || mShareEntrance == ShareEntrance.answerNormal) {
} else if (mShareType == ShareType.askNormal) {
copyLink(shareUrl);
} else if (mShareEntrance != ShareEntrance.shareGh) {
} else if (mShareType != ShareType.shareGh) {
copyLink(shareUrl);
} else {
try {
@ -660,11 +617,10 @@ public class ShareUtils {
}
break;
case 7:
if (mShareEntrance != ShareEntrance.shareGh) {
popupWindow.get().dismiss();
if (mShareType != ShareType.shareGh) {
popupWindow.dismiss();
} else {
shareType = "copy_link";
LogUtils.uploadShareType(shareType, shareEntrance.getName(), shareUrl, mTitle, mSummary, resourceId);
copyLink("推荐光环助手,绿色安全的手游加速助手:" + shareUrl);
}
break;
}
@ -699,12 +655,12 @@ public class ShareUtils {
void onCancel();
}
private static class SharePopupWindow extends PopupWindow {
SharePopupWindow(View contentView, int width, int height, boolean focusable) {
super(contentView, width, height, focusable);
}
@Override
public void dismiss() {
View backgroundView = getContentView().findViewById(R.id.share_container);
@ -714,5 +670,5 @@ public class ShareUtils {
getContentView().postDelayed(super::dismiss, 0);
}
}
}

View File

@ -2,7 +2,6 @@ package com.gh.common.util
import android.content.Context
import android.content.SharedPreferences
import com.google.gson.reflect.TypeToken
import com.halo.assistant.HaloApp
object SPUtils {
@ -91,20 +90,7 @@ object SPUtils {
@JvmStatic
fun getStringSet(key: String): Set<String> {
return sp.getStringSet(key, HashSet()) ?: HashSet()
}
@JvmStatic
fun setMap(key: String, map: Map<String, String>) {
val mapJson = GsonUtils.toJson(map)
setString(key, mapJson)
}
@JvmStatic
fun getMap(key: String): MutableMap<String, String> {
val mapJson = getString(key)
val type = object : TypeToken<MutableMap<String, String>>() {}.type
return GsonUtils.gson.fromJson(mapJson, type) ?: mutableMapOf()
return sp.getStringSet(key, HashSet())?: HashSet()
}
@JvmStatic

View File

@ -12,7 +12,6 @@ import android.text.style.StyleSpan
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import com.gh.common.view.CenterImageSpan
import com.halo.assistant.HaloApp
class SpanBuilder(content: String) {
private var spannableString: SpannableStringBuilder = SpannableStringBuilder(content)
@ -59,8 +58,8 @@ class SpanBuilder(content: String) {
}
//添加图标
fun image(start: Int, end: Int, @DrawableRes res: Int): SpanBuilder {
val imageSpan = CenterImageSpan(HaloApp.getInstance().application, res)
fun image(context: Context, start: Int, end: Int, @DrawableRes res: Int): SpanBuilder {
val imageSpan = CenterImageSpan(context, res)
spannableString.setSpan(imageSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
return this
}

View File

@ -35,19 +35,4 @@ public class SpeedUtils {
}
}
public static String getRemainSecondTime(long totalSize, long currentSize, long speed) {
long remainSize = totalSize - currentSize;
long remainTime;
if (speed != 0) {
remainTime = remainSize / speed;
} else {
return "-s";
}
int hour = (int) (remainTime / 3600);
remainTime = (remainTime - hour * 3660);
int minute = (int) (remainTime / 60);
int second = (int) (remainTime - minute * 60);
return second + "s";
}
}

View File

@ -66,7 +66,7 @@ public class TagUtils {
return;
}
isUpdate = true;
RetrofitManager.getInstance(context).getSensitiveApi().getTags()
RetrofitManager.getInstance(context).getApi().getTags()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<List<TagEntity>>() {

View File

@ -133,38 +133,23 @@ object TextHelper {
Utils.toast(application, "已复制:$arg")
}
}): SpannableStringBuilder {
val builder = SpannableStringBuilder(text)
return updateSpannableStringWithHighlightedSpan(context, builder, wrapper, highlightColorId, highlightedTextClickListener)
}
fun updateSpannableStringWithHighlightedSpan(
context: Context,
ssb: SpannableStringBuilder,
wrapper: String = "###",
@ColorRes
highlightColorId: Int = R.color.theme_font,
highlightedTextClickListener: SimpleCallback<String>? = object : SimpleCallback<String> {
override fun onCallback(arg: String) {
val application = HaloApp.getInstance().application
val cmb = application.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
cmb.text = arg
Utils.toast(application, "已复制:$arg")
}
}): SpannableStringBuilder {
if (ssb.endsWith(wrapper)) {
var modifiedText = text
if (modifiedText.endsWith(wrapper)) {
// 若高亮符在最后一位就在后面加一个空格,避免整行都能点击
ssb.append(" ")
modifiedText = "$modifiedText "
}
val sBuilder = SpannableStringBuilder(modifiedText)
val wrapperTextLength = wrapper.length
val matcher = Pattern.compile("$wrapper(.+?)$wrapper", Pattern.DOTALL).matcher(ssb)
val matcher = Pattern.compile("$wrapper(.+?)$wrapper", Pattern.DOTALL).matcher(modifiedText)
val pair = TreeMap<Int, Int>()
while (matcher.find()) {
// 保存起始位置和结束位置
pair[matcher.start(1)] = matcher.end(1)
ssb.setSpan(object : ClickableSpan() {
sBuilder.setSpan(object : ClickableSpan() {
override fun updateDrawState(ds: TextPaint) {
super.updateDrawState(ds)
ds.color = ContextCompat.getColor(context, highlightColorId)
@ -189,12 +174,12 @@ object TextHelper {
val end = reversePair[key]
end?.let {
ssb.replace(end, end + wrapperTextLength, "")
ssb.replace(key - wrapperTextLength, key, "")
sBuilder.replace(end, end + wrapperTextLength, "")
sBuilder.replace(key - wrapperTextLength, key, "")
}
}
return ssb
return sBuilder
}
/**

View File

@ -60,7 +60,7 @@ object TimeUtils {
/**
* 判断时间戳是多少天前
*/
fun getBeforeDays(timestamp: Long): Int {
fun getBeforeDays(timestamp: Long):Int{
var days: Long = 0
val format = SimpleDateFormat("yyyyMMdd HH:mm", Locale.getDefault())
try {
@ -73,15 +73,4 @@ object TimeUtils {
return days.toInt()
}
/**
* 格式化视频时长
*/
@JvmStatic
fun formatVideoDuration(length: Long): String {
val minute = length / 60
val second = length % 60
return String.format(Locale.CHINA, "%02d:%02d", minute, second)
}
}

View File

@ -7,13 +7,10 @@ import com.halo.assistant.HaloApp
object ToastUtils {
/** 之前显示的内容 */
private var mOldMsg: String? = null
/** Toast对象 */
private var mToast: Toast? = null
/** 第一次时间 */
private var mOneTime: Long = 0
/** 第二次时间 */
private var mTwoTime: Long = 0
@ -22,34 +19,19 @@ object ToastUtils {
* @param message
*/
fun showToast(message: String) {
showToast(message, -1)
}
/**
* 显示Toast
* @param message
* @param gravity
*/
fun showToast(message: String, gravity: Int = -1, yOffset: Int = 0) {
if (mToast == null) {
mToast = Toast.makeText(HaloApp.getInstance().application, message, Toast.LENGTH_SHORT)
if (gravity != -1) mToast!!.setGravity(gravity, 0, yOffset) else
mToast!!.setGravity(DisplayUtils.getToastDefaultGravity(), 0, DisplayUtils.getToastOffset())
mToast!!.show()
mOneTime = System.currentTimeMillis()
} else {
mTwoTime = System.currentTimeMillis()
if (message == mOldMsg) {
if (mTwoTime - mOneTime > Toast.LENGTH_SHORT) {
if (gravity != -1) mToast!!.setGravity(gravity, 0, yOffset) else
mToast!!.setGravity(DisplayUtils.getToastDefaultGravity(), 0, DisplayUtils.getToastOffset())
mToast!!.show()
}
} else {
mOldMsg = message
mToast!!.setText(message)
if (gravity != -1) mToast!!.setGravity(gravity, 0, yOffset) else
mToast!!.setGravity(DisplayUtils.getToastDefaultGravity(), 0, DisplayUtils.getToastOffset())
mToast!!.show()
}
}

View File

@ -1,127 +0,0 @@
package com.gh.common.util;
import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
public class UriUtils {
@SuppressLint("NewApi")
public static String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.parseLong(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{split[1]};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
* @param selection (Optional) Filter used in the query.
* @param selectionArgs (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
*/
private static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {column};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
private static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
private static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
private static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
}

View File

@ -1,18 +0,0 @@
package com.gh.common.videolog
import androidx.room.*
@Dao
interface VideoRecordDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertMany(eventList: List<VideoRecordEntity>)
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(event: VideoRecordEntity)
@Query("SELECT * FROM VideoRecord")
fun getAll(): List<VideoRecordEntity>
@Delete
fun deleteMany(eventList: List<VideoRecordEntity>)
}

View File

@ -1,18 +0,0 @@
package com.gh.common.videolog
import android.os.Parcelable
import androidx.annotation.Keep
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.android.parcel.Parcelize
import java.util.*
@Keep
@Parcelize
@Entity(tableName = "VideoRecord")
data class VideoRecordEntity(
@PrimaryKey
val id: String = UUID.randomUUID().toString(),
var videoId: String = "",
var time: Long = 0
) : Parcelable

View File

@ -1,76 +0,0 @@
package com.gh.common.videolog
import android.annotation.SuppressLint
import android.app.Application
import com.gh.common.util.toRequestBody
import com.gh.gamecenter.manager.UserManager
import com.gh.gamecenter.retrofit.BiResponse
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.room.AppDatabase
import com.halo.assistant.HaloApp
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
import java.util.concurrent.Executors
object VideoRecordUtils {
private const val STORE_SIZE = 20
private lateinit var mApplication: Application
private val videoRecordSet by lazy { hashSetOf<VideoRecordEntity>() }
private val videoRecordExecutor by lazy { Executors.newSingleThreadExecutor() }
private val videoRecordDao by lazy { AppDatabase.getInstance(mApplication).videoRecordDao() }
@JvmStatic
fun init(application: Application) {
mApplication = application
videoRecordExecutor.execute {
val recordList = videoRecordDao.getAll()
videoRecordSet.addAll(recordList)
}
}
fun log(videoId: String) {
videoRecordExecutor.execute {
try {
val entity = VideoRecordEntity(videoId = videoId, time = System.currentTimeMillis() / 1000L)
videoRecordSet.add(entity)
videoRecordDao.insert(entity)
} catch (e: Exception) {
e.printStackTrace()
}
if (videoRecordSet.size >= STORE_SIZE) {
commitVideoRecord()
}
}
}
fun commitVideoRecord() {
if (videoRecordSet.isEmpty()) return
videoRecordExecutor.execute {
uploadVideoRecord()
val exposureList = videoRecordSet.toList()
videoRecordSet.removeAll(exposureList)
videoRecordDao.deleteMany(exposureList)
}
}
@SuppressLint("CheckResult")
fun uploadVideoRecord(time: Long = 0) {
if (!UserManager.getInstance().isLoggedIn) return
val requestMap = HashMap<String, Any>()
val videoIds = videoRecordSet.toList().map { it.videoId }
requestMap["g_id"] = HaloApp.getInstance().gid
requestMap["time"] = time
requestMap["video_id"] = videoIds
RetrofitManager.getInstance(HaloApp.getInstance().application).api
.uploadVideoLog(requestMap.toRequestBody())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<ResponseBody>() {
override fun onSuccess(data: ResponseBody) {
}
})
}
}

View File

@ -190,8 +190,8 @@ class AdBannerView : LinearLayout {
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val ad = mDatas[position % mDatas.size]
val view = holder.itemView as ImageView
Picasso.with(context).load(ad.image).into(view)
val view = holder.itemView as SimpleDraweeView
ImageUtils.display(view,ad.image)
holder.itemView.setOnClickListener {
onItemClick?.invoke(position % mDatas.size)
}

View File

@ -21,10 +21,8 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
: ConstraintLayout(context, attrs, defStyleAttr) {
private var mSizeTv: TextView
var newestTv: TextView
var ratingTv: TextView //目前只在专题页面显示
var recommendedTv: TextView
private var mNewestTv: TextView
private var mRecommendedTv: TextView
private var mOnConfigFilterSetupListener: OnConfigFilterSetupListener? = null
@ -32,33 +30,23 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
View.inflate(context, R.layout.layout_config_filter, this)
mSizeTv = findViewById(R.id.size_tv)
newestTv = findViewById(R.id.newest_tv)
ratingTv = findViewById(R.id.rating_tv)
recommendedTv = findViewById(R.id.recommended_tv)
mNewestTv = findViewById(R.id.newest_tv)
mRecommendedTv = findViewById(R.id.recommended_tv)
mSizeTv.setOnClickListener {
showSelectionPopupWindow(this, mSizeTv, mSizeTv.text.toString())
}
ratingTv.setOnClickListener {
mOnConfigFilterSetupListener?.onSetupSortType(SortType.RATING)
toggleHighlightedTextView(ratingTv, true)
toggleHighlightedTextView(newestTv, false)
toggleHighlightedTextView(recommendedTv, false)
}
newestTv.setOnClickListener {
mNewestTv.setOnClickListener {
mOnConfigFilterSetupListener?.onSetupSortType(SortType.NEWEST)
toggleHighlightedTextView(ratingTv, false)
toggleHighlightedTextView(newestTv, true)
toggleHighlightedTextView(recommendedTv, false)
toggleHighlightedTextView(mNewestTv, true)
toggleHighlightedTextView(mRecommendedTv, false)
}
recommendedTv.setOnClickListener {
mRecommendedTv.setOnClickListener {
mOnConfigFilterSetupListener?.onSetupSortType(SortType.RECOMMENDED)
toggleHighlightedTextView(ratingTv, false)
toggleHighlightedTextView(newestTv, false)
toggleHighlightedTextView(recommendedTv, true)
toggleHighlightedTextView(mNewestTv, false)
toggleHighlightedTextView(mRecommendedTv, true)
}
}
@ -66,7 +54,7 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
mOnConfigFilterSetupListener = onConfigFilterSetupListener
}
fun toggleHighlightedTextView(targetTextView: TextView, highlightIt: Boolean) {
private fun toggleHighlightedTextView(targetTextView: TextView, highlightIt: Boolean) {
if (highlightIt) {
targetTextView.background = ContextCompat.getDrawable(targetTextView.context, R.drawable.text_blue_background)
targetTextView.setTextColor(Color.WHITE)
@ -152,8 +140,7 @@ class ConfigFilterView @JvmOverloads constructor(context: Context, attrs: Attrib
enum class SortType {
RECOMMENDED,
NEWEST,
RATING
NEWEST
}
enum class SortSize(val value: String) {

View File

@ -31,7 +31,7 @@ class EllipsizeTextView : AppCompatTextView {
val width = paint.measureText(text.subSequence(secondLastLineEnd, lastLineEnd).toString() + "...")
if (width > layout.width) {
val lastLineText = text.subSequence(secondLastLineEnd, lastLineEnd)
for (i in lastLineText.indices) {
for (i in 0 until lastLineText.length) {
val cutWidth = paint.measureText(text.subSequence(secondLastLineEnd, lastLineEnd - i).toString() + "...")
if (cutWidth <= layout.width) {
charSequence = text.subSequence(0, lastLineEnd - i)
@ -41,7 +41,7 @@ class EllipsizeTextView : AppCompatTextView {
}
} else {
charSequence = text.subSequence(0, lastLineEnd)
text = SpannableStringBuilder().append(charSequence).append("...")
text = charSequence
}
}
}

View File

@ -8,132 +8,100 @@ import android.text.Layout;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.view.View;
import com.gh.gamecenter.R;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.core.content.ContextCompat;
import com.gh.gamecenter.R;
public class ExpandTextView extends AppCompatTextView {
private CharSequence mSnapshotText;
private String mEndText = "...";
private CharSequence mShrankText = "";
private String mExpandText = mEndText + "全文";
private CharSequence mExpandedText = "";
private boolean mUseGradientAlphaEndText = false;
private boolean mShowExpandTextRegardlessOfMaxLines = false; // 不论文字超过 maxLines 都显示"...展开"文字
private int mMaxLines = 3; // 由于sdk版本限制(getMaxLines) 这里设置默认值
private static int DEFAULT_ADDITIONAL_END_TEXT_COUNT = 2;
private boolean mInitLayout = false;
private boolean mIsExpanded = false; // 位于 recyclerView 时需要自行在外层管理是否已展开
private ExpandCallback mExpandCallback;
private SelfCalculateMaxLinesCallback mMaxLinesCalculatedCallback;
private Rect mLastVisibleLineRect;
private Rect mLastActualLineRect;
private static int DEFAULT_ADDITIONAL_END_TEXT_COUNT = 2;
public ExpandTextView(Context context) {
super(context);
}
public ExpandTextView(Context context, AttributeSet attrs) {
super(context, attrs);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
mMaxLines = getMaxLines();
}
mLastVisibleLineRect = new Rect();
mLastActualLineRect = new Rect();
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ExpandTextView);
mUseGradientAlphaEndText = ta.getBoolean(R.styleable.ExpandTextView_useGradientAlphaEndText, false);
mEndText = ta.getString(R.styleable.ExpandTextView_endText) == null ? mEndText : ta.getString(R.styleable.ExpandTextView_endText);
mExpandText = ta.getString(R.styleable.ExpandTextView_expandText) == null ? mExpandText : ta.getString(R.styleable.ExpandTextView_expandText);
mExpandText = ta.getString(R.styleable.ExpandTextView_expandText) == null ? mExpandText : ta
.getString(R.styleable.ExpandTextView_expandText);
ta.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mShowExpandTextRegardlessOfMaxLines && !mIsExpanded) {
updateMaxLines();
}
setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight() - getExtraBottomPadding());
}
private void updateMaxLines() {
mMaxLines = getLineCount() - 1;
setMaxLines(mMaxLines);
mMaxLinesCalculatedCallback.onMaxLinesCalculated(mMaxLines);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mMaxLines > 0
&& ((mShowExpandTextRegardlessOfMaxLines && !mIsExpanded) || (mInitLayout && !mIsExpanded && getLineCount() > mMaxLines))) {
if (mInitLayout && !mIsExpanded && getLineCount() > mMaxLines) {
mSnapshotText = getText();
mInitLayout = false;
showExpandButton();
}
}
public void setExpandText(String text) {
public void setExpendText(String text) {
this.mExpandText = text;
}
public void setExpandCallback(ExpandCallback callback) {
this.mExpandCallback = callback;
}
/**
* 适用于不使用 maxLines 而是整段收起时的文字来确定“...更多”的位置的样式
* @param shrankText 收起时的文字 (“...更多”跟在 shrankText 后)
* @param expandedText 展开时的文字
*/
public void setShrankTextAndExpandedText(CharSequence shrankText, CharSequence expandedText) {
mShrankText = shrankText;
mExpandedText = expandedText;
mShowExpandTextRegardlessOfMaxLines = !TextUtils.isEmpty(shrankText);
if (!mIsExpanded && mShowExpandTextRegardlessOfMaxLines) {
setText(mShrankText);
} else {
setText(mExpandedText);
}
}
@Override
public void setText(CharSequence text, BufferType type) {
mInitLayout = true;
super.setText(text, type);
}
private void showExpandButton() {
String finalEndText = "";
TextPaint paint = getPaint();
Layout layout = getLayout();
int start = layout.getLineStart(0);
int lastLineEnd = layout.getLineEnd(mMaxLines - 1);
int lastLineStart = layout.getLineStart(mMaxLines - 1);
float lastLineRight = layout.getLineRight(mMaxLines - 1);
int viewWidth = getWidth() - getPaddingRight() - getPaddingLeft();
int additionalEndTextCount = 0;
float expandTextWidth;
if (mUseGradientAlphaEndText) {
additionalEndTextCount = DEFAULT_ADDITIONAL_END_TEXT_COUNT;
@ -141,15 +109,15 @@ public class ExpandTextView extends AppCompatTextView {
} else {
expandTextWidth = paint.measureText(mExpandText);
}
CharSequence content = mSnapshotText.subSequence(start, lastLineEnd);
if (viewWidth - lastLineRight > expandTextWidth) {
if (mUseGradientAlphaEndText) {
finalEndText = content.toString()
.substring(content.length() - additionalEndTextCount, content.length()) + mEndText;
.substring(content.length() - additionalEndTextCount, content.length()) + mEndText;
finalEndText = finalEndText.replace("\n", "");
content = content.subSequence(0, content.length() - additionalEndTextCount) + finalEndText + mExpandText;
} else {
content = content.toString().trim() + mExpandText;
@ -162,10 +130,10 @@ public class ExpandTextView extends AppCompatTextView {
if (mUseGradientAlphaEndText) {
subSequence = lastLineText.subSequence(0, i - additionalEndTextCount);
subSequenceWidth = paint.measureText(subSequence.toString());
finalEndText = lastLineText.subSequence(i - additionalEndTextCount, i) + mEndText;
expandTextWidth = paint.measureText(finalEndText + mExpandText);
if (viewWidth - subSequenceWidth > expandTextWidth) {
finalEndText = finalEndText.replace("\n", "");
content = mSnapshotText.subSequence(start, lastLineStart + i - additionalEndTextCount) + finalEndText + mExpandText;
@ -174,7 +142,7 @@ public class ExpandTextView extends AppCompatTextView {
} else {
subSequence = lastLineText.subSequence(0, i);
subSequenceWidth = paint.measureText(subSequence.toString());
if (viewWidth - subSequenceWidth > expandTextWidth) {
content = mSnapshotText.subSequence(start, lastLineStart + i) + mExpandText;
break;
@ -182,18 +150,18 @@ public class ExpandTextView extends AppCompatTextView {
}
}
}
SpannableStringBuilder msp = new SpannableStringBuilder(mSnapshotText);
int length = msp.length();
int expandTextStartPosition;
expandTextStartPosition = content.length() - finalEndText.length() - mExpandText.length();
expandTextStartPosition = Math.max(expandTextStartPosition, 0);
int startPosition;
startPosition = content.length() - finalEndText.length() - mExpandText.length();
startPosition = Math.max(startPosition, 0);
// 避免越界
if (expandTextStartPosition >= length) return;
msp.replace(expandTextStartPosition, length, finalEndText + mExpandText);
if (startPosition >= length) return;
msp.replace(startPosition, length, finalEndText + mExpandText);
msp.setSpan(new ClickableSpan() {
@Override
public void updateDrawState(@NonNull TextPaint ds) {
@ -201,49 +169,24 @@ public class ExpandTextView extends AppCompatTextView {
ds.setColor(ContextCompat.getColor(getContext(), R.color.theme_font));
ds.setUnderlineText(false);
}
@Override
public void onClick(@NonNull View widget) {
mIsExpanded = true;
setMaxLines(Integer.MAX_VALUE);
if (mShowExpandTextRegardlessOfMaxLines) {
setText(mExpandedText);
} else {
setText(mSnapshotText);
}
setText(mSnapshotText);
if (mExpandCallback != null) {
mExpandCallback.onExpand();
}
}
}, expandTextStartPosition + mEndText.length(), msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
int paintColor = 0;
// 找到第一个位置与 endTextStartPosition 贴合的 ForegroundSpan / ClickableSpan ,
// 获取颜色赋值给 GradientAlphaTextSpan
Object[] objects = msp.getSpans(0, expandTextStartPosition, Object.class);
if (objects.length != 0) {
for (Object span : objects) {
int startPosition = msp.getSpanStart(span);
int endPosition = msp.getSpanEnd(span);
if (expandTextStartPosition >= startPosition && expandTextStartPosition <= endPosition) {
if (span instanceof ForegroundColorSpan) {
paintColor = ((ForegroundColorSpan) span).getForegroundColor();
break;
} else if (span instanceof ClickableSpan) {
paintColor = getResources().getColor(R.color.theme_font);
break;
}
}
}
}
msp.setSpan(new GradientAlphaTextSpan(paintColor), expandTextStartPosition, expandTextStartPosition + finalEndText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}, startPosition + mEndText.length(), msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
msp.setSpan(new GradientAlphaTextSpan(), startPosition, startPosition + finalEndText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
setText(msp);
setMovementMethod(CustomLinkMovementMethod.getInstance());
}
/**
* 获取 maxLines + lineSpacingExtra + movementMethod 一起使用时产生的大小与 lineSpacingExtra 一样的底部空间
*/
@ -253,16 +196,16 @@ public class ExpandTextView extends AppCompatTextView {
int lastVisibleLineIndex = Math.min(getMaxLines(), getLineCount()) - 1;
// 获取实际文字的最后一行的 index
int lastActualLineIndex = getLineCount() - 1;
if (lastVisibleLineIndex >= 0) {
Layout layout = getLayout();
int lastVisibleLineBaseline = getLineBounds(lastVisibleLineIndex, mLastVisibleLineRect);
getLineBounds(lastActualLineIndex, mLastActualLineRect);
int heightBetweenLastVisibleLineRectAndLastActualLineRect = (mLastActualLineRect.bottom - mLastVisibleLineRect.bottom);
if (getMeasuredHeight() == getLayout().getHeight() - heightBetweenLastVisibleLineRectAndLastActualLineRect) {
result = mLastVisibleLineRect.bottom - (lastVisibleLineBaseline + layout.getPaint()
.getFontMetricsInt().descent + getPaddingBottom());
.getFontMetricsInt().descent + getPaddingBottom());
if (getLineSpacingExtra() > result) {
result = 0;
} else {
@ -272,29 +215,21 @@ public class ExpandTextView extends AppCompatTextView {
}
return result;
}
/**
* 此方法仅更改标记,不做实际展开的操作
*/
public void setIsExpanded(boolean isExpanded) {
mIsExpanded = isExpanded;
}
public void setExpandMaxLines(int maxLines) {
mMaxLines = maxLines;
setMaxLines(maxLines);
}
public void setSelfCalculateMaxLinesCallback(SelfCalculateMaxLinesCallback callback) {
mMaxLinesCalculatedCallback = callback;
}
public interface ExpandCallback {
void onExpand();
}
public interface SelfCalculateMaxLinesCallback {
void onMaxLinesCalculated(int maxLines);
}
}

View File

@ -1,32 +0,0 @@
package com.gh.common.view
import android.content.Context
import android.util.AttributeSet
import android.widget.LinearLayout
import com.gh.common.util.tryCatchInRelease
/**
* 游戏列表标签的容器(特定功能的View)
*
* 一行内,防止标签显示越界
*/
class GameTagContainerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : LinearLayout(context, attrs) {
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
super.onLayout(changed, l, t, r, b)
tryCatchInRelease {
var childContentWidth = 0
for (i in 0 until childCount) {
val tag = getChildAt(i)
val tagLp = tag.layoutParams
if (tagLp is LayoutParams) {
tag.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED)
val tagWidth = tagLp.leftMargin + tagLp.rightMargin + tag.measuredWidth
childContentWidth += tagWidth
}
}
if (childContentWidth > width && childCount > 1) {
removeViewAt(childCount - 1)
}
}
}
}

View File

@ -1,17 +1,20 @@
package com.gh.common.view
import android.graphics.*
import android.graphics.Canvas
import android.graphics.LinearGradient
import android.graphics.Paint
import android.graphics.Shader
import android.text.style.ReplacementSpan
import androidx.core.graphics.ColorUtils
class GradientAlphaTextSpan(var textColor: Int) : ReplacementSpan() {
class GradientAlphaTextSpan() : ReplacementSpan() {
override fun getSize(paint: Paint, text: CharSequence?, start: Int, end: Int, fm: Paint.FontMetricsInt?): Int {
return paint.measureText(text, start, end).toInt()
}
override fun draw(canvas: Canvas, text: CharSequence?, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint) {
val originalColor = if (textColor == 0) paint.color else textColor
val originalColor = paint.color
val originalColorWithAlphaChanged = ColorUtils.setAlphaComponent(paint.color, 1)
val textWidth = paint.measureText(text, start, end).toInt()

View File

@ -1,5 +1,4 @@
package com.gh.common.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
@ -8,8 +7,7 @@ import androidx.core.view.MotionEventCompat;
import androidx.core.view.NestedScrollingChild;
import androidx.core.view.NestedScrollingChildHelper;
import androidx.core.view.ViewCompat;
import com.gh.common.view.dsbridge.DWebView;
import wendu.dsbridge.DWebView;
public class NestedScrollWebView extends DWebView implements NestedScrollingChild {

View File

@ -25,8 +25,7 @@ import androidx.core.view.NestedScrollingParentHelper;
import androidx.core.view.ViewCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.core.view.accessibility.AccessibilityRecordCompat;
import com.gh.common.view.dsbridge.DWebView;
import wendu.dsbridge.DWebView;
/**
* Copyright (c) Tuenti Technologies. All rights reserved.

View File

@ -65,9 +65,7 @@ class WelcomeDialog : BaseDialogFragment() {
EntranceUtils.HOST_COMMUNITY -> {
DirectUtils.directToCommunity(requireContext(), CommunityEntity(mWelcomeEntity?.link!!, mWelcomeEntity?.text!!))
}
// else -> DialogUtils.showLowVersionDialog(context)
else -> DirectUtils.directToLinkPage(requireContext(), mWelcomeEntity
?: WelcomeDialogEntity(), EntranceUtils.ENTRANCE_WELCOME, "首页弹窗")
else -> DialogUtils.showLowVersionDialog(context)
}
mDismissByClickImage = true

View File

@ -7,11 +7,11 @@ import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.Interpolator;
import java.lang.reflect.Field;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import java.lang.reflect.Field;
/**
* Auto Scroll View Pager
* <ul>

View File

@ -1,11 +0,0 @@
package com.gh.common.view.dsbridge;
/**
* Created by du on 16/12/31.
*/
public interface CompletionHandler<T> {
void complete(T retValue);
void complete();
void setProgressData(T value);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +0,0 @@
package com.gh.common.view.dsbridge;
/**
* Created by du on 16/12/31.
*/
public interface OnReturnValue<T> {
void onValue(T retValue);
}

View File

@ -206,8 +206,7 @@ public class ScrollPageHelper extends PagerSnapHelper {
} else if (snapLastItem && endOfList) {
return child;
} else if (endOfList) {
// return null;
return child;
return null;
} else {
return reverseLayout ? layoutManager.findViewByPosition(firstChild - offset)
: layoutManager.findViewByPosition(firstChild + offset);
@ -263,8 +262,7 @@ public class ScrollPageHelper extends PagerSnapHelper {
} else if (snapLastItem && startOfList) {
return child;
} else if (startOfList) {
// return null;
return child;
return null;
} else {
return reverseLayout ? layoutManager.findViewByPosition(lastChild + offset)
: layoutManager.findViewByPosition(lastChild - offset);

View File

@ -8,12 +8,6 @@ import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.collection.ArrayMap;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.ProcessLifecycleOwner;
import com.gh.common.AppExecutor;
import com.gh.common.exposure.ExposureEvent;
import com.gh.common.exposure.ExposureUtils;
@ -23,15 +17,14 @@ import com.gh.common.util.DataCollectionUtils;
import com.gh.common.util.DeviceUtils;
import com.gh.common.util.DialogUtils;
import com.gh.common.util.GdtHelper;
import com.gh.common.util.HomePluggableHelper;
import com.gh.common.util.MD5Utils;
import com.gh.common.util.MtaHelper;
import com.gh.common.util.NetworkUtils;
import com.gh.common.util.PackageUtils;
import com.gh.common.util.SPUtils;
import com.gh.gamecenter.entity.ApkEntity;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.entity.GameUpdateEntity;
import com.gh.gamecenter.entity.HomePluggableFilterEntity;
import com.gh.gamecenter.entity.PluginLocation;
import com.gh.gamecenter.eventbus.EBDownloadStatus;
import com.gh.gamecenter.manager.PackagesManager;
@ -61,6 +54,11 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import androidx.annotation.Nullable;
import androidx.collection.ArrayMap;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.ProcessLifecycleOwner;
public class DownloadManager implements DownloadStatusListener {
private static DownloadManager mInstance;
@ -109,7 +107,7 @@ public class DownloadManager implements DownloadStatusListener {
public void onTaskError(DownloadEntity entity) {
// 下载进度超出是任务出错,但不需要去掉状态栏通知 https://gitlab.ghzs.com/pm/halo-app-issues/issues/496
if (entity.getStatus() == DownloadStatus.overflow) {
// MtaHelper.onEventWithBasicDeviceInfo("下载无法完成", "游戏", entity.getName());
MtaHelper.onEventWithBasicDeviceInfo("下载无法完成", "游戏", entity.getName());
} else {
downloadingMap.remove(entity.getUrl());
}
@ -140,6 +138,7 @@ public class DownloadManager implements DownloadStatusListener {
mUpdateMarks = SPUtils.getStringSet(UPDATE_IS_READ_MARK);
//TODO unregister this
DownloadStatusManager.getInstance().registerTaskStatusListener(this);
// 只有下载模块需要这坨东西,因此移动到这里初始化
@ -153,6 +152,7 @@ public class DownloadManager implements DownloadStatusListener {
statusMap = new ArrayMap<>();
downloadingMap = new ArrayMap<>();
// TODO 这里的 handler 类的 case 可能会被多次调用,原因未知
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
@ -271,7 +271,7 @@ public class DownloadManager implements DownloadStatusListener {
downloadEntity.setPlugin(!TextUtils.isEmpty(apkEntity.getGhVersion()));
ExposureUtils.DownloadType downloadType = ExposureUtils.getDownloadType(apkEntity, gameEntity.getId());
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, apkEntity.getPlatform(), traceEvent, downloadType);
ExposureEvent downloadExposureEvent = ExposureUtils.logADownloadExposureEvent(gameEntity, gameEntity.getPlatform(), traceEvent, downloadType);
// 将下载事件放入 downloadEntity 中供下载完成时取出使用
downloadEntity.setExposureTrace(gson.toJson(downloadExposureEvent));
@ -432,7 +432,6 @@ public class DownloadManager implements DownloadStatusListener {
* @param url 下载链接
* @return null表示下载列表中不存在该任务否则返回下载任务
*/
@Nullable
public DownloadEntity getDownloadEntityByUrl(String url) {
if (TextUtils.isEmpty(url)) return null;
return mDownloadDao.get(url);
@ -495,13 +494,11 @@ public class DownloadManager implements DownloadStatusListener {
*
* @return null表示没有下载任务
*/
@NonNull
public List<DownloadEntity> getAll() {
if (CommonDebug.IS_DEBUG) {
CommonDebug.logMethodName(this);
}
List<DownloadEntity> all = mDownloadDao.getAll();
return all != null ? all : new ArrayList<>();
return mDownloadDao.getAll();
}
public ArrayMap<String, DownloadEntity> getEntryMap(String name) {
@ -652,7 +649,6 @@ public class DownloadManager implements DownloadStatusListener {
// 所以还是老老实实地以 startService 为主吧
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
&& ProcessLifecycleOwner.get().getLifecycle().getCurrentState() == Lifecycle.State.CREATED) {
serviceIntent.putExtra(DownloadService.KEY_SERVICE_ACTION, DownloadService.START_FOREGROUND);
mContext.startForegroundService(serviceIntent);
} else {
mContext.startService(serviceIntent);
@ -675,13 +671,20 @@ public class DownloadManager implements DownloadStatusListener {
// 当满足系统版本大于 8.0 、应用在后台运行时以前台服务开启
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
&& ProcessLifecycleOwner.get().getLifecycle().getCurrentState() == Lifecycle.State.CREATED) {
serviceIntent.putExtra(DownloadService.KEY_SERVICE_ACTION, DownloadService.START_FOREGROUND);
mContext.startForegroundService(serviceIntent);
} else {
mContext.startService(serviceIntent);
}
}
public void disableDownloadSpeedLimit() {
// DownloadSpeedController.disableSpeedLimit();
}
public void updateSpeedLimitationReleaseDelay(int delay) {
// DownloadSpeedController.updateLimitationReleaseDelay(delay);
}
public void checkRetryDownload() {
if (!NetworkUtils.isWifiConnected(mContext)) return;
@ -729,24 +732,10 @@ public class DownloadManager implements DownloadStatusListener {
if (showRedPoint) return "";
if (updateList != null) {
// 首页永久忽略的插件化列表
List<HomePluggableFilterEntity> permanentInactiveUpdateList = HomePluggableHelper.getPermanentInactivePluggablePackage();
for (GameUpdateEntity updateEntity : updateList) {
if (updateEntity.isShowPlugin(PluginLocation.only_index) && !mUpdateMarks.contains(updateEntity.getId() + updateEntity.getPackageName())) {
// 判断该更新的的包名是否被永久忽略
if (permanentInactiveUpdateList != null) {
boolean isPluggablePermanentInactive = false;
for (HomePluggableFilterEntity filterEntity : permanentInactiveUpdateList) {
if (filterEntity.getPkgName().equals(updateEntity.getPackageName())) {
isPluggablePermanentInactive = true;
}
}
if (!isPluggablePermanentInactive) {
return "";
}
} else {
return "";
}
if (updateEntity.isShowPlugin(PluginLocation.only_index)
&& !mUpdateMarks.contains(updateEntity.getId() + updateEntity.getPackageName())) {
return "";
}
}
}

View File

@ -164,7 +164,7 @@ class DownloadDialog : BaseDialogFragment(), View.OnTouchListener {
downloadNotice,
mEntrance, "下载多平台弹窗")
}
// MtaHelper.onEvent(MTA_KEY, "点击", mViewModel.gameEntity.name + "_" + downloadNotice.title)
MtaHelper.onEvent(MTA_KEY, "点击", mViewModel.gameEntity.name + "_" + downloadNotice.title)
}
}
@ -280,13 +280,13 @@ class DownloadDialog : BaseDialogFragment(), View.OnTouchListener {
}
private fun postBrowseMta() {
// if (mCollectionAdapter == null) {
// MtaHelper.onEventWithTime(MTA_KEY, mElapsedHelper.elapsedTime, "浏览", mGameEntity?.name)
// } else {
// val collectionData = mViewModel.collectionLiveData.value
// MtaHelper.onEventWithTime(MTA_KEY, mElapsedHelper.elapsedTime, "浏览", mGameEntity?.name + "_" + collectionData?.name)
// throwExceptionInDebug("collectionData must be not null", collectionData == null)
// }
if (mCollectionAdapter == null) {
MtaHelper.onEventWithTime(MTA_KEY, mElapsedHelper.elapsedTime, "浏览", mGameEntity?.name)
} else {
val collectionData = mViewModel.collectionLiveData.value
MtaHelper.onEventWithTime(MTA_KEY, mElapsedHelper.elapsedTime, "浏览", mGameEntity?.name + "_" + collectionData?.name)
throwExceptionInDebug("collectionData must be not null", collectionData == null)
}
}
override fun onStart() {

View File

@ -6,7 +6,6 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.gh.base.OnViewClickListener
import com.gh.common.exposure.ExposureEvent
import com.gh.common.util.DirectUtils
import com.gh.common.util.MtaHelper
import com.gh.common.util.throwExceptionInDebug
import com.gh.gamecenter.NewsDetailActivity
@ -93,12 +92,11 @@ class DownloadDialogAdapter(context: Context,
mContext.startActivity(QaActivity.getIntent(mContext, data.linkText, qaCollectionId = data.linkId))
}
else -> {
//Utils.toast(mContext, "暂不支持类型:" + data.linkType)
DirectUtils.directToLinkPage(mContext, data.getLinkEntity(), mEntrance, mPath)
Utils.toast(mContext, "暂不支持类型:" + data.linkType)
}
}
// MtaHelper.onEvent(DownloadDialog.MTA_KEY, "点击", viewModel.gameEntity.name + "_" + data.title)
MtaHelper.onEvent(DownloadDialog.MTA_KEY, "点击", viewModel.gameEntity.name + "_" + data.title)
}
}
is DownloadDialogInstructionItemViewHolder -> {

View File

@ -7,7 +7,6 @@ import com.gh.common.exposure.ExposureEvent
import com.gh.common.util.PackageUtils
import com.gh.common.util.goneIf
import com.gh.common.util.throwExceptionInDebug
import com.gh.common.util.toColor
import com.gh.download.DownloadManager
import com.gh.gamecenter.R
import com.gh.gamecenter.databinding.DownloadDialogInstalledItemBinding
@ -31,7 +30,6 @@ class DownloadDialogInstalledItemViewHolder(val binding: DownloadDialogInstalled
throwExceptionInDebug("apkLink 不应该出现在这里")
} else if (apkCollection != null || apkEntity.downloadInstruction.isNotEmpty()) {
binding.collection.visibility = View.VISIBLE
binding.collectionPluggableHint.visibility = View.GONE
binding.downloadStatusIcon.visibility = View.GONE
binding.progressbar.visibility = View.GONE
binding.pluggable.visibility = View.GONE
@ -47,14 +45,7 @@ class DownloadDialogInstalledItemViewHolder(val binding: DownloadDialogInstalled
}
binding.collection.text = if (apkCollection != null) {
if (apkCollection.showPluggableHint) {
binding.collectionPluggableHint.visibility = View.VISIBLE
binding.collection.setTextColor(R.color.text_05CBA3.toColor())
gameEntity.pluginDesc + "此版本"
} else {
binding.collection.setTextColor(R.color.text_cccccc.toColor())
"查看合集"
}
"查看合集"
} else "查看详情"
itemView.setTag(DownloadDialogAdapter.ITEM_TAG_KEY, DownloadDialogItemStatus.COLLECTION)
} else {

View File

@ -190,11 +190,11 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
}
val downloadEntity = DownloadManager.getInstance(it.context).getDownloadEntityByUrl(apkEntity.url)
if (downloadEntity?.status == DownloadStatus.pause) {
if (downloadEntity.status == DownloadStatus.pause) {
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_暂停中"
} else if (downloadEntity?.status == DownloadStatus.waiting) {
} else if (downloadEntity.status == DownloadStatus.waiting) {
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_等待中"
} else if (downloadEntity?.status == DownloadStatus.subscribe) {
} else if (downloadEntity.status == DownloadStatus.subscribe) {
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_排队中"
} else {
mtaValue = gameEntity.name + "_" + apkEntity.getPlatformName() + "_下载中"
@ -203,8 +203,6 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
}
DownloadDialogItemStatus.INSTALL -> {
val downloadEntity = DownloadManager.getInstance(it.context).getDownloadEntityByUrl(apkEntity.url)
?: return@setOnClickListener
if (FileUtils.isEmptyFile(downloadEntity.path)) {
Utils.toast(it.context, R.string.install_failure_hint)
DownloadManager.getInstance(it.context).cancel(apkEntity.url)
@ -262,7 +260,7 @@ class DownloadDialogItemViewHolder(val binding: DownloadDialogItemBinding) : Bas
}
}
throwExceptionInDebug("无法识别当前状态", mtaValue == "未知")
// MtaHelper.onEvent(DownloadDialog.MTA_KEY, "点击", mtaValue)
MtaHelper.onEvent(DownloadDialog.MTA_KEY, "点击", mtaValue)
}
}

View File

@ -13,7 +13,7 @@ class DownloadDialogPlatformRequestItemViewHolder(val binding: DownloadDialogPla
binding.content.setOnClickListener {
val intent = VoteActivity.getIntent(it.context, gameEntity.name, gameEntity.id)
it.context.startActivity(intent)
// MtaHelper.onEvent(DownloadDialog.MTA_KEY, "点击", gameEntity.name + "_求版本")
MtaHelper.onEvent(DownloadDialog.MTA_KEY, "点击", gameEntity.name + "_求版本")
}
}
}

View File

@ -61,13 +61,15 @@ class DownloadViewModel(application: Application, val gameEntity: GameEntity) :
var isInstalled = false
apk.apkCollection?.saveApkEntity?.let {
for (entity in it) {
isInstalled = isInstalled(entity.packageName)
isInstalled = PackagesManager.isInstalled(entity.packageName)
&& Config.getSettings()?.gameDownloadBlackList?.contains(entity.packageName) != true
if (isInstalled) break
}
}
isInstalled
} else {
isInstalled(apk.packageName)
PackagesManager.isInstalled(apk.packageName)
&& Config.getSettings()?.gameDownloadBlackList?.contains(apk.packageName) != true
}
if (installed) {
mInstalledApkList.add(apk)
@ -76,24 +78,6 @@ class DownloadViewModel(application: Application, val gameEntity: GameEntity) :
}
}
// 判断是否显示合集插件化提示
mInstalledApkList.forEach { apk ->
if (apk.apkCollection != null) {
var hasPluggable = false
var installedPlugin = false
apk.apkCollection?.saveApkEntity?.forEach { collectionApk ->
if (PackageUtils.isCanPluggable(collectionApk)) {
hasPluggable = true
} else if (PackageUtils.getGhId(collectionApk.packageName) == gameEntity.id) {
installedPlugin = true
}
if (apk.apkCollection?.saveApkEntity?.last() == collectionApk) {
apk.apkCollection?.showPluggableHint = hasPluggable && !installedPlugin
}
}
}
}
mInstalledApkList.sortWith(Comparator { o1, o2 -> o2.order - o1.order })
mOtherApkList.sortWith(Comparator { o1, o2 -> o2.order - o1.order })
@ -148,7 +132,7 @@ class DownloadViewModel(application: Application, val gameEntity: GameEntity) :
return SORT_PLUGGABLE
} else if (PackageUtils.isCanUpdate(apkEntity, gameEntity.id)) {
return SORT_UPDATE
} else if (PackageUtils.getGhId(packageName) == gameEntity.id) {
} else if (PackageUtils.getMetaData(getApplication(), packageName, "gh_id") == gameEntity.id) {
return SORT_NORMAL_LAUNCH
}
}
@ -240,14 +224,6 @@ class DownloadViewModel(application: Application, val gameEntity: GameEntity) :
}
}
// 仅用于多平台面板的已安装判断
private fun isInstalled(packageName: String): Boolean {
val ghId = PackageUtils.getGhId(packageName)
return PackagesManager.isInstalled(packageName)
&& (ghId == null || ghId == gameEntity.id)
&& Config.getSettings()?.gameDownloadBlackList?.contains(packageName) != true
}
class Factory(val mApplication: Application, val gameEntity: GameEntity) : ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return DownloadViewModel(mApplication, gameEntity) as T

View File

@ -21,10 +21,8 @@ class BlockActivity : NormalActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setToolbarMenu(R.menu.menu_download)
}
override fun provideNormalIntent(): Intent {
return getTargetIntent(this, BlockActivity::class.java, GameFragment::class.java)
DownloadManager.getInstance(this).updateSpeedLimitationReleaseDelay(10)
}
override fun showDownloadMenu(): Boolean {

View File

@ -6,6 +6,7 @@ import android.os.Bundle;
import com.gh.base.fragment.BaseFragment_TabLayout;
import com.gh.common.util.EntranceUtils;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.download.DownloadFragment;
/**
@ -48,4 +49,11 @@ public class DownloadManagerActivity extends NormalActivity {
bundle.putString(EntranceUtils.KEY_PACKAGENAME, packageName);
return getTargetIntent(context, DownloadManagerActivity.class, DownloadFragment.class, bundle);
}
@Override
protected void onResume() {
super.onResume();
DownloadManager.getInstance(this).disableDownloadSpeedLimit();
}
}

View File

@ -12,6 +12,7 @@ import com.gh.common.exposure.ExposureType;
import com.gh.common.util.DataUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.EntranceUtils;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.entity.GameEntity;
import com.gh.gamecenter.gamedetail.GameDetailFragment;
import com.halo.assistant.HaloApp;
@ -29,6 +30,7 @@ public class GameDetailActivity extends NormalActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DownloadManager.getInstance(this).updateSpeedLimitationReleaseDelay(10);
DisplayUtils.transparentStatusBar(this);
}

View File

@ -8,7 +8,6 @@ import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
@ -19,7 +18,6 @@ import com.ethanhua.skeleton.Skeleton;
import com.ethanhua.skeleton.ViewSkeletonScreen;
import com.gh.base.OnRequestCallBackListener;
import com.gh.base.ToolBarActivity;
import com.gh.common.filter.RegionSettingHelper;
import com.gh.common.util.ApkActiveUtils;
import com.gh.common.util.DetailDownloadUtils;
import com.gh.common.util.DeviceTokenUtils;
@ -84,8 +82,6 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
DownloadProgressBar mDownloadPb;
@BindView(R.id.list_skeleton)
View mListSkeleton;
@BindView(R.id.detail_ll_bottom)
View mDetailBottom;
private ViewSkeletonScreen mSkeleton;
@ -214,11 +210,6 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
checkLibaoStatus();
}
}
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mDetailBottom.getLayoutParams();
params.topMargin = 0;
mDetailBottom.setLayoutParams(params);
}
@Override
@ -357,14 +348,8 @@ public class LibaoDetailActivity extends ToolBarActivity implements LibaoDetailA
// 获取游戏摘要
private void getGameDigest() {
if (mLibaoEntity.getGame() == null) return;
String gameId = mLibaoEntity.getGame().getId();
if (RegionSettingHelper.shouldThisGameBeFiltered(gameId)) {
return;
}
RetrofitManager.getInstance(this).getSensitiveApi().getGameNewsDigest(gameId)
RetrofitManager.getInstance(this).getApi().getGameNewsDigest(gameId)
.map(ApkActiveUtils.filterMapper)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())

View File

@ -23,9 +23,6 @@ import android.view.View;
import android.view.Window;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.lifecycle.ViewModelProviders;
import com.gh.base.AppUncaughtHandler;
import com.gh.base.BaseActivity;
import com.gh.base.fragment.BaseFragment_ViewPager;
@ -48,7 +45,6 @@ import com.gh.common.util.DialogUtils;
import com.gh.common.util.DirectUtils;
import com.gh.common.util.DisplayUtils;
import com.gh.common.util.EntranceUtils;
import com.gh.common.util.HomePluggableHelper;
import com.gh.common.util.LogUtils;
import com.gh.common.util.LunchType;
import com.gh.common.util.MtaHelper;
@ -120,6 +116,8 @@ import java.util.TimerTask;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import androidx.annotation.NonNull;
import androidx.lifecycle.ViewModelProviders;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
@ -216,9 +214,8 @@ public class MainActivity extends BaseActivity {
// checkTinkerPath(); // 看情况是否需要显示补丁弹窗
// 必须放在这里,否会导致获取 baseActivity 不是本应用包名
// postDelayed 是为了让 ProcessLifecycleOwner 知道准确状态,避免调用 startForegroundService
handler.postDelayed(() -> DownloadManager.getInstance(this).initDownloadService(), 0);
// 必须放在这里,否会导致获取baseActivity不是本应用包名
DownloadManager.getInstance(this).initDownloadService();
checkNotificationPermission();
@ -261,8 +258,6 @@ public class MainActivity extends BaseActivity {
PlatformUtils.getInstance(getApplicationContext());
// 友盟记录启动
PushAgent.getInstance(this).onAppStart();
HomePluggableHelper.activationFilterData();
});
@ -717,12 +712,12 @@ public class MainActivity extends BaseActivity {
kv6.put("安装或卸载", "安装完成");
DataUtils.onEvent(this, "插件化", mDownloadEntity.getName(), kv6);
// DataUtils.onMtaEvent(this,
// "插件化_新",
// "位置", mDownloadEntity.getEntrance(),
// "游戏", mDownloadEntity.getName() + "-" + mDownloadEntity.getPlatform(),
// "操作", "安装完成",
// "网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
DataUtils.onMtaEvent(this,
"插件化_新",
"位置", mDownloadEntity.getEntrance(),
"游戏", mDownloadEntity.getName() + "-" + mDownloadEntity.getPlatform(),
"操作", "安装完成",
"网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
}
// 没有光环 ID 的都记录一下游戏 ID供'我的游戏'区分同包名不同插件用
@ -738,7 +733,7 @@ public class MainActivity extends BaseActivity {
if (mSp.getBoolean(SettingsFragment.CONCERN_GAME_SP_KEY, true)) { //设置页面控制是否安装后自动关注
// 安装后关注游戏
DownloadEntity finalDownloadEntity = mDownloadEntity;
RetrofitManager.getInstance(this).getSensitiveApi().getGameDigestByPackageName(UrlFilterUtils.getFilterQuery("package", packageName))
RetrofitManager.getInstance(this).getApi().getGameDigestByPackageName(UrlFilterUtils.getFilterQuery("package", packageName))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<List<GameDigestEntity>>() {
@ -765,12 +760,12 @@ public class MainActivity extends BaseActivity {
kv6.put("安装或卸载", "卸载完成");
DataUtils.onEvent(this, "插件化", mDownloadEntity.getName(), kv6);
// DataUtils.onMtaEvent(this,
// "插件化_新",
// "位置", mDownloadEntity.getEntrance(),
// "游戏", mDownloadEntity.getName() + "-" + mDownloadEntity.getPlatform(),
// "操作", "卸载完成",
// "网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
DataUtils.onMtaEvent(this,
"插件化_新",
"位置", mDownloadEntity.getEntrance(),
"游戏", mDownloadEntity.getName() + "-" + mDownloadEntity.getPlatform(),
"操作", "卸载完成",
"网络状态", DeviceUtils.getNetwork(HaloApp.getInstance().getApplication()));
startActivity(PackageUtils.getInstallIntent(this, mDownloadEntity.getPath()));
}

View File

@ -18,11 +18,15 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.view.MotionEventCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.ethanhua.skeleton.Skeleton;
import com.ethanhua.skeleton.ViewSkeletonScreen;
import com.gh.base.OnRequestCallBackListener;
import com.gh.base.ToolBarActivity;
import com.gh.common.filter.RegionSettingHelper;
import com.gh.common.history.HistoryHelper;
import com.gh.common.util.ApkActiveUtils;
import com.gh.common.util.CheckLoginUtils;
@ -36,7 +40,6 @@ import com.gh.common.util.EntranceUtils;
import com.gh.common.util.GdtHelper;
import com.gh.common.util.MtaHelper;
import com.gh.common.util.ShareUtils;
import com.gh.common.view.FixLinearLayoutManager;
import com.gh.common.view.VerticalItemDecoration;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.adapter.viewholder.DetailViewHolder;
@ -65,9 +68,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import androidx.annotation.NonNull;
import androidx.core.view.MotionEventCompat;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
@ -257,7 +257,7 @@ public class NewsDetailActivity extends ToolBarActivity implements OnClickListen
// init RecyclerView
mDetailRv.setHasFixedSize(true);
mDetailRv.setLayoutManager(new FixLinearLayoutManager(this));
mDetailRv.setLayoutManager(new LinearLayoutManager(this));
mDetailRv.addItemDecoration(new VerticalItemDecoration(this, 8, false));
adapter = new NewsDetailAdapter(this, this, mEntrance);
mDetailRv.setAdapter(adapter);
@ -323,7 +323,7 @@ public class NewsDetailActivity extends ToolBarActivity implements OnClickListen
shareIcon = gameEntity.getIcon();
}
showShare(url, shareIcon, adapter.getNewsDetailEntity().getTitle(),
"来自光环助手(最强卡牌神器)", ShareUtils.ShareEntrance.news, adapter.getNewsDetailEntity().getId());
"来自光环助手(最强卡牌神器)", ShareUtils.ShareType.news);
}
break;
case R.id.menu_collect:
@ -613,15 +613,11 @@ public class NewsDetailActivity extends ToolBarActivity implements OnClickListen
}
private void getGameDetail(String gameId) {
if (RegionSettingHelper.shouldThisGameBeFiltered(gameId)) {
return;
}
if (TextUtils.isEmpty(gameId)) {
mDetailBottomLl.setVisibility(View.GONE);
return;
}
RetrofitManager.getInstance(this).getSensitiveApi().getGameNewsDigest(gameId)
RetrofitManager.getInstance(this).getApi().getGameNewsDigest(gameId)
.map(ApkActiveUtils.filterMapper)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())

View File

@ -7,11 +7,11 @@ import android.text.TextUtils;
import android.view.MenuItem;
import android.view.MotionEvent;
import androidx.fragment.app.Fragment;
import com.gh.base.ToolBarActivity;
import com.gh.gamecenter.normal.NormalFragment;
import androidx.fragment.app.Fragment;
/**
* Created by khy on 17/10/17.
*/
@ -108,9 +108,7 @@ public abstract class NormalActivity extends ToolBarActivity {
@Override
public void onBackPressed() {
if (mTargetFragment.isAdded()
&& mTargetFragment instanceof NormalFragment
&& !((NormalFragment) mTargetFragment).onBackPressed()) {
if (mTargetFragment instanceof NormalFragment && !((NormalFragment) mTargetFragment).onBackPressed()) {
super.onBackPressed();
}
}

View File

@ -22,8 +22,4 @@ class QaActivity : NormalActivity() {
return getTargetIntent(context, QaActivity::class.java, HelpContainerFragment::class.java, args)
}
}
override fun provideNormalIntent(): Intent {
return getTargetIntent(this, QaActivity::class.java, HelpContainerFragment::class.java)
}
}

View File

@ -141,7 +141,7 @@ open class SearchActivity : BaseActivity() {
searchEt.setText(key)
searchEt.setSelection(searchEt.text.length)
updateDisplayType(DisplayType.GAME_DETAIL)
// MtaHelper.onEvent("游戏搜索", "默认搜索", key)
MtaHelper.onEvent("游戏搜索", "默认搜索", key)
}
SearchType.HOT -> {
mSearchKey = key
@ -154,7 +154,7 @@ open class SearchActivity : BaseActivity() {
searchEt.setText(key)
searchEt.setSelection(searchEt.text.length)
updateDisplayType(DisplayType.GAME_DETAIL)
// MtaHelper.onEvent("游戏搜索", "历史搜索", key)
MtaHelper.onEvent("游戏搜索", "历史搜索", key)
}
SearchType.MANUAL -> {
val newSearchKey = searchEt.text.toString().trim { it <= ' ' }
@ -173,7 +173,7 @@ open class SearchActivity : BaseActivity() {
toast("请输入搜索内容")
}
}
// MtaHelper.onEvent("游戏搜索", "主动搜索", newSearchKey)
MtaHelper.onEvent("游戏搜索", "主动搜索", newSearchKey)
}
}
mIsAutoSearchDisabled = false

View File

@ -67,7 +67,7 @@ public class ShareGhActivity extends ToolBarActivity {
QRCodeUtils.setQRCode(this, getString(R.string.gh_website_url_100), mGhQrcode);
ShareUtils.getInstance(this).showShareWindows(this, mShareRl, getString(R.string.gh_website_url_300)
, getString(R.string.gh_icon_url), "玩手游不用肝的感觉真好"
, "绿色安全的手游加速助手", ShareUtils.ShareEntrance.shareGh, "");
, "绿色安全的手游加速助手", ShareUtils.ShareType.shareGh);
}
@OnClick(R.id.gh_address_tv)

View File

@ -12,7 +12,6 @@ import com.gh.common.util.EntranceUtils;
import com.gh.common.util.PlatformUtils;
import com.gh.common.util.RunningUtils;
import com.gh.gamecenter.entity.CommunityEntity;
import com.gh.gamecenter.entity.SubjectRecommendEntity;
import com.gh.gamecenter.entity.VideoLinkEntity;
import com.gh.gamecenter.manager.UserManager;
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel;
@ -97,7 +96,7 @@ public class SkipActivity extends BaseActivity {
DirectUtils.directToArticle(this, path, ENTRANCE_BROWSER);
break;
case HOST_GAME:
DirectUtils.directToGameDetail(this, path, ENTRANCE_BROWSER, false, "libao".equals(to),null);
DirectUtils.directToGameDetail(this, path, ENTRANCE_BROWSER, false, "libao".equals(to));
break;
case HOST_COLUMN:
DirectUtils.directToSubject(this, path, uri.getQueryParameter(KEY_NAME), ENTRANCE_BROWSER);
@ -105,17 +104,10 @@ public class SkipActivity extends BaseActivity {
case HOST_SUGGESTION:
String platform = uri.getQueryParameter(KEY_PLATFORM);
String platformName = PlatformUtils.getInstance(this).getPlatformName(platform);
String gameId = uri.getQueryParameter(EntranceUtils.KEY_GAMEID);
String packageMd5 = uri.getQueryParameter(EntranceUtils.KEY_PACKAGE_MD5);
String content = (TextUtils.isEmpty(gameId) || TextUtils.isEmpty(packageMd5)) ?
String.format("%s-%s-V%s",
uri.getQueryParameter(KEY_GAME_NAME),
TextUtils.isEmpty(platformName) ? platform : platformName,
uri.getQueryParameter(KEY_VERSION)) :
String.format("%s-%s-V%s\n游戏ID%s\n游戏包MD5%s\n",
uri.getQueryParameter(KEY_GAME_NAME),
TextUtils.isEmpty(platformName) ? platform : platformName,
uri.getQueryParameter(KEY_VERSION), gameId, packageMd5);
String content = String.format("%s-%s-V%s",
uri.getQueryParameter(KEY_GAME_NAME),
TextUtils.isEmpty(platformName) ? platform : platformName,
uri.getQueryParameter(KEY_VERSION));
DirectUtils.directToFeedback(this, content, ENTRANCE_BROWSER);
break;
case HOST_DOWNLOAD:
@ -273,36 +265,6 @@ public class SkipActivity extends BaseActivity {
columnId = uri.getQueryParameter("column_id");
DirectUtils.directAskColumnDetail(this, columnId, community, ENTRANCE_BROWSER, "浏览器");
break;
case EntranceUtils.HOST_BLOCK:
name = uri.getQueryParameter("name");
SubjectRecommendEntity entity = new SubjectRecommendEntity();
entity.setLink(path);
entity.setName(name);
entity.setText(name);
DirectUtils.directToBlock(this, entity);
break;
case EntranceUtils.HOST_SERVER_BLOCK:
DirectUtils.directToGameServers(this,ENTRANCE_BROWSER, "浏览器");
break;
case EntranceUtils.HOST_AMWAY_BLOCK:
DirectUtils.directToAmway(this, null, ENTRANCE_BROWSER, "浏览器");
break;
case EntranceUtils.HOST_HELP:
name = uri.getQueryParameter("name");
DirectUtils.directToQa(this, name, path);
break;
case EntranceUtils.HOST_HELP_COLLECTION:
name = uri.getQueryParameter("name");
DirectUtils.directToQaCollection(this, name, path);
break;
case EntranceUtils.HOST_GAME_UPLOAD:
DirectUtils.directGameUpload(this, ENTRANCE_BROWSER, "浏览器");
break;
default:
EntranceUtils.jumpActivity(this, new Bundle()); // 跳转至首页
return;

Some files were not shown because too many files have changed in this diff Show More