解决小米,魅族手机打开悬浮窗口问题

当开启一个悬浮窗口时,发现三星,华为都能够开启,无论系统为android4.4.4、android5.1.1还是android6.0,但是当用小米手机或者魅族的时候发现打不开了,检查manifest中的android.permission.SYSTEM_ALERT_WINDOW权限,我也加了啊,但是就是不好使,这个权限也不是android6.0中的敏感权限,所以android6.0动态申请权限是行不通的,这个问题找了好久,发现很难通过代码去打开悬浮窗,没辙之后想到,调到应用的设置界面去吧,引导用户手动的去打开。下面是三星和小米手机的运行效果,魅族的和小米的效果差不多就没贴动图了。

三星Galaxy (android6.0)手机上运行的效果:

解决小米,魅族手机打开悬浮窗口问题_第1张图片


小米5(android6.0)上运行效果:


解决小米,魅族手机打开悬浮窗口问题_第2张图片


首先添加权限


Build.MANUFACTURER这个可以获取手机的型号,可以分辨是小米还是魅族

    public void open(View v){
        //开启悬浮框前先请求权限
        if("Xiaomi".equals(Build.MANUFACTURER)){//小米手机
            requestPermission();
        }else if("Meizu".equals(Build.MANUFACTURER)){//魅族手机
            requestPermission();
        }else {//其他手机
            CallFloatBoxView.showFloatBox(this);
        }
    }

 /**
     * 请求用户给予悬浮窗的权限
     */
    public void requestPermission() {
        if(isFloatWindowOpAllowed(this)){//已经开启
            CallFloatBoxView.showFloatBox(this);
        }else {
            openSetting();
        }
    }

    /**
     * 打开权限设置界面
     */
    public void openSetting() {
        try {
            Intent localIntent = new Intent(
                    "miui.intent.action.APP_PERM_EDITOR");
            localIntent.setClassName("com.miui.securitycenter",
                            "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
            localIntent.putExtra("extra_pkgname", getPackageName());
            startActivityForResult(localIntent,11);

        } catch (ActivityNotFoundException localActivityNotFoundException) {
            Intent intent1 = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            Uri uri = Uri.fromParts("package", getPackageName(), null);
            intent1.setData(uri);
            startActivityForResult(intent1,11);
        }

    }

完整的类如下:

package com.cool.hello.widget;

import android.annotation.TargetApi;
import android.app.AppOpsManager;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.cool.hello.R;

import java.lang.reflect.Method;

public class WatchBoardViewActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_watch_board_view);


    }

    public void open(View v){
        //开启悬浮框前先请求权限
        if("Xiaomi".equals(Build.MANUFACTURER)){//小米手机
            requestPermission();
        }else if("Meizu".equals(Build.MANUFACTURER)){//魅族手机
            requestPermission();
        }else {//其他手机
            CallFloatBoxView.showFloatBox(this);
        }
    }

    public void close(View v){
        CallFloatBoxView.hideFloatBox();
    }

    /**
     * 请求用户给予悬浮窗的权限
     */
    public void requestPermission() {
        if(isFloatWindowOpAllowed(this)){//已经开启
            CallFloatBoxView.showFloatBox(this);
        }else {
            openSetting();
        }
    }

    /**
     * 打开权限设置界面
     */
    public void openSetting() {
        try {
            Intent localIntent = new Intent(
                    "miui.intent.action.APP_PERM_EDITOR");
            localIntent.setClassName("com.miui.securitycenter",
                            "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
            localIntent.putExtra("extra_pkgname", getPackageName());
            startActivityForResult(localIntent,11);

        } catch (ActivityNotFoundException localActivityNotFoundException) {
            Intent intent1 = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            Uri uri = Uri.fromParts("package", getPackageName(), null);
            intent1.setData(uri);
            startActivityForResult(intent1,11);
        }

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == 11){
            if(isFloatWindowOpAllowed(this)){//已经开启
                CallFloatBoxView.showFloatBox(this);
            }else {
                Toast.makeText(this,"开启悬浮窗失败",Toast.LENGTH_SHORT).show();
            }
        }
    }

    /**
     * 判断悬浮窗权限
     *
     * @param context
     * @return
     */
    @TargetApi(Build.VERSION_CODES.KITKAT)
    public static boolean isFloatWindowOpAllowed(Context context) {
        final int version = Build.VERSION.SDK_INT;
        if (version >= 19) {
            return checkOp(context, 24);  // AppOpsManager.OP_SYSTEM_ALERT_WINDOW
        } else {
            if ((context.getApplicationInfo().flags & 1 << 27) == 1 << 27) {
                return true;
            } else {
                return false;
            }
        }
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    public static boolean checkOp(Context context, int op) {
        final int version = Build.VERSION.SDK_INT;

        if (version >= 19) {
            AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
            try {

                Class spClazz = Class.forName(manager.getClass().getName());
                Method method = manager.getClass().getDeclaredMethod("checkOp", int.class, int.class, String.class);
                int property = (Integer) method.invoke(manager, op,
                        Binder.getCallingUid(), context.getPackageName());
                Log.e("399"," property: " + property);

                if (AppOpsManager.MODE_ALLOWED == property) {
                    return true;
                } else {
                    return false;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            Log.e("399","Below API 19 cannot invoke!");
        }
        return false;
    }

}

悬浮窗:CallFloatBoxView.java

package com.cool.hello.widget;

import android.content.Context;
import android.graphics.PixelFormat;
import android.os.Build;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;

import com.cool.hello.R;

/**
 * Created by cool on 2016/8/25.
 */
public class CallFloatBoxView {
    private static Context mContext;
    private static View mView;
    private static Boolean isShown = false;
    private static WindowManager wm;

    public static void showFloatBox(Context context) {
        if (isShown) {
            return;
        }
        isShown = true;

        mContext = context;
        wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        final WindowManager.LayoutParams params = new WindowManager.LayoutParams();

        int type;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            type = WindowManager.LayoutParams.TYPE_TOAST;
        } else {
            type = WindowManager.LayoutParams.TYPE_PHONE;
        }
        params.type = type;
        params.flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;

        params.format = PixelFormat.TRANSLUCENT;
        params.width = ViewGroup.LayoutParams.WRAP_CONTENT;
        params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
        params.gravity = Gravity.CENTER;
        params.x = context.getResources().getDisplayMetrics().widthPixels;
        params.y = 0;
        ImageView imageView = new ImageView(mContext);
        imageView.setImageResource(R.drawable.sese);
        mView = imageView;
        mView.setOnTouchListener(new View.OnTouchListener() {
            float lastX, lastY;
            int oldOffsetX, oldOffsetY;
            int tag = 0;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                final int action = event.getAction();
                float x = event.getX();
                float y = event.getY();
                if (tag == 0) {
                    oldOffsetX = params.x;
                    oldOffsetY = params.y;
                }
                if (action == MotionEvent.ACTION_DOWN) {
                    lastX = x;
                    lastY = y;
                } else if (action == MotionEvent.ACTION_MOVE) {
                    // 减小偏移量,防止过度抖动
                    params.x += (int) (x - lastX) / 3;
                    params.y += (int) (y - lastY) / 3;
                    tag = 1;
                    if (mView != null)
                        wm.updateViewLayout(mView, params);
                } else if (action == MotionEvent.ACTION_UP) {
                    int newOffsetX = params.x;
                    int newOffsetY = params.y;
                    if (Math.abs(oldOffsetX - newOffsetX) <= 20 && Math.abs(oldOffsetY - newOffsetY) <= 20) {

                    } else {
                        tag = 0;
                    }
                }
                return true;
            }
        });
        wm.addView(mView, params);
    }

    public static void hideFloatBox() {
        if (isShown && null != mView) {
            wm.removeView(mView);
            isShown = false;
            mView = null;
        }
    }
}


最后非常感谢这篇博文:http://blog.csdn.net/cankingapp/article/details/51569576





 
 

你可能感兴趣的:(Android)