写一个来电话时出现的悬浮窗,一站解决黑马手机卫士来电悬浮窗的高版本安卓系统的适配问题

   日期:2020-08-27     浏览:106    评论:0    
核心提示:黑马程序员1、解决高版本小米、魅族等手机悬浮窗权限报Android permission denied for window type 2002错误。2、解决黑马程序员教学视频中悬浮窗在高版本安卓手机上不能移动的问题。    Android6

黑马程序员

1、解决高版本小米、魅族等手机悬浮窗权限报Android permission denied for window type 2002错误。

2、解决黑马程序员教学视频中悬浮窗在高版本安卓手机上不能移动的问题。

    Android6.0以上使用WindownManager实现悬浮窗会出现 Android permission denied for window type 2002 错误信息,这个是因为在Android6.0以上我们需要去设置页面设置 允许显示在其他应用上层 才可以正常使用悬浮窗。

6.0以上即使我们在清单文件中注册了

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

在有的手机中依然会报错 解决方法如下

首先判断权限不能用 ContextCompat.checkSelfPermission(context, permission)而是用下面的方法:

@RequiresApi(api = Build.VERSION_CODES.M)
    public static boolean canShowAlert(Context context){
        return Settings.canDrawOverlays(context);
    }
    

如果此方法返回false说明没有开启在其他应用上层显示 这时我们需要让用户手动去开启 否则无法使用悬浮窗

Toast.makeText(getApplicationContext(),"请给予悬浮窗权限",Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, START_WINDOW);

解决黑马程序员教学视频中悬浮窗在高版本安卓手机上不能移动的问题

设置params.type 为WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY即可解决不能移动的问题,具体flags的含义可以参考

Android 悬浮窗基本使用

public void showToast() {
        if (PermissionsUtil.canShowAlert(getApplicationContext())) {
            Log.d(TAG, "showToast: --------------------------有权限可以弹窗");

            mToast_view = View.inflate(getApplicationContext(), R.layout.toast_view, null);

            //设置Toast的具体属性值
            final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
            params.height = WindowManager.LayoutParams.WRAP_CONTENT;
            params.width = WindowManager.LayoutParams.WRAP_CONTENT;
            params.format = PixelFormat.TRANSLUCENT;
            params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
            params.setTitle("Toast");
            params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
// | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
            //得把原点定在左上才能保证坐标正确 应该是默认的原点不是左上角
            params.gravity = Gravity.LEFT + Gravity.TOP;
            //加载Toast的位置信息
            int toast_location_x = SpUtil.getInt(this, SpKey.TOAST_LOCATION_X, 0);
            int toast_location_y = SpUtil.getInt(this, SpKey.TOAST_LOCATION_Y, 0);
            //控件左上角的x坐标
            params.x = toast_location_x;
            //控件左上角的y坐标
            params.y = toast_location_y;
            Log.d(TAG, "showToast: -----------------------------------params.x = " + params.x);
            Log.d(TAG, "showToast: -----------------------------------params.y = " + params.y);

            //如果不设置这个 悬浮窗不会被移动
            params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;

            mToast_view.setOnTouchListener(new View.OnTouchListener() {
                private int mStartY;
                private int mStartX;
                @SuppressLint("ClickableViewAccessibility")
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch (event.getAction()){
                        //当点击时
                        case MotionEvent.ACTION_DOWN:
                            Log.d(TAG, "onTouch: ----------------------------悬浮窗被按下");
                            //记录起始位置
// getX是以组件左上角为坐标原点,获取X坐标轴上的值。
// getRawX是以屏幕左上角为左脚做预案,获取X坐标轴上的值。
                            mStartX = (int) event.getRawX();
                            mStartY = (int) event.getRawY();
                            break;
                        //当移动时
                        case MotionEvent.ACTION_MOVE:
                            Log.d(TAG, "onTouch: ----------------------------悬浮窗被移动");
                            //记录移动完的位置
                            int endX = (int) event.getRawX();
                            int endY = (int) event.getRawY();

                            //计算差值
                            int disX = endX - mStartX;
                            int disY = endY - mStartY;

                            //容错处理

                            //得到移动完的具体位置
                            params.x = params.x + disX;
                            params.y = params.y + disY;

                            //更新位置
                            mWm.updateViewLayout(mToast_view,params);

                            //重置起始位置 将最后的位置当成起始位置
                            mStartX = endX;
                            mStartY = endY;
                            break;
                        //当抬起时
                        case MotionEvent.ACTION_UP:
                            //保存位置
                            SpUtil.putInt(getApplicationContext(), SpKey.TOAST_LOCATION_X,params.x);
                            SpUtil.putInt(getApplicationContext(), SpKey.TOAST_LOCATION_Y,params.y);
                            break;
                    }
                    //只有触摸事件时返回值是true才能响应触摸事件
                    //既有触摸事件又有点击事件时 返回false 点击事件才能生效 P964
                    return true;
                }
            });

            //给窗体添加这个吐司
            mWm.addView(mToast_view, params);
        }else {
            Toast.makeText(this,"悬浮窗权限已被拒绝",Toast.LENGTH_SHORT).show();
        }
       }
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服