关闭通知权限后,Toast在华为等手机不显示问题

关闭通知权限后,Toast在华为等手机不显示
这个涉及到Toast源码问题
我们可以判断是否有通知权限
如果有就正常走Toast弹框
如果没有就通过反射,强制Toast弹框

/**
* 检查通知栏权限有没有开启
*/
public static boolean isNotificationEnabled(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
NotificationManager manager = ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE));
if (manager != null) {
return manager.areNotificationsEnabled();
} else {
return false;
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
ApplicationInfo appInfo = context.getApplicationInfo();
String pkg = context.getApplicationContext().getPackageName();
int uid = appInfo.uid;

        try {
            Class appOpsClass = Class.forName(AppOpsManager.class.getName());
            Method checkOpNoThrowMethod = appOpsClass.getMethod("checkOpNoThrow", Integer.TYPE, Integer.TYPE, String.class);
            Field opPostNotificationValue = appOpsClass.getDeclaredField("OP_POST_NOTIFICATION");
            int value = (Integer) opPostNotificationValue.get(Integer.class);
            return (Integer) checkOpNoThrowMethod.invoke(appOps, value, uid, pkg) == 0;
        } catch (NoSuchMethodException | NoSuchFieldException | InvocationTargetException | IllegalAccessException | RuntimeException | ClassNotFoundException ignored) {
            return true;
        }
    } else {
        return true;
    }
}

/**
* 强制显示系统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();
    }
}

/**
* Toast弹框
*/
public void show(final Context context, final String info){

    Toast toast = Toast.makeText(context, info, Toast.LENGTH_SHORT);

   //如果没有通知权限 就强制Toast弹框
    if (!isNotificationEnabled(context)) {
        showSystemToast(toast);
        return;
    }

    //下面走正常弹框
    ......

}

你可能感兴趣的:(关闭通知权限后,Toast在华为等手机不显示问题)