Blankj/AndroidUtilCode · error · Exception

u should impl these apis: " + noImplApis + "\n u can check i

Error message

u should impl these apis: " + noImplApis + "\n u can check it in file: " + jsonFile.toString()

What it means

After scanning, ApiPlugin collects all XxxApi subclasses of ApiUtils.BaseApi (mApiClasses) and all @ApiUtils.Api impls (apiImplMap). Any api class with no registered impl is added to noImplApis. If noImplApis is non-empty and ext.abortOnError is true (default), it throws Exception listing the unimplemented APIs and pointing at the generated __api__.json. This is a compile-time guarantee that no missing impl reaches runtime (where ApiUtils.getApi would otherwise return null and crash later).

Source

Thrown at plugin/api-gradle-plugin/src/main/java/com/blankj/api/ApiPlugin.groovy:105

                apiImplMap.each { key, value ->
                    implApis.put(key, value.toString())
                }
                apiClasses.each {
                    if (!apiImplMap.containsKey(it)) {
                        noImplApis.add(it)
                    }
                }
                Map apiDetails = [:]
                apiDetails.put("ApiUtilsClass", apiUtilsClass)
                apiDetails.put("implApis", implApis)
                apiDetails.put("noImplApis", noImplApis)
                String apiJson = JsonUtils.getFormatJson(apiDetails)
                log(jsonFile.toString() + ": " + apiJson)
                FileUtils.write(jsonFile, apiJson)

                if (noImplApis.size() > 0) {
                    if (ext.abortOnError) {
                        throw new Exception("u should impl these apis: " + noImplApis +
                                "\n u can check it in file: " + jsonFile.toString())
                    }
                }
                ApiInject.start(apiImplMap, apiUtilsTransformFile, apiUtilsClass)
            }
        } else {
            throw new Exception("No ApiUtils of ${apiUtilsClass} in $mProject.")
        }
    }
}

View on GitHub (pinned to 7b4caf9e54)

Solutions

  1. Add a class extending the unimplemented XxxApi, annotated @ApiUtils.Api (isMock = false), with a public no-arg constructor.
  2. If running a single module in isolation, provide a @ApiUtils.Api(isMock = true) mock impl so the api is satisfied.
  3. If the real impl exists but is skipped, broaden onlyScanLibRegex / remove jumpScanLibRegex so the impl's jar/module is scanned.
  4. Temporarily set abortOnError = false to let the build proceed (the api will return null at runtime, so use this only for diagnostics).

Example fix

// before - MainApi declared but never implemented -> "u should impl these apis"
public abstract class MainApi extends ApiUtils.BaseApi {
    public abstract MainResult startMainActivity(Context ctx, MainParam p);
}

// after - add a real impl (or a mock for isolated builds)
@ApiUtils.Api
public class MainApiImpl extends MainApi {
    public MainApiImpl() {}   // public no-arg constructor required
    @Override
    public MainResult startMainActivity(Context ctx, MainParam p) {
        MainActivity.start(ctx, p);
        return new MainResult("ok");
    }
}
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Declaring `abstract class XxxApi extends ApiUtils.BaseApi` with no class annotated @ApiUtils.Api extending it; the real impl lives in a module excluded from the scan (onlyScanLibRegex/jumpScanLibRegex) or not compiled into the current variant; the impl is annotated with a wrong @Api whose descriptor does not match.

Common situations: An api is declared in an export module but its impl lives in a feature/pkg module not included in the current single-module debug build; impl class forgotten or not annotated; annotation import points to a different @Api.

Related errors


AI-assisted analysis of Blankj/AndroidUtilCode@7b4caf9e54 (2026-08-14). Data as JSON: /api/errors/44c49514f9e386c3. Report an issue: GitHub.