解决通知关闭Toast失效问题

1 篇文章 0 订阅
1 篇文章 0 订阅

下图是系统INotificationManager的实现源码 当pkg = “android”时不会校验通知关闭逻辑
所以只需要hook INotificationManager 将参数pkg始终传“android” 就行了 


实现代码: 

/**
 * Created by linjinfa on 2018/2/5.
 * email 331710168@qq.com
 */
public class ToastUtil {

    private static Object iNotificationManagerObj;

    /**
     * @param context
     * @param message
     */
    public static void show(Context context, String message) {
        show(context, message, Toast.LENGTH_SHORT, Gravity.BOTTOM);
    }

    /**
     *
     * @param context
     * @param message
     */
    public static void showCenter(Context context, String message) {
        show(context, message, Toast.LENGTH_SHORT, Gravity.CENTER);
    }

    /**
     * @param context
     * @param message
     */
    public static void show(Context context, String message, int duration, int gravity) {
        if (TextUtils.isEmpty(message)) {
            return;
        }
        //后setText 兼容小米默认会显示app名称的问题
        Toast toast = Toast.makeText(context, null, duration);
        toast.setText(message);
        toast.setGravity(gravity, 0, 0);
        if(isNotificationEnabled(context)){
            toast.show();
        }else{
            showSystemToast(toast);
        }
    }

    /**
     * 业务相关的toast
     * @param context
     * @param message
     */
    public static void showCenterForBusiness(final Context context, final String message) {
        if (context != null) {
            if (context instanceof Activity) {
                ((Activity) context).runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        show(context, message, Toast.LENGTH_SHORT, Gravity.CENTER);
                    }
                });
            } else {
                show(context, message, Toast.LENGTH_SHORT, Gravity.CENTER);
            }
        }
    }

    /**
     * 显示系统Toast
     */
    private static void showSystemToast(Toast toast){
        try{
            Method getServiceMethod = Toast.class.getDeclaredMethod("getService");
            getServiceMethod.setAccessible(true);
            //hook INotificationManager
            if(iNotificationManagerObj == null){
                iNotificationManagerObj = getServiceMethod.invoke(null);

                Class iNotificationManagerCls = Class.forName("android.app.INotificationManager");
                Object iNotificationManagerProxy = Proxy.newProxyInstance(toast.getClass().getClassLoader(), new Class[]{iNotificationManagerCls}, new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //强制使用系统Toast
                        if("enqueueToast".equals(method.getName())
                                || "enqueueToastEx".equals(method.getName())){  //华为p20 pro上为enqueueToastEx
                            args[0] = "android";
                        }
                        return method.invoke(iNotificationManagerObj, args);
                    }
                });
                Field sServiceFiled = Toast.class.getDeclaredField("sService");
                sServiceFiled.setAccessible(true);
                sServiceFiled.set(null, iNotificationManagerProxy);
            }
            toast.show();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 消息通知是否开启
     * @return
     */
    private static boolean isNotificationEnabled(Context context) {
        NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context);
        boolean areNotificationsEnabled = notificationManagerCompat.areNotificationsEnabled();
        return areNotificationsEnabled;
    }

}
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值