Android 判断应用是否处于非全屏模式
对于常见大多数安卓应用判断分屏的方法是使用isInMultiWindowMode()方法来判断是否是处于全屏状态,当这种方法有一种特殊途径会失效,我们先介绍isInMultiWindowMode()方法。在使用另外一种,通过android.app.WindowConfiguration–>getWindowingMode 通过反射的方法调用到这个。
isInMultiWindowMode() 方法判断分屏
1.使用 Activity
类的 isInMultiWindowMode()
方法来检查当前活动是否在分屏模式下。例如:
javaCopy codeif (isInMultiWindowMode()) {
// 在分屏模式下执行的代码
} else {
// 不在分屏模式下执行的代码
}
2.如果你需要在应用的其他组件(如 Fragment
、Service
等)中检查分屏模式,你可以使用 WindowManager
来获取当前设备的配置信息,并检查 Configuration
中的 isInMultiWindowMode()
方法。例如:
javaCopy codeWindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
if (windowManager != null) {
Configuration configuration = getResources().getConfiguration();
if (configuration != null && configuration.isInMultiWindowMode()) {
// 在分屏模式下执行的代码
} else {
// 不在分屏模式下执行的代码
}
}
这两种方法都可以让你检查应用当前是否处于分屏模式,从而进行相应的操作。
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.WindowManager;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
// 检查当前是否处于分屏模式
checkMultiWindowMode();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// 当配置改变时重新检查分屏模式
checkMultiWindowMode();
}
private void checkMultiWindowMode() {
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
if (windowManager != null) {
Configuration configuration = getResources().getConfiguration();
if (configuration != null && configuration.isInMultiWindowMode()) {
// 在分屏模式下显示特定布局
setContentView(R.layout.activity_main_multi_window);
TextView textView = findViewById(R.id.textView);
textView.setText("当前处于分屏模式");
} else {
// 不在分屏模式下显示默认布局
setContentView(R.layout.activity_main);
}
}
}
}
上面简单的使用了isInMultiWindowMode方法来判断应用是否处于分屏状态。
getWindowingMode方法
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// 当配置改变时重新检查分屏模式
checkWindowingMode(newConfig);
}
/**
* get the status whether app is shown in full screen or multi windows.
* @param configuration , from activity onConfigurationChanged
* */
@SuppressLint("PrivateApi")
public static void checkWindowingMode(Configuration configuration) {
try {
@SuppressLint("BlockedPrivateApi")
Field field = configuration.getClass().getDeclaredField("windowConfiguration");
field.setAccessible(true);
Class<?> clazz = Class.forName("android.app.WindowConfiguration");
Method method = clazz.getDeclaredMethod("getWindowingMode", null);
method.setAccessible(true);
int windowingMode = (int) (method.invoke(field.get(configuration)));
isFullScreen = windowingMode == WINDOWING_MODE_FULL_SCREEN;
Log.d(TAG,"windowingMode = "+windowingMode + "isFullScreen "+isFullScreen);
} catch (Exception e) {
e.printStackTrace();
isFullScreen = true;
}
}
@SuppressLint("PrivateApi")
是 Android 中的一个注解,用于告诉编译器忽略特定类型的 lint 错误或警告。
使用了私有 API,lint 可能会警告你。你可以在方法前面添加 @SuppressLint("PrivateApi")
注解来消除这个警告。
@SuppressLint("BlockedPrivateApi")
Field field = configuration.getClass().getDeclaredField("windowConfiguration");
field.setAccessible(true);
使用了反射来获取 windowConfiguration
字段,这个字段可能是一个被标记为私有的 API,因此 lint 可能会对此发出警告。
通过在代码中添加 @SuppressLint("BlockedPrivateApi")
注解,你告诉 lint 忽略这个警告,使得你的代码可以编译通过。
method.setAccessible(true)
是 Java 中反射 API 中的一个方法调用,用于设置方法的可访问性。通过调用 setAccessible(true)
方法,你可以取消对方法的访问限制,使得即使这个方法是私有的或者不可访问的,你也可以在运行时调用它。
int windowingMode = (int) (method.invoke(field.get(configuration)));
field.get(configuration)
:首先通过反射获取了名为 “windowConfiguration” 的字段所对应的值,这个值是configuration
对象中的一个字段的值。method.invoke(field.get(configuration))
:然后调用了method
对象所代表的方法,并传入了上一步获取到的值作为方法调用的对象。这样就相当于在获取到的对象上调用了相应的方法。
我们看一下WindowConfiguration的源码,https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/WindowConfiguration.java
/** Windowing mode is currently not defined. */
public static final int WINDOWING_MODE_UNDEFINED = 0;
/** Occupies the full area of the screen or the parent container. */
public static final int WINDOWING_MODE_FULLSCREEN = 1;
/** Always on-top (always visible). of other siblings in its parent container. */
public static final int WINDOWING_MODE_PINNED = 2;
/** Can be freely resized within its parent container. */
// TODO: Remove once freeform is migrated to wm-shell.
public static final int WINDOWING_MODE_FREEFORM = 5;
/** Generic multi-window with no presentation attribution from the window manager. */
public static final int WINDOWING_MODE_MULTI_WINDOW = 6;
/** @hide */
@IntDef(prefix = { "WINDOWING_MODE_" }, value = {
WINDOWING_MODE_UNDEFINED,
WINDOWING_MODE_FULLSCREEN,
WINDOWING_MODE_MULTI_WINDOW,
WINDOWING_MODE_PINNED,
WINDOWING_MODE_FREEFORM,
})
public void setWindowingMode(@WindowingMode int windowingMode) {
mWindowingMode = windowingMode;
}
@WindowingMode
public int getWindowingMode() {
return mWindowingMode;
}
NAME | VALE | explain |
---|---|---|
WINDOWING_MODE_UNDEFINED | 0 | 处理未定义的窗口模式 |
WINDOWING_MODE_FULLSCREEN | 1 | 处理全屏窗口模式 |
WINDOWING_MODE_PINNED | 2 | 处理固定窗口模式 |
WINDOWING_MODE_FREEFORM | 5 | 处理自由窗口模式 |
WINDOWING_MODE_MULTI_WINDOW | 6 | 处理多窗口模式 |
通过反射的方式可以拿到全部的窗口模式,通过返回值判断当前是否处于FullScreen状态。