{"record":{"id":"fd1f251211531840","repo":"Justson/AgentWeb","slug":"this-object-has-not-offer-method-javascript-to-cal","errorCode":null,"errorMessage":"This object has not offer method javascript to call ,please check addJavascriptInterface annotation was be added","messagePattern":"This object has not offer method javascript to call ,please check addJavascriptInterface annotation was be added","errorType":"exception","errorClass":"JsInterfaceObjectException","httpStatus":null,"severity":"error","filePath":"agentweb-core/src/main/java/com/just/agentweb/JsInterfaceHolderImpl.java","lineNumber":58,"sourceCode":"    JsInterfaceHolderImpl(WebCreator webCreator, AgentWeb.SecurityType securityType) {\n        super(webCreator, securityType);\n        this.mWebCreator = webCreator;\n        this.mWebView = mWebCreator.getWebView();\n        this.mSecurityType = securityType;\n    }\n\n    @Override\n    public JsInterfaceHolder addJavaObjects(Map<String, Object> maps) {\n        if (!checkSecurity()) {\n            LogUtils.e(TAG, \"The injected object is not safe, give up injection\");\n            return this;\n        }\n        Set<Map.Entry<String, Object>> sets = maps.entrySet();\n        for (Map.Entry<String, Object> mEntry : sets) {\n            Object v = mEntry.getValue();\n            boolean t = checkObject(v);\n            if (!t) {\n                throw new JsInterfaceObjectException(\"This object has not offer method javascript to call ,please check addJavascriptInterface annotation was be added\");\n            } else {\n                addJavaObjectDirect(mEntry.getKey(), v);\n            }\n        }\n        return this;\n    }\n\n    @Override\n    public JsInterfaceHolder addJavaObject(String k, Object v) {\n        if (!checkSecurity()) {\n            return this;\n        }\n        boolean t = checkObject(v);\n        if (!t) {\n            throw new JsInterfaceObjectException(\"this object has not offer method javascript to call , please check addJavascriptInterface annotation was be added\");\n        } else {\n            addJavaObjectDirect(k, v);\n        }","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/Justson/AgentWeb/blob/8f7f6adbf01010e9b2b44638f31edf10e1ba53f7/agentweb-core/src/main/java/com/just/agentweb/JsInterfaceHolderImpl.java#L40-L76","documentation":"JsInterfaceHolderImpl.addJavaObjects validates each object with checkObject(), which requires the class to expose methods annotated with @JavascriptInterface. An object with no such annotated methods is rejected with JsInterfaceObjectException because JavaScript would have nothing callable, a security/compatibility guard (especially needed on API 17+).","triggerScenarios":"Adding a plain POJO without any @JavascriptInterface-annotated public methods via addJavaObjects(map), or using methods with the old pre-17 @JavascriptInterface semantics/imports (wrong annotation package).","commonSituations":"Importing com.sun.javascript or a custom @JavascriptInterface instead of android.webkit.JavascriptInterface, annotating methods on a superclass but building against a SDK that strips annotations, or adding DTO/config objects by mistake.","solutions":["Annotate the public methods to expose with android.webkit.JavascriptInterface","Ensure the class passed actually declares annotated methods itself (not only inherited/proxied ones)","Check the import — it must be android.webkit.JavascriptInterface, not another annotation","Only register objects intended as JS bridges; remove unrelated objects from the map"],"exampleFix":"// before\nclass Bridge { public void go(){} } // no annotation -> throws\n// after\nclass Bridge {\n    @android.webkit.JavascriptInterface\n    public void go(){}\n}","handlingStrategy":"validation","validationCode":"boolean ok = false; for (Method m : obj.getClass().getMethods()) { if (m.isAnnotationPresent(JavascriptInterface.class)) { ok = true; break; } } if (!ok) return;","typeGuard":"boolean isJsBridge(Object o) { for (Method m : o.getClass().getMethods()) { if (m.isAnnotationPresent(android.webkit.JavascriptInterface.class)) return true; } return false; }","tryCatchPattern":"try { holder.addJavaObjects(map); } catch (JsInterfaceObjectException e) { Log.e(TAG, \"object lacks @JavascriptInterface methods\", e); }","preventionTips":["Annotate bridge methods with android.webkit.JavascriptInterface","Check annotation imports","Add ProGuard keep rules for @JavascriptInterface methods","Register only dedicated bridge classes"],"tags":["android","javascript-interface","annotation","js-bridge"],"backgroundTag":"invalid-argument-value","analyzedSha":"8f7f6adbf01010e9b2b44638f31edf10e1ba53f7","analyzedAt":"2026-09-11T10:05:24.337Z","contentChangedAt":"2026-09-11T10:05:24.337Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}