前言
代码环境为Android8.1
再Android设备有多块屏幕时,在副屏上的进程显示toast的时候会发现toast显示在了主屏上,下面的修改过后,toast可以显示在正确的屏幕上.
Toast的修改
构造的时候拿到传入的context并保存
public Toast(@NonNull Context context, @Nullable Looper looper) {
....................
mTN.tnContext = context;
}
........................
static class TN extends ITransientNotification.Stub {
Context tnContext = null;
.......................
之后,在toast的handleShow()中获取WindowManager的时候使用之前保存的context
public void handleShow(IBinder windowToken) {
......................
if (tnContext != null) {
if (DEBUG_TOAST) Log.d(TAG, "It is com.hht.backrow.vehicle, using the right context.");
mWM = (WindowManager)tnContext.getSystemService(Context.WINDOW_SERVICE);
} else {
mWM = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
}
......................
这样修改之后,发Toast的时候会在WMS的addWindow的时候返回异常结果,之后会抛出异常,无法显示Toast所以这里还需要在WMS中修改一下
WMS
private boolean doesAddToastWindowRequireToken(String packageName, int callingUid,
WindowState attachedWindow) {
if (("com.xxx.xxx").equals(packageName)) {
if (DEBUG_TOAST) Slog.d(TAG, "It is " + packageName + ", allow it to show toast without token.");
return false;
}
这里可以把副屏使用的应用的包名加一个判断直接放过去不在addwindow中返回异常结果,或者不加包名判断直接全部无脑方过去.这个方法是在Android7.1中加入的,之前没有这个判断.