Android关闭通知不能吐司问题

Toast使用了INotificationManager类,和通知栏有关,如果关闭了通知权限,则Toast不能弹出,如三星、华为等手机在关闭通知栏的情况下就不能使用吐司了。当然国内厂商很多,总会有厂商来自己处理这个东西,比如小米,小米在关闭通知的情况下还可以弹出吐司。

不能强迫用户打开通知,一些很重要的情况下必须要告知用户一些信息,如付款失败、订单创建失败,这种时候我们就让机把吐司吐出来。实现原理就是冒充系统消息,使用系统吐司。

实现思路是APP调用NotificationManager弹出吐司,就需要给Manager传一个包名,manager获取到该APP包名后先判断该APP是否有通知权限,如果没有则终止,不弹出吐司,有则弹出。我们想在APP没有通知权限下也能弹出吐司就要给manager传“android”,这是使用系统Toast意思,毕竟系统的不会被禁。

1.首先判断当前通知权限是否可用

private static boolean isNotificationEnabled(Context context) {
        NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context);
        boolean areNotificationsEnabled = notificationManagerCompat.areNotificationsEnabled();
        return areNotificationsEnabled;
    }

2.如果当前通知权限没被禁,那就直接show就行,如果被禁就使用系统吐司

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 Objectinvoke(Object proxy, Method method, Object[] args)throws Throwable {

//强制使用系统Toast

                    if ("enqueueToast".equals(method.getName())

||"enqueueToastEx".equals(method.getName())//华为p20 pro上为enqueueToastEx

                            ||"enqueueToastLog".equals(method.getName())) {//三星s10 enqueueToastLog

                        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();

    }

}

method.getName() 的判断需要注意,这里是根据手机来区分的,如果使用的手机获取到的方法名不在这里面就需要自己添加(测试比较麻烦,需要对单独手机进行测试,比如我用的是三星s10,s9可能就不是这个值就需要新增)

你可能感兴趣的:(Android关闭通知不能吐司问题)