安卓获取手机型号和刘海屏适配

先上完整代码,因为我这是和unity交互的版本,带有unity的设置就不改了,自行修改即可

package com.unity.qwe;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.Toast;

import com.SweatMa.MaTest.takephotoforunity.UnityTakePhotoActivity;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;

import java.io.File;
import java.lang.reflect.Method;
import java.util.List;

public class UnityMainAcivity extends UnityPlayerActivity {

    public static final String DISPLAY_NOTCH_STATUS = "display_notch_status";
    String carrier;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getInfo();
        getNavigationBarInfo();
        ISAndroidPFullScreen();
    }

    // 获取手机型号和厂商
    void getInfo() {
        String model = Build.MODEL;
        carrier = Build.MANUFACTURER;
        Log.d("Unity", "手机型号型号" + model + "+手机厂商+" + carrier);
    }
    void getNavigationBarInfo()
    {
        boolean hasBottom=isNavigationBarShow(this);
        Log.d("Unity","是否开启底部导航栏"+hasBottom);
        int BottomHeight=getBottomNavigatorHeight(this);
        Log.d("Unity","底部导航栏高度"+BottomHeight);
        sendBottomInfo(hasBottom,BottomHeight);
    }
    // 检查是不是安卓P全屏适配
    void ISAndroidPFullScreen() {
        Window window = getWindow();
        //SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 是显示黑边   SYSTEM_UI_FLAG_LAYOUT_STABLE 不显示黑边
        window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        // 设置界面全屏显示
        WindowManager.LayoutParams lp = window.getAttributes();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            Log.d("Unity", "是安卓P");
            lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;

            // 获取顶部状态栏高度
           int a= getTopStatusBarHeight(this);

        } else {
            Log.d("Unity", "不是安卓P"); // 不是安卓P根据各厂商方法
            if (carrier.equalsIgnoreCase("HUAWEI")) {
                checkHuaweiDisplayNotchStatus();
            } else if (carrier.equalsIgnoreCase("xiaomi")) {
                checkXiaoMiisplayNotchStatus();
            } else if (carrier.equalsIgnoreCase("oppo")) {
                checkOPPODisplayNotchStatus();
            } else if (carrier.equalsIgnoreCase("vivo")) {
                checkVIVOisplayNotchStatus();
            }


        }
        // 设置界面延伸到刘海区显示
        window.setAttributes(lp);
    }
