产品的无脑需求,不按照google规范来搞,要在后台显示自定义Toast。
这可让我发愁呀~
![](https://i-blog.csdnimg.cn/blog_migrate/a41ec933f77d724fb4abec4423eac0eb.png)
硬着头皮搞需求呗~
联系framework同事,然后在拦截的地方加了白名单
不过他还好心提醒我是否需要限制次数,卧槽,还能这样,我想了下此次的需求不需求就拒绝了。
W NotificationService: Package com.xxx.xxx.xxx is above allowed toast quota, the following toast was blocked and discarded: CustomToastRecord{e28d3f8 18408:com.xxx.xxx.xxxx/u0a217 isSystemToast=false token=android.os.BinderProxy@d10533b callback=android.app.ITransientNotification$Stub$Proxy@1c800d1 duration=0}
本来以为有了framework同事的魔改万事大吉了,后来发现居然不能再settings里面弹出toast!
没办法,后来才知道,settings限制不安全的弹框出现,只好自己处理了
import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import android.view.WindowManager;
public class ToastUtil {
private static Toast toast = new Toast(myApplication.getInstance());
public static void showToast2(Context context, int drawableId) {
LayoutInflater inflater = (LayoutInflater) context.getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.xxxxxx, null);
ImageView imgContent = view.findViewById(R.id.imgContent);
imgContent.setImageResource(drawableId);
setToastParams(toast);
toast.setView(view);
toast.show();
}
public static void showToast1(Context context) {
LayoutInflater inflater = (LayoutInflater) context.getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.xxxxxx, null);
setToastParams(toast);
toast.setView(view);
toast.show();
}
private static void setToastParams(Toast toast) {
WindowManager.LayoutParams windowParams = getWindowParams(toast);
Field privateFlags = null;
Field privateFlagConstField = null;
try {
privateFlagConstField = WindowManager.LayoutParams.class.getDeclaredField("SYSTEM_FLAG_SHOW_FOR_ALL_USERS");
privateFlagConstField .setAccessible(true);
int privateFlagConst = privateFlagConstField.getInt(WindowManager.LayoutParams.class);
privateFlags = WindowManager.LayoutParams.class.getDeclaredField("privateFlags");
privateFlags.setAccessible(true);
int privateFlagsConst = privateFlags.getInt(WindowManager.LayoutParams.class);
privateFlagsConst |= privateFlagConst;
privateFlags.setInt(windowParams, privateFlagsConst);
setTrustedOverlay(windowParams);
} catch (Exception e) {
Log.e("xxx", "setToastParams err " + e);
}
}
private static WindowManager.LayoutParams getWindowParams(Toast toast){
try {
Method getWindowParams = toast.getClass().getMethod("getWindowParams");
if (getWindowParams == null) {
return null;
}
getWindowParams.setAccessible(true);
return (WindowManager.LayoutParams) getWindowParams.invoke(toast);
} catch (Exception e) {
Log.e("xxxxx", "getWindowParams err " + e);
return null;
}
}
private static void setTrustedOverlay(WindowManager.LayoutParams windowParams) {
try {
Method method = windowParams.getClass().getMethod("setTrustedOverlay");
if (method == null) {
return;
}
method.setAccessible(true);
method.invoke(windowParams);
} catch (Exception e) {
Log.e("xxxxx", "setTrustedOverlay err " + e);
return;
}
}
}
服务器编译apk,然后组合命令
adb root
adb remount
adb push xxxx
adb shell sync
adb reboot
重启测试搞定~
太难了~ 做手机除了要懂应用层,framework也要熟悉~
加油,加班狗。