突破小米悬浮窗权限控制--不需要权限的悬浮窗

突破小米悬浮窗权限控制–不需要权限的悬浮窗

在上一篇文章讲了Android的Toast拓展,在原生Toast基础上对显示时长和显示动画做了二次封装,强化了Toast的部分功能。也分析了对于二次封装的ExToast设计原理,以及Toast的关键点。如果不了解的可以看看下面的链接。

Toast拓展–自定义显示时间和动画


常用悬浮窗与Toast

之前分析过,Toast其实就是系统悬浮窗的一种,那它跟常用的系统悬浮窗有什么区别呢?

先看一下常用的Andoird系统悬浮窗写法:

// 获取应用的Context
mContext = context.getApplicationContext();
// 获取WindowManager
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mView = setUpView(context);

final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
// 类型
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;

int flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
params.flags = flags;
params.format = PixelFormat.TRANSLUCENT;
params.width = LayoutParams.MATCH_PARENT;
params.height = LayoutParams.MATCH_PARENT;
params.gravity = Gravity.CENTER;
mWindowManager.addView(mView, params);

再看看在Toast源码里面的写法关键代码:

final WindowManager.LayoutParams params = mParams;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.format = PixelFormat.TRANSLUCENT;
params.windowAnimations = com.android.internal.R.style.Animation_Toast;
// 类型
params.type = WindowManager.LayoutParams.TYPE_TOAST;
params.setTitle("Toast");
params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
...    
// 获取应用的context
Context context = mView.getContext().getApplicationContext();
// 获取WindowManager
mWM = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
...
if (mView.getParent() != null) {
    mWM.removeView(mView);
}
mWM.addView(mView, mParams);    

上面的两段代码大致流程都是一样的:创建WindowManager.LayoutParams做窗口的配置->通过context获取WindowManager服务->通过WindowManager服务添加悬浮窗View

主要的不同点在于WindowManager.LayoutParams的type。
WindowManager.LayoutParams的type有很多种,包括各种系统对话框,锁屏窗口,电话窗口等等,但这些窗口基本上都是需要权限的。

而我们平时使用的Toast,并不需要权限就能显示,那就可以尝试直接把悬浮窗的类型设成TYPE_TOAST,来定制一个不需要权限的悬浮窗。

下面是demo代码:

import android.content.Context;
import android.graphics.PixelFormat;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;

public class ADToast implements View.OnTouchListener {
   

    Context mContext;
    WindowManager.LayoutParams params;
    WindowManager mWM;
    View mView;

    private float mTouchStartX;
    private float mTouchStartY;
    private float x;
    private float y;

    public ADToast(Context context){
        this.mContext = context;
        params = new WindowManager.LayoutParams();
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        params.format = PixelFormat.TRANSLUCENT;
        params.windowAnimations = R.style.anim_view;
        // 悬浮窗类型,整个demo的关键点
        params.type = WindowManager.LayoutParams.TYPE_TOAST;
        params.gravity = Gravity.LEFT | Gravity.TOP;
        params.setTitle("Toast");
        params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        mWM = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
        LayoutInflater inflate = (LayoutInflater)
                mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mView = inflate.inflate(R.layout.float_tips_layout, null);
        mView.setOnTouchListener(this);
    }

    public void show(){
        TextView tv = (TextView)mView.findViewById(R.id.message);
        tv.setText("悬浮窗");
        if (mView.getParent() != null) {
   
评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值