{"record":{"id":"83acb285ccebdd4c","repo":"didi/DoKit","slug":"can-t-check-permissions-for-null-context","errorCode":null,"errorMessage":"Can't check permissions for null context","messagePattern":"Can't check permissions for null context","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Android/dokit/src/main/java/com/didichuxing/doraemonkit/util/DoKitPermissionUtil.java","lineNumber":147,"sourceCode":"     *\n     * @param context\n     * @param perms\n     * @return\n     */\n    public static boolean hasPermissions(@NonNull Context context,\n                                         @Size(min = 1) @NonNull String... perms) {\n        // Always return true for SDK < M, let the system deal with the permissions\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {\n            Log.w(TAG, \"hasPermissions: API version < M, returning true by default\");\n\n            // DANGER ZONE!!! Changing this will break the library.\n            return true;\n        }\n\n        // Null context may be passed if we have detected Low API (less than M) so getting\n        // to this point with a null context should not be possible.\n        if (context == null) {\n            throw new IllegalArgumentException(\"Can't check permissions for null context\");\n        }\n\n        for (String perm : perms) {\n            if (ContextCompat.checkSelfPermission(context, perm)\n                    != PackageManager.PERMISSION_GRANTED) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * 检测是否有sd卡读写权限，不可靠。无sd卡或者磁盘满了的情况下，即使赋予了权限也可能报无权限\n     *\n     * @return\n     */\n    public static boolean checkStorageUnreliable() {","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/didi/DoKit/blob/626827cddb2feb2f3aee87a52a064b4e5ca2bed4/Android/dokit/src/main/java/com/didichuxing/doraemonkit/util/DoKitPermissionUtil.java#L129-L165","documentation":"DoKitPermissionUtil.hasPermissions(context, perms...) returns true unconditionally below API 23 (the OS handles install-time permissions), so a null Context can only reach the real check on M+ devices — where it throws IllegalArgumentException('Can't check permissions for null context') before calling ContextCompat.checkSelfPermission. The library treats a null context on M+ as a programming error, since permission state fundamentally cannot be queried without one.","triggerScenarios":"Calling DoKitPermissionUtil.hasPermissions(null, Manifest.permission.X) (or a wrapper that forwards a null Activity/Context) on a device running API 23+; a field-based context used before initialization; a detached fragment whose getActivity() returned null and was passed unchecked.","commonSituations":"Calling permission helpers from background services or broadcast receivers where a context was never captured; helper classes with a lazily-set application context that is null at first use; testing on old emulators (< M) masking the bug, then crashing on modern devices.","solutions":["Pass a non-null Context — ideally getApplicationContext() captured at init, or getActivity() guarded for null.","In fragments, guard: Context ctx = getContext(); if (ctx == null) return; before permission checks.","Initialize any context field in onCreate/attach before the first hasPermissions call.","Note the varargs must also be non-empty (@Size(min = 1)); pass at least one permission."],"exampleFix":"// before\nif (DoKitPermissionUtil.hasPermissions(null, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { ... }\n\n// after\nContext ctx = fragment.getContext();\nif (ctx != null && DoKitPermissionUtil.hasPermissions(ctx, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { ... }","handlingStrategy":"type-guard","validationCode":"if (context != null) {\n    boolean ok = DoKitPermissionUtil.hasPermissions(context, perms);\n} else {\n    // capture a context before permission checks\n}","typeGuard":"static boolean canCheckPermissions(Context ctx) {\n    return ctx != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;\n}","tryCatchPattern":"Not recommended — IllegalArgumentException marks a caller bug; supply a real Context instead of catching.","preventionTips":["Capture getApplicationContext() at module init and use it for permission checks.","Guard fragment calls with getContext() null-checks (detached fragments return null).","Remember the <M path returns true by default, so tests must include API 23+ devices."],"tags":["android","dokit","permissions","null-argument","runtime-permissions"],"backgroundTag":null,"analyzedSha":"626827cddb2feb2f3aee87a52a064b4e5ca2bed4","analyzedAt":"2026-08-14T12:45:58.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}