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
- Add a class extending the unimplemented XxxApi, annotated @ApiUtils.Api (isMock = false), with a public no-arg constructor.
- If running a single module in isolation, provide a @ApiUtils.Api(isMock = true) mock impl so the api is satisfied.
- If the real impl exists but is skipped, broaden onlyScanLibRegex / remove jumpScanLibRegex so the impl's jar/module is scanned.
- 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
- Every class extending ApiUtils.BaseApi must have exactly one @ApiUtils.Api impl in the app build.
- For isolated/single-module runs, ship a @ApiUtils.Api(isMock = true) impl in the mock source set.
- Confirm impl classes are in scanned jars/modules (mind onlyScanLibRegex/jumpScanLibRegex).
- Inspect the generated __api__.json after each build to catch noImplApis early.
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
- <" + className + "> and <" + apiInfo.implApiClass + "> impl
- No ApiUtils of ${apiUtilsClass} in $mProject.
- ApiExtension's apiUtilsClass is empty.
- These buses is not right: " + wrongBus + "\n u can check it
- No BusUtils of ${ext.busUtilsClass} in $mProject.
AI-assisted analysis of Blankj/AndroidUtilCode@7b4caf9e54 (2026-08-14).
Data as JSON: /api/errors/44c49514f9e386c3.
Report an issue: GitHub.