a
This commit is contained in:
@@ -0,0 +1 @@
|
||||
/build
|
||||
@@ -0,0 +1,68 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'kotlin-parcelize'
|
||||
apply plugin: 'com.google.dagger.hilt.android'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
buildToolsVersion rootProject.ext.android.buildToolsVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
versionCode rootProject.ext.android.versionCode
|
||||
versionName rootProject.ext.android.versionName
|
||||
multiDexEnabled true
|
||||
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
|
||||
javaCompileOptions {
|
||||
annotationProcessorOptions {
|
||||
arguments += [
|
||||
"room.schemaLocation":"$projectDir/schemas".toString(),
|
||||
"room.incremental":"true",
|
||||
"room.expandProjection":"true",
|
||||
AROUTER_MODULE_NAME: project.getName()
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
}
|
||||
|
||||
kapt {
|
||||
arguments {
|
||||
arg("AROUTER_MODULE_NAME", project.getName())
|
||||
}
|
||||
generateStubs = true
|
||||
useBuildCache = true
|
||||
javacOptions {
|
||||
option("-Xmaxerrs", 500)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
compileOnly(rootProject.ext.jetpack["hilt"])
|
||||
kapt rootProject.ext.compiler["hiltAndroidCompiler"]
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.bbgo.library_statusbar
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.bbgo.library_statusbar.test", appContext.packageName)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.bbgo.library_statusbar">
|
||||
|
||||
</manifest>
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.bbgo.library_statusbar;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Rect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface INotchScreen {
|
||||
|
||||
boolean hasNotch(Activity activity);
|
||||
|
||||
void setDisplayInNotch(Activity activity);
|
||||
|
||||
void getNotchRect(Activity activity, NotchSizeCallback callback);
|
||||
|
||||
interface NotchSizeCallback {
|
||||
void onResult(List<Rect> notchRects);
|
||||
}
|
||||
|
||||
interface HasNotchCallback {
|
||||
void onResult(boolean hasNotch);
|
||||
}
|
||||
|
||||
interface NotchScreenCallback {
|
||||
void onResult(NotchScreenInfo notchScreenInfo);
|
||||
}
|
||||
|
||||
class NotchScreenInfo {
|
||||
public boolean hasNotch;
|
||||
public List<Rect> notchRects;
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package com.bbgo.library_statusbar;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
|
||||
import com.bbgo.library_statusbar.impl.AndroidPNotchScreen;
|
||||
import com.bbgo.library_statusbar.impl.HuaweiNotchScreen;
|
||||
import com.bbgo.library_statusbar.impl.MiNotchScreen;
|
||||
import com.bbgo.library_statusbar.impl.OppoNotchScreen;
|
||||
import com.bbgo.library_statusbar.utils.RomUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class NotchScreenManager {
|
||||
|
||||
private static final NotchScreenManager instance = new NotchScreenManager();
|
||||
private final INotchScreen notchScreen;
|
||||
|
||||
private NotchScreenManager() {
|
||||
notchScreen = getNotchScreen();
|
||||
}
|
||||
|
||||
public static NotchScreenManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void setDisplayInNotch(Activity activity) {
|
||||
if (notchScreen != null)
|
||||
notchScreen.setDisplayInNotch(activity);
|
||||
}
|
||||
|
||||
public void getNotchInfo(final Activity activity, final INotchScreen.NotchScreenCallback notchScreenCallback) {
|
||||
final INotchScreen.NotchScreenInfo notchScreenInfo = new INotchScreen.NotchScreenInfo();
|
||||
if (notchScreen != null && notchScreen.hasNotch(activity)) {
|
||||
notchScreen.getNotchRect(activity, new INotchScreen.NotchSizeCallback() {
|
||||
@Override
|
||||
public void onResult(List<Rect> notchRects) {
|
||||
if (notchRects != null && notchRects.size() > 0) {
|
||||
notchScreenInfo.hasNotch = true;
|
||||
notchScreenInfo.notchRects = notchRects;
|
||||
}
|
||||
notchScreenCallback.onResult(notchScreenInfo);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
notchScreenCallback.onResult(notchScreenInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private INotchScreen getNotchScreen() {
|
||||
INotchScreen notchScreen = null;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
notchScreen = new AndroidPNotchScreen();
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (RomUtils.isHuawei()) {
|
||||
notchScreen = new HuaweiNotchScreen();
|
||||
} else if (RomUtils.isOppo()) {
|
||||
notchScreen = new OppoNotchScreen();
|
||||
} else if (RomUtils.isVivo()) {
|
||||
notchScreen = new HuaweiNotchScreen();
|
||||
} else if (RomUtils.isXiaomi()) {
|
||||
notchScreen = new MiNotchScreen();
|
||||
}
|
||||
}
|
||||
return notchScreen;
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
package com.bbgo.library_statusbar.impl;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.view.DisplayCutout;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
|
||||
|
||||
import com.bbgo.library_statusbar.INotchScreen;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
public class AndroidPNotchScreen implements INotchScreen {
|
||||
|
||||
/**
|
||||
* Android P 没有单独的判断方法,根据getNotchRect方法的返回结果处理即可
|
||||
*/
|
||||
@Override
|
||||
public boolean hasNotch(Activity activity) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplayInNotch(Activity activity) {
|
||||
Window window = activity.getWindow();
|
||||
// 延伸显示区域到耳朵区
|
||||
WindowManager.LayoutParams lp = window.getAttributes();
|
||||
lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
|
||||
window.setAttributes(lp);
|
||||
// 允许内容绘制到耳朵区
|
||||
final View decorView = window.getDecorView();
|
||||
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNotchRect(Activity activity, final NotchSizeCallback callback) {
|
||||
final View contentView = activity.getWindow().getDecorView();
|
||||
contentView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
WindowInsets windowInsets = contentView.getRootWindowInsets();
|
||||
if (windowInsets != null) {
|
||||
DisplayCutout cutout = windowInsets.getDisplayCutout();
|
||||
if (cutout != null) {
|
||||
List<Rect> rects = cutout.getBoundingRects();
|
||||
callback.onResult(rects);
|
||||
return;
|
||||
}
|
||||
}
|
||||
callback.onResult(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
package com.bbgo.library_statusbar.impl;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
|
||||
import com.bbgo.library_statusbar.INotchScreen;
|
||||
import com.bbgo.library_statusbar.utils.ScreenUtil;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class HuaweiNotchScreen implements INotchScreen {
|
||||
/**
|
||||
* 刘海屏全屏显示FLAG
|
||||
*/
|
||||
public static final int FLAG_NOTCH_SUPPORT = 0x00010000;
|
||||
|
||||
/**
|
||||
* 设置华为刘海屏手机不使用刘海区
|
||||
*/
|
||||
public static void setNotDisplayInNotch(Activity activity) {
|
||||
try {
|
||||
Window window = activity.getWindow();
|
||||
WindowManager.LayoutParams layoutParams = window.getAttributes();
|
||||
Class layoutParamsExCls = Class.forName("com.huawei.android.view.LayoutParamsEx");
|
||||
Constructor con = layoutParamsExCls.getConstructor(WindowManager.LayoutParams.class);
|
||||
Object layoutParamsExObj = con.newInstance(layoutParams);
|
||||
Method method = layoutParamsExCls.getMethod("clearHwFlags", int.class);
|
||||
method.invoke(layoutParamsExObj, FLAG_NOTCH_SUPPORT);
|
||||
window.getWindowManager().updateViewLayout(window.getDecorView(), window.getDecorView().getLayoutParams());
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNotch(Activity activity) {
|
||||
boolean ret = false;
|
||||
try {
|
||||
ClassLoader cl = activity.getClassLoader();
|
||||
Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
|
||||
Method get = HwNotchSizeUtil.getMethod("hasNotchInScreen");
|
||||
ret = (boolean) get.invoke(HwNotchSizeUtil);
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplayInNotch(Activity activity) {
|
||||
try {
|
||||
Window window = activity.getWindow();
|
||||
WindowManager.LayoutParams layoutParams = window.getAttributes();
|
||||
Class layoutParamsExCls = Class.forName("com.huawei.android.view.LayoutParamsEx");
|
||||
Constructor con = layoutParamsExCls.getConstructor(WindowManager.LayoutParams.class);
|
||||
Object layoutParamsExObj = con.newInstance(layoutParams);
|
||||
Method method = layoutParamsExCls.getMethod("addHwFlags", int.class);
|
||||
method.invoke(layoutParamsExObj, FLAG_NOTCH_SUPPORT);
|
||||
window.getWindowManager().updateViewLayout(window.getDecorView(), window.getDecorView().getLayoutParams());
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNotchRect(Activity activity, NotchSizeCallback callback) {
|
||||
try {
|
||||
ClassLoader cl = activity.getClassLoader();
|
||||
Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
|
||||
Method get = HwNotchSizeUtil.getMethod("getNotchSize");
|
||||
int[] ret = (int[]) get.invoke(HwNotchSizeUtil);
|
||||
ArrayList<Rect> rects = new ArrayList<>();
|
||||
rects.add(ScreenUtil.calculateNotchRect(activity, ret[0], ret[1]));
|
||||
callback.onResult(rects);
|
||||
} catch (Throwable ignore) {
|
||||
callback.onResult(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package com.bbgo.library_statusbar.impl;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.view.Window;
|
||||
|
||||
import com.bbgo.library_statusbar.INotchScreen;
|
||||
import com.bbgo.library_statusbar.utils.ScreenUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class MiNotchScreen implements INotchScreen {
|
||||
private static boolean isNotch() {
|
||||
try {
|
||||
Method getInt = Class.forName("android.os.SystemProperties").getMethod("getInt", String.class, int.class);
|
||||
int notch = (int) getInt.invoke(null, "ro.miui.notch", 0);
|
||||
return notch == 1;
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int getNotchHeight(Context context) {
|
||||
int resourceId = context.getResources().getIdentifier("notch_height", "dimen", "android");
|
||||
if (resourceId > 0) {
|
||||
return context.getResources().getDimensionPixelSize(resourceId);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int getNotchWidth(Context context) {
|
||||
int resourceId = context.getResources().getIdentifier("notch_width", "dimen", "android");
|
||||
if (resourceId > 0) {
|
||||
return context.getResources().getDimensionPixelSize(resourceId);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNotch(Activity activity) {
|
||||
return isNotch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplayInNotch(Activity activity) {
|
||||
int flag = 0x00000100 | 0x00000200 | 0x00000400;
|
||||
try {
|
||||
Method method = Window.class.getMethod("addExtraFlags",
|
||||
int.class);
|
||||
method.invoke(activity.getWindow(), flag);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNotchRect(Activity activity, NotchSizeCallback callback) {
|
||||
Rect rect = ScreenUtil.calculateNotchRect(activity, getNotchWidth(activity), getNotchHeight(activity));
|
||||
ArrayList<Rect> rects = new ArrayList<>();
|
||||
rects.add(rect);
|
||||
callback.onResult(rects);
|
||||
}
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
package com.bbgo.library_statusbar.impl;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
|
||||
|
||||
import com.bbgo.library_statusbar.INotchScreen;
|
||||
import com.bbgo.library_statusbar.utils.ScreenUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class OppoNotchScreen implements INotchScreen {
|
||||
|
||||
/**
|
||||
* 获取刘海的坐标
|
||||
* <p>
|
||||
* 属性形如:[ro.oppo.screen.heteromorphism]: [378,0:702,80]
|
||||
* <p>
|
||||
* 获取到的值为378,0:702,80
|
||||
* <p>
|
||||
* <p>
|
||||
* (378,0)是刘海区域左上角的坐标
|
||||
* <p>
|
||||
* (702,80)是刘海区域右下角的坐标
|
||||
*/
|
||||
private static String getScreenValue() {
|
||||
String value = "";
|
||||
Class<?> cls;
|
||||
try {
|
||||
cls = Class.forName("android.os.SystemProperties");
|
||||
Method get = cls.getMethod("get", String.class);
|
||||
Object object = cls.newInstance();
|
||||
value = (String) get.invoke(object, "ro.oppo.screen.heteromorphism");
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNotch(Activity activity) {
|
||||
boolean ret = false;
|
||||
try {
|
||||
ret = activity.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism");
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setDisplayInNotch(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNotchRect(Activity activity, NotchSizeCallback callback) {
|
||||
try {
|
||||
String screenValue = getScreenValue();
|
||||
if (!TextUtils.isEmpty(screenValue)) {
|
||||
String[] split = screenValue.split(":");
|
||||
String leftTopPoint = split[0];
|
||||
String[] leftAndTop = leftTopPoint.split(",");
|
||||
String rightBottomPoint = split[1];
|
||||
String[] rightAndBottom = rightBottomPoint.split(",");
|
||||
int left;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
if (ScreenUtil.isPortrait(activity)) {
|
||||
left = Integer.valueOf(leftAndTop[0]);
|
||||
top = Integer.valueOf(leftAndTop[1]);
|
||||
right = Integer.valueOf(rightAndBottom[0]);
|
||||
bottom = Integer.valueOf(rightAndBottom[1]);
|
||||
} else {
|
||||
left = Integer.valueOf(leftAndTop[1]);
|
||||
top = Integer.valueOf(leftAndTop[0]);
|
||||
right = Integer.valueOf(rightAndBottom[1]);
|
||||
bottom = Integer.valueOf(rightAndBottom[0]);
|
||||
}
|
||||
Rect rect = new Rect(left, top, right, bottom);
|
||||
ArrayList<Rect> rects = new ArrayList<>();
|
||||
rects.add(rect);
|
||||
callback.onResult(rects);
|
||||
}
|
||||
} catch (Throwable ignore) {
|
||||
callback.onResult(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package com.bbgo.library_statusbar.impl;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
import com.bbgo.library_statusbar.INotchScreen;
|
||||
import com.bbgo.library_statusbar.utils.ScreenUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* 测试之后发现vivo并不需要适配,因为vivo没有将显示区域绘制到耳朵区的API
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class VivoNotchScreen implements INotchScreen {
|
||||
public static boolean isNotch() {
|
||||
boolean value = false;
|
||||
int mask = 0x00000020;
|
||||
try {
|
||||
Class<?> cls = Class.forName("android.util.FtFeature");
|
||||
Method hideMethod = cls.getMethod("isFtFeatureSupport", int.class);
|
||||
Object object = cls.newInstance();
|
||||
value = (boolean) hideMethod.invoke(object, mask);
|
||||
} catch (Exception e) {
|
||||
Log.e("tag", "get error() ", e);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* vivo的适配文档中就告诉是27dp,未告知如何动态获取
|
||||
*/
|
||||
public static int getNotchHeight(Context context) {
|
||||
float density = getDensity(context);
|
||||
return (int) (27 * density);
|
||||
}
|
||||
|
||||
/**
|
||||
* vivo的适配文档中就告诉是100dp,未告知如何动态获取
|
||||
*/
|
||||
public static int getNotchWidth(Context context) {
|
||||
float density = getDensity(context);
|
||||
return (int) (100 * density);
|
||||
}
|
||||
|
||||
private static float getDensity(Context context) {
|
||||
return context.getResources().getDisplayMetrics().density;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNotch(Activity activity) {
|
||||
return isNotch();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setDisplayInNotch(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNotchRect(Activity activity, NotchSizeCallback callback) {
|
||||
ArrayList<Rect> rects = new ArrayList<>();
|
||||
Rect rect = ScreenUtil.calculateNotchRect(activity, getNotchWidth(activity), getNotchHeight(activity));
|
||||
rects.add(rect);
|
||||
callback.onResult(rects);
|
||||
}
|
||||
}
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
package com.bbgo.library_statusbar.utils;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
public final class RomUtils {
|
||||
|
||||
private static final String HUAWEI = "huawei";
|
||||
private static final String VIVO = "vivo";
|
||||
private static final String XIAOMI = "xiaomi";
|
||||
private static final String OPPO = "oppo";
|
||||
|
||||
private static final String VERSION_PROPERTY_HUAWEI = "ro.build.version.emui";
|
||||
private static final String VERSION_PROPERTY_VIVO = "ro.vivo.os.build.display.id";
|
||||
private static final String VERSION_PROPERTY_XIAOMI = "ro.build.version.incremental";
|
||||
private static final String VERSION_PROPERTY_OPPO = "ro.build.version.opporom";
|
||||
private static final String UNKNOWN = "unknown";
|
||||
|
||||
private static RomInfo bean = null;
|
||||
|
||||
private RomUtils() {
|
||||
throw new UnsupportedOperationException("u can't instantiate me...");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the rom is made by huawei.
|
||||
*
|
||||
* @return {@code true}: yes<br>{@code false}: no
|
||||
*/
|
||||
public static boolean isHuawei() {
|
||||
return HUAWEI.equals(getRomInfo().name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the rom is made by vivo.
|
||||
*
|
||||
* @return {@code true}: yes<br>{@code false}: no
|
||||
*/
|
||||
public static boolean isVivo() {
|
||||
return VIVO.equals(getRomInfo().name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the rom is made by xiaomi.
|
||||
*
|
||||
* @return {@code true}: yes<br>{@code false}: no
|
||||
*/
|
||||
public static boolean isXiaomi() {
|
||||
return XIAOMI.equals(getRomInfo().name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the rom is made by oppo.
|
||||
*
|
||||
* @return {@code true}: yes<br>{@code false}: no
|
||||
*/
|
||||
public static boolean isOppo() {
|
||||
return OPPO.equals(getRomInfo().name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the rom's information.
|
||||
*
|
||||
* @return the rom's information
|
||||
*/
|
||||
public static RomInfo getRomInfo() {
|
||||
if (bean != null) return bean;
|
||||
bean = new RomInfo();
|
||||
final String brand = getBrand();
|
||||
final String manufacturer = getManufacturer();
|
||||
if (isRightRom(brand, manufacturer, HUAWEI)) {
|
||||
bean.name = HUAWEI;
|
||||
String version = getRomVersion(VERSION_PROPERTY_HUAWEI);
|
||||
String[] temp = version.split("_");
|
||||
if (temp.length > 1) {
|
||||
bean.version = temp[1];
|
||||
} else {
|
||||
bean.version = version;
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
if (isRightRom(brand, manufacturer, VIVO)) {
|
||||
bean.name = VIVO;
|
||||
bean.version = getRomVersion(VERSION_PROPERTY_VIVO);
|
||||
return bean;
|
||||
}
|
||||
if (isRightRom(brand, manufacturer, XIAOMI)) {
|
||||
bean.name = XIAOMI;
|
||||
bean.version = getRomVersion(VERSION_PROPERTY_XIAOMI);
|
||||
return bean;
|
||||
}
|
||||
if (isRightRom(brand, manufacturer, OPPO)) {
|
||||
bean.name = OPPO;
|
||||
bean.version = getRomVersion(VERSION_PROPERTY_OPPO);
|
||||
return bean;
|
||||
} else {
|
||||
bean.name = manufacturer;
|
||||
}
|
||||
bean.version = getRomVersion("");
|
||||
return bean;
|
||||
}
|
||||
|
||||
private static boolean isRightRom(final String brand, final String manufacturer, final String... names) {
|
||||
for (String name : names) {
|
||||
if (brand.contains(name) || manufacturer.contains(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String getManufacturer() {
|
||||
try {
|
||||
String manufacturer = Build.MANUFACTURER;
|
||||
if (!TextUtils.isEmpty(manufacturer)) {
|
||||
return manufacturer.toLowerCase();
|
||||
}
|
||||
} catch (Throwable ignore) { /**/ }
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
private static String getBrand() {
|
||||
try {
|
||||
String brand = Build.BRAND;
|
||||
if (!TextUtils.isEmpty(brand)) {
|
||||
return brand.toLowerCase();
|
||||
}
|
||||
} catch (Throwable ignore) { /**/ }
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
private static String getRomVersion(final String propertyName) {
|
||||
String ret = "";
|
||||
if (!TextUtils.isEmpty(propertyName)) {
|
||||
ret = getSystemProperty(propertyName);
|
||||
}
|
||||
if (TextUtils.isEmpty(ret) || ret.equals(UNKNOWN)) {
|
||||
try {
|
||||
String display = Build.DISPLAY;
|
||||
if (!TextUtils.isEmpty(display)) {
|
||||
ret = display.toLowerCase();
|
||||
}
|
||||
} catch (Throwable ignore) { /**/ }
|
||||
}
|
||||
if (TextUtils.isEmpty(ret)) {
|
||||
return UNKNOWN;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static String getSystemProperty(final String name) {
|
||||
String prop = getSystemPropertyByShell(name);
|
||||
if (!TextUtils.isEmpty(prop)) return prop;
|
||||
prop = getSystemPropertyByStream(name);
|
||||
if (!TextUtils.isEmpty(prop)) return prop;
|
||||
if (Build.VERSION.SDK_INT < 28) {
|
||||
return getSystemPropertyByReflect(name);
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
|
||||
private static String getSystemPropertyByShell(final String propName) {
|
||||
String line;
|
||||
BufferedReader input = null;
|
||||
try {
|
||||
Process p = Runtime.getRuntime().exec("getprop " + propName);
|
||||
input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
|
||||
String ret = input.readLine();
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
} catch (IOException ignore) {
|
||||
} finally {
|
||||
if (input != null) {
|
||||
try {
|
||||
input.close();
|
||||
} catch (IOException ignore) { /**/ }
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String getSystemPropertyByStream(final String key) {
|
||||
try {
|
||||
Properties prop = new Properties();
|
||||
FileInputStream is = new FileInputStream(
|
||||
new File(Environment.getRootDirectory(), "build.prop")
|
||||
);
|
||||
prop.load(is);
|
||||
return prop.getProperty(key, "");
|
||||
} catch (Exception ignore) { /**/ }
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String getSystemPropertyByReflect(String key) {
|
||||
try {
|
||||
@SuppressLint("PrivateApi")
|
||||
Class<?> clz = Class.forName("android.os.SystemProperties");
|
||||
Method getMethod = clz.getMethod("get", String.class, String.class);
|
||||
return (String) getMethod.invoke(clz, key, "");
|
||||
} catch (Exception e) { /**/ }
|
||||
return "";
|
||||
}
|
||||
|
||||
public static class RomInfo {
|
||||
private String name;
|
||||
private String version;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RomInfo{name=" + name +
|
||||
", version=" + version + "}";
|
||||
}
|
||||
}
|
||||
}
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
package com.bbgo.library_statusbar.utils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.Display;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class ScreenUtil {
|
||||
|
||||
public static boolean isPortrait(Context context) {
|
||||
return context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取contentView的高度,建议在onWindowFocusChanged之后调用,否则高度为0
|
||||
*/
|
||||
public static int getContentViewHeight(Activity activity) {
|
||||
return getContentView(activity).getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取contentView的在屏幕上的展示区域,建议在onWindowFocusChanged之后调用
|
||||
*/
|
||||
public static Rect getContentViewDisplayFrame(Activity activity) {
|
||||
View contentView = getContentView(activity);
|
||||
Rect displayFrame = new Rect();
|
||||
contentView.getWindowVisibleDisplayFrame(displayFrame);
|
||||
return displayFrame;
|
||||
}
|
||||
|
||||
public static View getContentView(Activity activity) {
|
||||
return activity.getWindow().getDecorView().findViewById(android.R.id.content);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取navigationBar的高度
|
||||
*/
|
||||
public static int getNavigationBarHeight(Context context) {
|
||||
return getDimensionPixel(context, "navigation_bar_height");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取statusBar的高度
|
||||
*/
|
||||
public static int getStatusBarHeight(Context context) {
|
||||
return getDimensionPixel(context, "status_bar_height");
|
||||
}
|
||||
|
||||
|
||||
private static int getDimensionPixel(Context context, String navigation_bar_height) {
|
||||
int result = 0;
|
||||
Resources resources = context.getResources();
|
||||
int resourceId = resources.getIdentifier(navigation_bar_height, "dimen", "android");
|
||||
if (resourceId > 0) {
|
||||
result = resources.getDimensionPixelSize(resourceId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取屏幕宽高
|
||||
*/
|
||||
public static int[] getScreenSize(Context context) {
|
||||
int[] size = new int[2];
|
||||
WindowManager w = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
Display d = w.getDefaultDisplay();
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
d.getMetrics(metrics);
|
||||
int widthPixels = metrics.widthPixels;
|
||||
int heightPixels = metrics.heightPixels;
|
||||
if (Build.VERSION.SDK_INT >= 17)
|
||||
try {
|
||||
Point realSize = new Point();
|
||||
Display.class.getMethod("getRealSize", Point.class).invoke(d, realSize);
|
||||
widthPixels = realSize.x;
|
||||
heightPixels = realSize.y;
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
size[0] = widthPixels;
|
||||
size[1] = heightPixels;
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过宽高计算notch的Rect
|
||||
*
|
||||
* @param notchWidth 刘海的宽
|
||||
* @param notchHeight 刘海的高
|
||||
*/
|
||||
public static Rect calculateNotchRect(Context context, int notchWidth, int notchHeight) {
|
||||
int[] screenSize = getScreenSize(context);
|
||||
int screenWidth = screenSize[0];
|
||||
int screenHeight = screenSize[1];
|
||||
int left;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
if (isPortrait(context)) {
|
||||
left = (screenWidth - notchWidth) / 2;
|
||||
top = 0;
|
||||
right = left + notchWidth;
|
||||
bottom = notchHeight;
|
||||
} else {
|
||||
left = 0;
|
||||
top = (screenHeight - notchWidth) / 2;
|
||||
right = notchHeight;
|
||||
bottom = top + notchWidth;
|
||||
}
|
||||
return new Rect(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.bbgo.library_statusbar
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user