先上完整代码,因为我这是和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
,如果你的设备是没有刘海的,这里会报空,如果是有刘海的设备才会有值