@RequiresApi(api = Build.VERSION_CODES.P)
// 检查是否是刘海屏手机
public void getHasTop()
{
    Log.d("Unity", "点击");
    View decorView = getWindow().getDecorView();
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
        // 没有刘海的手机这里为空
        DisplayCutout displayCutout = decorView.getRootWindowInsets().getDisplayCutout();
//        Log.d("Unity", "有刘海吗"+displayCutout);
        // 不为空,是有刘海屏的设备
        if (displayCutout !=null)
        {
            int topPx=displayCutout.getSafeInsetTop(); // 安全区域距离顶部的距离(刘海/状态栏)
            List<Rect> rects = displayCutout.getBoundingRects();
            if (rects == null || rects.size() == 0) {
                Log.d("Unity", "这个不是刘海屏");
                sendTopInfo(false,topPx);
            } else {
                Log.d("Unity", "这个是刘海屏并且刘海高度为"+topPx);
                sendTopInfo(true,topPx);
            }
        }else{
            Log.d("Unity", "这个不是刘海屏设备");
            sendTopInfo(false,0);
        }


    }
}

    //--------------------- 华为 ------------------

    //检查华为的刘海状态
    void checkHuaweiDisplayNotchStatus() {
        boolean isLiuHai = hasNotchInHuawei(this);
        Log.d("Unity", "这个华为是刘海屏吗" + isLiuHai);
        if (isLiuHai)// 是华为刘海屏
        {
            int mIsNotchSwitchOpen = Settings.Secure.getInt(getContentResolver(), DISPLAY_NOTCH_STATUS, 0);
            Log.d("Unity", "刘海开启状态=" + mIsNotchSwitchOpen);
            if (mIsNotchSwitchOpen != 1) //  1 隐藏显示区域 0 是没隐藏
            {
                int liuhaiLength = getNotchSize(this);
                Log.d("Unity", "刘海长度=" + liuhaiLength);
                sendTopInfo(true,liuhaiLength);
            }
        }else{
            sendTopInfo(false,0);
        }
    }

    public static boolean hasNotchInHuawei(Context context) {
        boolean hasNotch = false;
        try {
            ClassLoader cl = context.getClassLoader();
            Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
            Method hasNotchInScreen = HwNotchSizeUtil.getMethod("hasNotchInScreen");
            if (hasNotchInScreen != null) {
                hasNotch = (boolean) hasNotchInScreen.invoke(HwNotchSizeUtil);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return hasNotch;
    }

    public static int getNotchSize(Context context) {
        int[] ret = new int[]{0, 0};
        try {
            ClassLoader cl = context.getClassLoader();
            Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
            Method get = HwNotchSizeUtil.getMethod("getNotchSize");
            ret = (int[]) get.invoke(HwNotchSizeUtil);
        } catch (ClassNotFoundException e) {
            Log.e("test", "getNotchSize ClassNotFoundException");
        } catch (NoSuchMethodException e) {
            Log.e("test", "getNotchSize NoSuchMethodException");
        } catch (Exception e) {
            Log.e("test", "getNotchSize Exception");
        } finally {
            return ret[1];
        }
    }

    //--------------------- OPPO-------------------
    void checkOPPODisplayNotchStatus() {
        boolean isLiuHai = hasNotchInOppo(this);
        Log.d("Unity", "这个OPPO是刘海屏吗" + isLiuHai);
        if (isLiuHai)// 是OPPO刘海屏
        {
            int mIsNotchSwitchOpen = Settings.Secure.getInt(getContentResolver(), DISPLAY_NOTCH_STATUS, 0);
            Log.d("Unity", "刘海开启状态=" + mIsNotchSwitchOpen);
            if (mIsNotchSwitchOpen != 1) //  1 隐藏显示区域 0 是没隐藏
            {
                int liuhaiLength = getTopStatusBarHeight(this);
                Log.d("Unity", "刘海长度=" + liuhaiLength);
                sendTopInfo(true,liuhaiLength);
            }
        }else{
            sendTopInfo(false,0);
        }
    }

    public static boolean hasNotchInOppo(Context context) {
        return context.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism");
    }



    //--------------------- VIVO-------------------
    void checkVIVOisplayNotchStatus() {
        boolean isLiuHai = hasNotchInVivo(this);
        Log.d("Unity", "这个vivo是刘海屏吗" + isLiuHai);
        if (isLiuHai)// 是vivo刘海屏
        {
            int mIsNotchSwitchOpen = Settings.Secure.getInt(getContentResolver(), DISPLAY_NOTCH_STATUS, 0);
            Log.d("Unity", "刘海开启状态=" + mIsNotchSwitchOpen);
            if (mIsNotchSwitchOpen != 1) //  1 隐藏显示区域 0 是没隐藏
            {
                int liuhaiLength = getTopStatusBarHeight(this);
                Log.d("Unity", "刘海长度=" + liuhaiLength);
                sendTopInfo(true,liuhaiLength);
            }
        }else{
            sendTopInfo(false,0);
        }
    }

    public static boolean hasNotchInVivo(Context context) {
        boolean hasNotch = false;
        try {
            ClassLoader cl = context.getClassLoader();
            Class ftFeature = cl.loadClass("android.util.FtFeature");
            Method[] methods = ftFeature.getDeclaredMethods();
            if (methods != null) {
                for (int i = 0; i < methods.length; i++) {
                    Method method = methods[i];
                    if (method != null) {
                        if (method.getName().equalsIgnoreCase("isFeatureSupport")) {
                            hasNotch = (boolean) method.invoke(ftFeature, 0x00000020);
                            break;
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            hasNotch = false;
        }
        return hasNotch;
    }


    //--------------------- 小米-------------------

    /**
     * 判断xiaomi是否有刘海屏
     * https://dev.mi.com/console/doc/detail?pId=1293
     *
     * @return
     */
    void checkXiaoMiisplayNotchStatus() {
        boolean isLiuHai = hasNotchXiaoMi(this);
        Log.d("Unity", "这个小米是刘海屏吗" + isLiuHai);
        if (isLiuHai)// 是xiaomi刘海屏
        {
            int mIsNotchSwitchOpen = Settings.Secure.getInt(getContentResolver(), DISPLAY_NOTCH_STATUS, 0);
            Log.d("Unity", "刘海开启状态=" + mIsNotchSwitchOpen);
            if (mIsNotchSwitchOpen != 1) //  1 隐藏显示区域 0 是没隐藏
            {
                int liuhaiLength = getTopStatusBarHeight(this);
                Log.d("Unity", "刘海长度=" + liuhaiLength);
                sendTopInfo(true,liuhaiLength);
            }
        }else{
            sendTopInfo(false,0);
        }
    }

    private static boolean hasNotchXiaoMi(Activity activity) {
        try {
            Class<?> c = Class.forName("android.os.SystemProperties");
            Method get = c.getMethod("getInt", String.class, int.class);
            return (int) (get.invoke(c, "ro.miui.notch", 0)) == 1;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 判断底部导航栏是否显示
     *
     * @param act
     * @return
     */
    public static boolean isNavigationBarShow(Activity act) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            Display display = act.getWindowManager().getDefaultDisplay();
            Point size = new Point();
            Point realSize = new Point();
            display.getSize(size);
            display.getRealSize(realSize);
            return realSize.y != size.y;
        } else {
            boolean menu = ViewConfiguration.get(act).hasPermanentMenuKey();
            boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
            if (menu || back) {
                return false;
            } else {
                return true;
            }
        }
    }
    /**
     * 如果有底部导航栏 获取底部导航栏高度
     * @param context
     * @return
     */
    public static int getBottomNavigatorHeight(Context context) {
        int rid = context.getResources().getIdentifier("config_showNavigationBar", "bool", "android");
//        boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey();
//        boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
        if (rid!=0) {
            int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
            return context.getResources().getDimensionPixelSize(resourceId);
        }
        return 0;
    }
    /**
     * 获取顶部状态栏高度
     * @param context
     * @return
     */
    public static int getTopStatusBarHeight(Context context) {
        int statusBarHeight = 0;
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
            Log.d("Unity","状态栏高度"+statusBarHeight);
        }

        return statusBarHeight;
    }
    //状态栏信息及刘海
    void sendTopInfo(boolean isLiuhai, int pixel)
    {
        String str;
        if (isLiuhai) // 刘海开启
        {
            str=1+"+"+pixel;
        }else // 未开启
        {
            str=0+"+"+pixel;
        }
        UnityPlayer.UnitySendMessage("Canvas","fromeAndroid",""+str);
    }
    // 底部导航栏信息
    void sendBottomInfo(boolean isOpen,int height)
    {
        String str;
        if (isOpen) // 导航栏开启
        {
            str=1+"+"+height;
        }else // 未开启
        {
            str=0+"+"+height;
        }
        UnityPlayer.UnitySendMessage("Canvas","getBottonNavigator",""+str);
    }


有个大坑!!!坑了我不知道多少时间

decorView.getRootWindowInsets()为空
DisplayCutout displayCutout = decorView.getRootWindowInsets().getDisplayCutout();
这个方法不能在onCreate中使用!!!不然会一直报空!!!恶心死我了,百度各种帖子无果,我这里面是放在了unity调用安卓的函数里
另外补充一下得到的displayCutout ,如果你的设备是没有刘海的,这里会报空,如果是有刘海的设备才会有值

发布了57 篇原创文章 · 获赞 22 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/Mediary/article/details/103259382