diff --git a/app/build.gradle b/app/build.gradle index e803e8fdd2..85de769541 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -341,6 +341,7 @@ dependencies { implementation "org.nanohttpd:nanohttpd:${nanohttpd}" implementation "com.aliyun.openservices:aliyun-log-android-sdk:${aliyunLog}" + implementation "com.github.princekin-f:EasyFloat:${easyFloat}" implementation project(':libraries:LGLibrary') // implementation project(':libraries:MTA') diff --git a/app/proguard-rules.txt b/app/proguard-rules.txt index 3c422b921c..fe1051d63f 100644 --- a/app/proguard-rules.txt +++ b/app/proguard-rules.txt @@ -131,4 +131,7 @@ ### 中国移动一键登录 -dontwarn com.cmic.sso.sdk.** --keep class com.cmic.sso.sdk.* { *; } \ No newline at end of file +-keep class com.cmic.sso.sdk.* { *; } + +### EasyFloat +-keep class com.lzf.easyfloat.* {*;} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c46883ae4e..3433f54029 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -26,22 +26,12 @@ - - - - - - - - - - @@ -53,7 +43,8 @@ com.shuyu.gsy.base, com.google.android.exoplayer2, tv.danmaku.ijk.media.exo2, - pl.droidsonroids.gif" /> + pl.droidsonroids.gif, + com.lzf.easyfloat"/> - - @@ -174,6 +163,11 @@ android:name="com.gh.gamecenter.WebActivity" android:screenOrientation="portrait" /> + + @@ -671,7 +665,7 @@ + android:theme="@style/AppFullScreenTheme" /> { - // 如果当前是在键盘输入时,点击"返回任务"要先收起键盘 - Util_System_Keyboard.hideSoftKeyboard(this); - startActivity(EnergyCenterActivity.Companion.getIntent(this)); - SPUtils.setBoolean(Constants.SP_SHOW_TASK_FLOAT, false); - mWM.removeView(mTaskBackView); - mHasAddTaskFloat = false; - }); - setFloatTouchListener(); - mWM.addView(mTaskBackView, mWmParams); - } - - private void setFloatTouchListener() { - int screenHeight = getResources().getDisplayMetrics().heightPixels; - - mTaskBackView.setOnTouchListener(new View.OnTouchListener() { - - private int intervalY; - private int startY; - - @Override - public boolean onTouch(View v, MotionEvent event) { - final int y = (int) event.getRawY(); - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - intervalY = y; - startY = y; - break; - - case MotionEvent.ACTION_MOVE: - mWmParams.y -= (y - intervalY); - if (mWmParams.y < 0) { - mWmParams.y = 0; - } - - if (mWmParams.y > screenHeight) { - mWmParams.y = screenHeight; - } - - if (mWM != null && mTaskBackView != null && mHasAddTaskFloat) { - mWM.updateViewLayout(mTaskBackView, mWmParams); - } - - intervalY = y; - return true; - - case MotionEvent.ACTION_UP: - // 滑动距离少于10视为点击,返回false,否则视为拖动,返回true - if (Math.abs(y - startY) <= 10) { - return false; - } else { - // 记录位置 - SPUtils.setInt(Constants.SP_TASK_FLOAT_LAST_Y, mWmParams.y); - return true; - } - } - return false; - } - }); - } - - /** * 此回调可用于确认当前 activity 已经执行了 finish() 方法并处于 isFinishing 状态 */ diff --git a/app/src/main/java/com/gh/base/GHActivityLifecycleCallbacksImpl.java b/app/src/main/java/com/gh/base/GHActivityLifecycleCallbacksImpl.java deleted file mode 100644 index 39d908f3ce..0000000000 --- a/app/src/main/java/com/gh/base/GHActivityLifecycleCallbacksImpl.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.gh.base; - -import android.app.Activity; -import android.app.Application.ActivityLifecycleCallbacks; -import android.os.Bundle; - -import com.gh.common.notifier.Notifier; -import com.gh.common.util.DataUtils; -import com.gh.download.DownloadManager; -import com.gh.gamecenter.SplashScreenActivity; -import com.halo.assistant.HaloApp; -import com.lightgame.utils.AppManager; - -/** - * 1、写点针对生命周期的统计代码 - * 2、写点通用的逻辑 - * 3、接口解耦 - * - * @author CsHeng - * @Date 09/05/2017 - * @Time 6:22 PM - */ -public class GHActivityLifecycleCallbacksImpl implements ActivityLifecycleCallbacks { - - @Override - public void onActivityCreated(Activity activity, Bundle savedInstanceState) { - - AppManager.getInstance().addActivity(activity); - } - - @Override - public void onActivityStarted(Activity activity) { - - } - - @Override - public void onActivityResumed(Activity activity) { - CurrentActivityHolder.getActivitySet().add(activity); - - if (HaloApp.isUserAcceptPrivacyPolicy(activity)) { - DataUtils.onResume(activity); - //FIXME 这里应该只是部分Activity需要 - try { - // 初始化gameMap - if (!(activity instanceof SplashScreenActivity)) { - DownloadManager.getInstance(activity).initGameMap(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - @Override - public void onActivityPaused(Activity activity) { - CurrentActivityHolder.getActivitySet().remove(activity); - - if (HaloApp.isUserAcceptPrivacyPolicy(activity)) { - DataUtils.onPause(activity); - } - } - - @Override - public void onActivityStopped(Activity activity) { - Notifier.hide(); - } - - @Override - public void onActivitySaveInstanceState(Activity activity, Bundle outState) { - - } - - @Override - public void onActivityDestroyed(Activity activity) { - if (activity.isFinishing()) { - AppManager.getInstance().finishActivity(activity); - } - } - -} diff --git a/app/src/main/java/com/gh/base/GlobalActivityLifecycleObserver.kt b/app/src/main/java/com/gh/base/GlobalActivityLifecycleObserver.kt new file mode 100644 index 0000000000..3d6a89c8e8 --- /dev/null +++ b/app/src/main/java/com/gh/base/GlobalActivityLifecycleObserver.kt @@ -0,0 +1,82 @@ +package com.gh.base + +import android.app.Activity +import android.app.Application +import android.os.Bundle +import com.gh.common.notifier.Notifier +import com.gh.common.util.DataUtils +import com.gh.common.util.FloatingBackViewManager +import com.gh.download.DownloadManager +import com.gh.gamecenter.SingleTaskWebActivity +import com.gh.gamecenter.SplashScreenActivity +import com.gh.gamecenter.energy.EnergyCenterActivity +import com.halo.assistant.HaloApp +import com.lightgame.utils.AppManager + +class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks { + + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { + AppManager.getInstance().addActivity(activity) + } + + override fun onActivityStarted(activity: Activity) { + + } + + override fun onActivityResumed(activity: Activity) { + CurrentActivityHolder.activitySet.add(activity) + + // 判断是否需要显示或隐藏返回小浮窗 + if (FloatingBackViewManager.getType().isNotEmpty()) { + if (activity is EnergyCenterActivity + && FloatingBackViewManager.getType() == FloatingBackViewManager.TYPE_TASK) { + FloatingBackViewManager.disableBackView() + } else if (activity is SingleTaskWebActivity + && FloatingBackViewManager.getType() == FloatingBackViewManager.TYPE_ACTIVITY + // TODO 再加上一个内容匹配? + ) { + FloatingBackViewManager.disableBackView() + } else { + FloatingBackViewManager.showBackView(activity) + } + } + + if (HaloApp.isUserAcceptPrivacyPolicy(activity)) { + DataUtils.onResume(activity) + // FIXME 这里应该只是部分Activity需要 + try { + // 初始化gameMap + if (activity !is SplashScreenActivity) { + DownloadManager.getInstance(activity).initGameMap() + } + } catch (e: Exception) { + e.printStackTrace() + } + } + } + + override fun onActivityPaused(activity: Activity) { + CurrentActivityHolder.activitySet.remove(activity) + FloatingBackViewManager.hideBackView(activity) + + if (HaloApp.isUserAcceptPrivacyPolicy(activity)) { + DataUtils.onPause(activity) + } + } + + override fun onActivityStopped(activity: Activity) { + Notifier.hide() + } + + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { + + } + + override fun onActivityDestroyed(activity: Activity) { + if (activity.isFinishing) { + AppManager.getInstance().finishActivity(activity) + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/common/constant/Constants.java b/app/src/main/java/com/gh/common/constant/Constants.java index addc69b0a1..c55be5db09 100644 --- a/app/src/main/java/com/gh/common/constant/Constants.java +++ b/app/src/main/java/com/gh/common/constant/Constants.java @@ -186,11 +186,6 @@ public class Constants { // 头像挂件ID public static final String SP_CHOOSE_AVATAR_ID = "choose_avatar_id"; - // 是否显示返回任务悬浮图标 - public static final String SP_SHOW_TASK_FLOAT = "show_task_float"; - // 悬浮图标Y值 - public static final String SP_TASK_FLOAT_LAST_Y = "task_float_last_y"; - // 是否第一次进入新分类2.0 public static final String SP_FIRST_ENTER_CATEGORY_V2 = "first_enter_category_v2"; diff --git a/app/src/main/java/com/gh/common/tracker/ActivityLifecycleWatcher.kt b/app/src/main/java/com/gh/common/tracker/ActivityLifecycleWatcher.kt index 2fbab7fba4..300e2230fd 100644 --- a/app/src/main/java/com/gh/common/tracker/ActivityLifecycleWatcher.kt +++ b/app/src/main/java/com/gh/common/tracker/ActivityLifecycleWatcher.kt @@ -4,7 +4,7 @@ import android.app.Activity import android.app.Application import android.os.Bundle -// TODO SplashActivity 没有回调 onStart 和 onStop +// FYI 快速启动并且不设置 contentView 马上结束的 SplashActivity 没有 onStart 和 onStop 回调 class ActivityLifecycleWatcher(private val mTrack: ITrack) : Application.ActivityLifecycleCallbacks { override fun onActivityStarted(activity: Activity) { diff --git a/app/src/main/java/com/gh/common/tracker/AppLifecycleWatcher.kt b/app/src/main/java/com/gh/common/tracker/AppLifecycleWatcher.kt index 5e927591e2..f5c67ce488 100644 --- a/app/src/main/java/com/gh/common/tracker/AppLifecycleWatcher.kt +++ b/app/src/main/java/com/gh/common/tracker/AppLifecycleWatcher.kt @@ -8,7 +8,7 @@ import java.util.concurrent.atomic.AtomicLong import kotlin.concurrent.fixedRateTimer /** - * 应用声明周期观察者 + * 应用生命周期观察者 */ class AppLifecycleWatcher(private val mTrack: ITrack) : DefaultLifecycleObserver { diff --git a/app/src/main/java/com/gh/common/tracker/Tracker.kt b/app/src/main/java/com/gh/common/tracker/Tracker.kt index 77cedec15f..64cd1cbaee 100644 --- a/app/src/main/java/com/gh/common/tracker/Tracker.kt +++ b/app/src/main/java/com/gh/common/tracker/Tracker.kt @@ -5,6 +5,10 @@ import android.app.Application import androidx.lifecycle.ProcessLifecycleOwner import java.util.* +/** + * launch_id 当前启动的唯一 id (每次应用冷启动或被内存回收时变更) + * session_id 当前会话的唯一 id (应用切换至后台超30秒时变更) + */ object Tracker : ITrack { private var mSessionId: String = "" diff --git a/app/src/main/java/com/gh/common/util/DirectUtils.kt b/app/src/main/java/com/gh/common/util/DirectUtils.kt index dcb06ae1a6..56b26debe1 100644 --- a/app/src/main/java/com/gh/common/util/DirectUtils.kt +++ b/app/src/main/java/com/gh/common/util/DirectUtils.kt @@ -660,6 +660,16 @@ object DirectUtils { jumpActivity(context, bundle) } + @JvmStatic + fun directToSingleTaskWebView(context: Context, url: String, entrance: String? = null) { + if (url.isEmpty()) return + val bundle = Bundle() + bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER) + bundle.putString(KEY_TO, SingleTaskWebActivity::class.java.simpleName) + bundle.putString(EntranceUtils.KEY_URL, url) + jumpActivity(context, bundle) + } + // 个人-系统消息 @JvmStatic fun directToOfficialNotification(context: Context, entrance: String? = null) { diff --git a/app/src/main/java/com/gh/common/util/FloatingBackViewManager.kt b/app/src/main/java/com/gh/common/util/FloatingBackViewManager.kt new file mode 100644 index 0000000000..233e970840 --- /dev/null +++ b/app/src/main/java/com/gh/common/util/FloatingBackViewManager.kt @@ -0,0 +1,100 @@ +package com.gh.common.util + +import android.app.Activity +import android.os.Build +import android.view.Gravity +import android.widget.TextView +import com.gh.gamecenter.R +import com.gh.gamecenter.energy.EnergyCenterActivity +import com.lightgame.utils.Util_System_Keyboard +import com.lzf.easyfloat.EasyFloat +import com.lzf.easyfloat.enums.ShowPattern +import com.lzf.easyfloat.enums.SidePattern + +object FloatingBackViewManager { + + const val TYPE_ACTIVITY = "type_activity" + const val TYPE_TASK = "type_task" + + private const val FLOATING_BACK_VIEW = "floating_back_view" + private var mLastY = 114F.dip2px() + + private var mType = "" + private var mActivityUrl = "" + + fun showBackView(activity: Activity) { + // 不支持 Android 4.1 的设备 + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN) return + + EasyFloat.with(activity) + .setLayout(R.layout.layout_task_back) + .setTag(FLOATING_BACK_VIEW) + .setAnimator(null) + .setGravity(Gravity.TOP.xor(Gravity.START), 0, mLastY) + .setSidePattern(SidePattern.LEFT) + .setShowPattern(ShowPattern.CURRENT_ACTIVITY) + .registerCallback { + createResult { _, _, view -> + val titleView = view?.findViewById(R.id.titleTv) + + view?.setOnClickListener { + // 先收起键盘 + Util_System_Keyboard.hideSoftKeyboard(activity) + + if (mType == TYPE_ACTIVITY) { + titleView?.text = "返回活动" + + // TODO 把 web 搞回栈顶部 +// activity.startActivity(SingleTaskWebActivity) + } else if (mType == TYPE_TASK) { + titleView?.text = "返回任务" + + activity.startActivity(EnergyCenterActivity.getIntent(activity)) + } + + disableBackView() + } + } + + dragEnd { view -> + val statusBarHeight = DisplayUtils.getStatusBarHeight(activity.resources) + + // 记录停止拖动的最后位置 + val outLocation = IntArray(2) + view.getLocationInWindow(outLocation) + val yOffset = outLocation[1] + + if (yOffset <= statusBarHeight) { + // 判断状态栏是否被消费 + if (yOffset == view.y.toInt()) { + view.y = statusBarHeight.toFloat() + } else { + view.y = 0F + } + } + + mLastY = yOffset + } + } + .show() + } + + fun getType(): String { + return mType + } + + fun hideBackView(activity: Activity) { + EasyFloat.dismiss(activity, FLOATING_BACK_VIEW) + } + + fun enableBackView(type: String, activityUrl: String = "") { + mType = type + mActivityUrl = activityUrl + } + + fun disableBackView() { + mType = "" + mActivityUrl = "" + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/MainActivity.java b/app/src/main/java/com/gh/gamecenter/MainActivity.java index f6162d7e2f..1c668fc0b8 100644 --- a/app/src/main/java/com/gh/gamecenter/MainActivity.java +++ b/app/src/main/java/com/gh/gamecenter/MainActivity.java @@ -313,9 +313,6 @@ public class MainActivity extends BaseActivity { //重置首页视频播放进度 SPUtils.setString(Constants.SP_HOME_VIDEO_PLAY_RECORD, ""); - // 重新打开APP重置"显示返回任务悬浮图标"标志位 - SPUtils.setBoolean(Constants.SP_SHOW_TASK_FLOAT, false); - postAttentionVideoRecord(); deleteSimulatorGame(); diff --git a/app/src/main/java/com/gh/gamecenter/SingleTaskWebActivity.kt b/app/src/main/java/com/gh/gamecenter/SingleTaskWebActivity.kt new file mode 100644 index 0000000000..f7cca43f3d --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/SingleTaskWebActivity.kt @@ -0,0 +1,11 @@ +package com.gh.gamecenter + +import android.content.Intent +import com.halo.assistant.fragment.WebFragment + +class SingleTaskWebActivity: WebActivity() { + + override fun provideNormalIntent(): Intent? { + return getTargetIntent(this, SingleTaskWebActivity::class.java, WebFragment::class.java) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/energy/EnergyCenterFragment.kt b/app/src/main/java/com/gh/gamecenter/energy/EnergyCenterFragment.kt index 6b7c58fedd..8dfc4f1c19 100644 --- a/app/src/main/java/com/gh/gamecenter/energy/EnergyCenterFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/energy/EnergyCenterFragment.kt @@ -52,8 +52,6 @@ class EnergyCenterFragment : BaseLazyFragment() { override fun onFragmentResume() { super.onFragmentResume() - SPUtils.setBoolean(Constants.SP_SHOW_TASK_FLOAT, false) - // 6:00-18:59 展示白天背景,否则展示夜晚背景 if (System.currentTimeMillis() >= TimeUtils.getTimeOfToday(6) && System.currentTimeMillis() < TimeUtils.getTimeOfToday(19) ) { diff --git a/app/src/main/java/com/gh/gamecenter/energy/HorizontalTaskAdapter.kt b/app/src/main/java/com/gh/gamecenter/energy/HorizontalTaskAdapter.kt index 5dd7fe6163..89204f14df 100644 --- a/app/src/main/java/com/gh/gamecenter/energy/HorizontalTaskAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/energy/HorizontalTaskAdapter.kt @@ -5,7 +5,6 @@ import android.view.ViewGroup import androidx.appcompat.app.AppCompatActivity import androidx.databinding.DataBindingUtil import com.gh.base.BaseRecyclerViewHolder -import com.gh.common.constant.Constants import com.gh.common.util.* import com.gh.gamecenter.R import com.gh.gamecenter.databinding.NoviceTaskItemBinding @@ -73,7 +72,7 @@ class HorizontalTaskAdapter(context: Context, notifyItemChanged(position) } } else { - SPUtils.setBoolean(Constants.SP_SHOW_TASK_FLOAT, true) + FloatingBackViewManager.enableBackView(FloatingBackViewManager.TYPE_TASK) DirectUtils.directToLinkPage(mContext, task.link, entrance, "") } } diff --git a/app/src/main/java/com/gh/gamecenter/energy/TaskAdapter.kt b/app/src/main/java/com/gh/gamecenter/energy/TaskAdapter.kt index 0633c7437b..7c1eaa656c 100644 --- a/app/src/main/java/com/gh/gamecenter/energy/TaskAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/energy/TaskAdapter.kt @@ -8,14 +8,15 @@ import androidx.databinding.DataBindingUtil import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.gh.base.BaseRecyclerViewHolder -import com.gh.common.constant.Constants import com.gh.common.constant.ItemViewType import com.gh.common.util.* import com.gh.gamecenter.R import com.gh.gamecenter.adapter.viewholder.FooterViewHolder import com.gh.gamecenter.baselist.ListAdapter import com.gh.gamecenter.baselist.LoadStatus -import com.gh.gamecenter.databinding.* +import com.gh.gamecenter.databinding.DailyTaskItemBinding +import com.gh.gamecenter.databinding.NoviceTasksItemBinding +import com.gh.gamecenter.databinding.TaskTitleItemBinding import com.gh.gamecenter.gamedetail.dialog.InviteCodeDialog import com.gh.gamecenter.manager.UserManager @@ -163,7 +164,7 @@ class TaskAdapter(context: Context) : ListAdapter(context) { notifyItemChanged(position) } } else { - SPUtils.setBoolean(Constants.SP_SHOW_TASK_FLOAT, true) + FloatingBackViewManager.enableBackView(FloatingBackViewManager.TYPE_TASK) DirectUtils.directToLinkPage(mContext, task.link, mEntrance, "") } } diff --git a/app/src/main/java/com/halo/assistant/HaloApp.java b/app/src/main/java/com/halo/assistant/HaloApp.java index bec81d1bb5..f1921491d1 100644 --- a/app/src/main/java/com/halo/assistant/HaloApp.java +++ b/app/src/main/java/com/halo/assistant/HaloApp.java @@ -14,7 +14,7 @@ import androidx.collection.ArrayMap; import androidx.lifecycle.ProcessLifecycleOwner; import androidx.multidex.MultiDexApplication; -import com.gh.base.GHActivityLifecycleCallbacksImpl; +import com.gh.base.GlobalActivityLifecycleObserver; import com.gh.common.AppExecutor; import com.gh.common.FixedRateJobHelper; import com.gh.common.constant.Config; @@ -195,7 +195,7 @@ public class HaloApp extends MultiDexApplication { StrictMode.setVmPolicy(policy); } - registerActivityLifecycleCallbacks(new GHActivityLifecycleCallbacksImpl()); + registerActivityLifecycleCallbacks(new GlobalActivityLifecycleObserver()); } /** diff --git a/app/src/main/res/layout/layout_task_back.xml b/app/src/main/res/layout/layout_task_back.xml index 5aca4057ea..e65c6e0029 100644 --- a/app/src/main/res/layout/layout_task_back.xml +++ b/app/src/main/res/layout/layout_task_back.xml @@ -1,25 +1,26 @@ - + android:background="@drawable/bg_task_back" + android:orientation="horizontal"> + android:textSize="12sp" /> diff --git a/dependencies.gradle b/dependencies.gradle index c0fc4916b5..564155cfcc 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -108,7 +108,8 @@ ext { whatTheStack = "0.1.0_rt" apkParser = "v2.6.10" nanohttpd = "2.3.1" - aliyunLog = "2.5.8" + aliyunLog = "2.5.14" + easyFloat = "1.3.4" sentry = "3.2.0" } \ No newline at end of file