package com.yhao.floatwindow.impl; import android.app.Activity; import android.app.Application; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.os.Handler; import com.yhao.floatwindow.interfaces.IConfigChanged; import com.yhao.floatwindow.interfaces.LifecycleListener; import com.yhao.floatwindow.interfaces.ResumedListener; import com.yhao.floatwindow.utils.FwContent; import com.yhao.floatwindow.utils.L; import com.yhao.floatwindow.utils.RotateUtil; import com.yhao.floatwindow.utils.ViewUtils; import java.util.HashMap; import java.util.Map; /** * @Copyright © 2017 Analysys Inc. All rights reserved. * @Description: <pre> * 用于控制悬浮窗显示周期 使用了三种方法针对返回桌面时隐藏悬浮按钮 * 1. startCount计数,针对back到桌面可以及时隐藏 * 2.监听home键,从而及时隐藏 * 3.resumeCount计时,针对一些只执行onPause不执行onStop的奇葩情况 * </pre> * @Version: 1.0.9 * @Create: 2017-12-1 17:04:11 * @Author: yhao */ public class FloatLifecycleReceiver extends BroadcastReceiver implements Application.ActivityLifecycleCallbacks { private static final String SYSTEM_DIALOG_REASON_KEY = "reason"; private static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"; private static final long DELAY = 300; private static ResumedListener sResumedListener; private static int num = 0; private Handler mHandler; private Class<?>[] activities; private boolean showFlag; private int startCount; private int resumeCount; private boolean appBackground; private LifecycleListener mLifecycleListener = null; private IConfigChanged mConfigChange = null; // 存储当前页面的信息,为切换页面时作为上个页面进行旋转屏幕比较 private Map<String, Boolean> mActivityAndLandscape = new HashMap<String, Boolean>(); private FloatLifecycleReceiver() { } public FloatLifecycleReceiver(Context applicationContext, boolean showFlag, Class<?>[] activities, LifecycleListener lifecycleListener) { this.showFlag = showFlag; this.activities = activities; num++; mLifecycleListener = lifecycleListener; mHandler = new Handler(); ((Application) applicationContext).registerActivityLifecycleCallbacks(this); applicationContext.registerReceiver(this, new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); } public static void setResumedListener(ResumedListener resumedListener) { sResumedListener = resumedListener; } private boolean needShow(Activity activity) { if (activities == null) { return true; } for (Class<?> a : activities) { if (a.isInstance(activity)) { return showFlag; } } return !showFlag; } public void setConfigChanged(IConfigChanged configChanged) { if (configChanged != null) { mConfigChange = configChanged; } } @Override public void onActivityResumed(Activity activity) { if (mConfigChange != null) { mConfigChange.onBackToDesktop(false); } checkConfigChangeWhenResume(activity); if (sResumedListener != null) { num--; if (num == 0) { sResumedListener.onResumed(); sResumedListener = null; } } resumeCount++; if (needShow(activity)) { mLifecycleListener.onShow(); } else { mLifecycleListener.onHide(); } if (appBackground) { appBackground = false; } } @Override public void onActivityPaused(final Activity activity) { if (mConfigChange != null) { mConfigChange.onBackToDesktop(false); } checkConfigChangeWhenPause(activity); resumeCount--; mHandler.postDelayed(new Runnable() { @Override public void run() { if (resumeCount == 0) { appBackground = true; mLifecycleListener.onBackToDesktop(); if (mConfigChange != null) { mConfigChange.onBackToDesktop(true); } } } }, DELAY); } @Override public void onActivityStarted(Activity activity) { startCount++; } @Override public void onActivityStopped(Activity activity) { if (mConfigChange != null) { mConfigChange.onBackToDesktop(false); } startCount--; if (startCount == 0) { mLifecycleListener.onBackToDesktop(); if (mConfigChange != null) { mConfigChange.onBackToDesktop(true); } } } @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action != null && action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) { String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY); if (SYSTEM_DIALOG_REASON_HOME_KEY.equals(reason)) { mLifecycleListener.onBackToDesktop(); if (mConfigChange != null) { mConfigChange.onBackToDesktop(true); } } } } @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override public void onActivityDestroyed(Activity activity) { } public void unRegisterReceiver(Context context) { ((Application) context).unregisterActivityLifecycleCallbacks(this); context.unregisterReceiver(this); } /** * 页面展示时检查是否页面旋转。逻辑: 和上个页面对比 * * @param activity */ private void checkConfigChangeWhenResume(Activity activity) { if (mActivityAndLandscape.size() > 0) { mActivityAndLandscape.clear(); } if (FwContent.isDebug) { L.i("------checkConfigChangeWhenResume----mActivityAndLandscape: " + mActivityAndLandscape.size()); } RotateUtil.getInstance().start(activity); String activityName = activity.getPackageName() + "." + activity.getLocalClassName(); if (mActivityAndLandscape.size() < 1) { // 有悬浮窗后的,首次切换页面 mActivityAndLandscape.put(activityName, ViewUtils.isActivityLandscape(activity)); if (mConfigChange != null) { mConfigChange.onActivityConfigChanged(); } } else { if (mActivityAndLandscape.containsKey(activityName)) { boolean isLandscape = ViewUtils.isActivityLandscape(activity); if (mActivityAndLandscape.get(activityName) != isLandscape) { mActivityAndLandscape.put(activityName, isLandscape); if (mConfigChange != null) { mConfigChange.onActivityConfigChanged(); } } else { // 页面方向未变 } } else { mActivityAndLandscape.clear(); // 有悬浮窗后的,首次切换页面 mActivityAndLandscape.put(activityName, ViewUtils.isActivityLandscape(activity)); if (mConfigChange != null) { mConfigChange.onActivityConfigChanged(); } } } } /** * 页面关闭时检查页面监听监视 * * @param activity */ private void checkConfigChangeWhenPause(Activity activity) { RotateUtil.getInstance().start(activity); if (mActivityAndLandscape.size() < 1) { // 有悬浮窗后的,首次关闭页面-(兼容页面打开,才展示悬浮窗,此时map无此页面信息) String activityName = activity.getPackageName() + "." + activity.getLocalClassName(); mActivityAndLandscape.put(activityName, ViewUtils.isActivityLandscape(activity)); } } }