开发常驻应用时遇到这样的需求:点击配网或者某一项跳转到了系统设置界面,这时候要求界面上出现一个悬浮按钮,点击悬浮按钮后要能够快速返回到自己的应用。这里面主要涉及到两个点:悬浮窗、应用前后台切换
首先说一下应用前后台监听,这里是结合application生命周期和APP是否在前台或后台运行做的处理:
private int mFinalCount;
private void initLifeCycle() {
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
LogMgr.d(TAG, "onActivityCreated");
}
@Override public void onActivityStarted(Activity activity) {
LogMgr.d(TAG, "onActivityStarted");
mFinalCount++;
//如果mFinalCount ==1,说明是从后台到前台
if (mFinalCount == 1 && !(TopActivityManager.getInstance()
.getCurrentActivity() instanceof FlashActivity)) {
//说明从后台回到了前台
FloatWindowManager.getInstance().dismissWindow();
}
}
@Override public void onActivityResumed(Activity activity) {
LogMgr.d(TAG, "onActivityResumed");
}
@Override public void onActivityPaused(Activity activity) {
LogMgr.d(TAG, "onActivityPaused");
}
@Override public void onActivityStopped(Activity activity) {
LogMgr.d(TAG, "onActivityStopped");
mFinalCount--;
//如果mFinalCount == 0,说明是前台到后台
if (mFinalCount == 0 && SystemHelper.isRunningBackground(ContextUtils.getContext())) {
FloatWindowManager.getInstance().applyOrShowFloatWindow(getApplicationContext());
}
}
@Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
LogMgr.d(TAG, "onActivitySaveInstanceState");
}
@Override public void onActivityDestroyed(Activity activity) {
LogMgr.d(TAG, "onActivityDestroyed");
}
});
}
这里通过一个变量记录当前打开的activity个数,配合当前显示的activity和是否在后端运行来判断出前后台切换,同时显示和隐藏掉悬浮窗
悬浮窗代码:
package com.unisound.smartphone.utils;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;
import android.view.Gravity;
import android.view.WindowManager;
import com.unisound.sdk.service.utils.ContextUtils;
import com.unisound.sdk.service.utils.LogMgr;
import com.unisound.smartphone.ui.AVCallFloatView;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
public class FloatWindowManager {
private static final String TAG = "FloatWindowManager";
private static volatile FloatWindowManager instance;
private boolean isWindowDismiss = true;
private WindowManager windowManager = null;
private WindowManager.LayoutParams mParams = null;
private AVCallFloatView floatView = null;
private Dialog dialog;
public static FloatWindowManager getInstance() {
if (instance == null) {
synchronized (FloatWindowManager.class) {
if (instance == null) {
instance = new FloatWindowManager();
}
}
}
return instance;
}
public void applyOrShowFloatWindow(Context context) {
if (isRunBackground(context)) {
if (checkPermission(context)) {
showWindow(context);
} else {
applyPermission(context);
}
}
}
private boolean checkPermission(Context context) {
return commonROMPermissionCheck(context);
}
private boolean commonROMPermissionCheck(Context context) {
Boolean result = true;
if (Build.VERSION.SDK_INT >= 23) {
try {
Class clazz = Settings.class;
Method canDrawOverlays = clazz.getDeclaredMethod("canDrawOv