Android Studio是如何实现AddJavascriptInterface提示的

效果图

源码是AddJavascriptInterfaceDetector.java

接下来我们来看看是如何实现的

Detector.JavaPsiScanner

  • 用于实现java源码检测的接口
  • 取代了之前的Detector.JavaScanner
   private static final String WEB_VIEW = "android.webkit.WebView";
    private static final String ADD_JAVASCRIPT_INTERFACE = "addJavascriptInterface";

    // ---- Implements JavaScanner ----

    @Nullable
    @Override
    public List<String> getApplicableMethodNames() {
        return Collections.singletonList(ADD_JAVASCRIPT_INTERFACE);
    }

    @Override
    public void visitMethod(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor,
            @NonNull PsiMethodCallExpression node, @NonNull PsiMethod method) {
        // Ignore the issue if we never build for any API less than 17.
        if (context.getMainProject().getMinSdk() >= 17) {
            return;
        }

        JavaEvaluator evaluator = context.getEvaluator();
        if (!evaluator.methodMatches(method, WEB_VIEW, true, TYPE_OBJECT, TYPE_STRING)) {
            return;
        }

        String message = "`WebView.addJavascriptInterface` should not be called with minSdkVersion < 17 for security reasons: " +
                "JavaScript can use reflection to manipulate application";
        context.report(ISSUE, node, context.getNameLocation(node), message);
    }

核心代码

  • getApplicableMethodNames()

这个方法用来返回你感兴趣的那些方法调用列表,所以这里设置
的是字符addJavascriptInterface,此方法配合以下方法使用

  • visitMethod(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor, @NonNull PsiMethodCallExpression node, @NonNull PsiMethod method)

addJavascriptInterface被调用时,会触发此方法。
JavaContext 上下文

需要注意的一些方法

  • 获取项目信息
    Project project = context.getMainProject();

  • 获取项目build.gradle中配置的minSdkVersion
    int minSdk= project.getMinSdk();
    以上判断如果minSDK大于17则不显示提示

  • JavaEvaluator
    求值类
    JavaEvaluator evaluator = context.getEvaluator();

接下来判断调用addJavascriptInterface的对象是不是Android系统提供的WebView

public boolean methodMatches(PsiMethod method,String className, boolean allowInherit,String... argumentTypes)

method
visitMethod中的method

className
addJavascriptInterface的类名如android.webkit.WebView

allowInherit
是否支持指定类的子类校验,比如WebView的子类

argumentTypes
指定方法中参数的类型
public void addJavascriptInterface(Object object, String name)
所以上面第一个参数为TYPE_OBJECT和TYPE_STRING

创建提示类Issue

Issue类提供了工厂方法创建issue
public static Issue create(String id,String briefDescription,String
explanation,Category category,int priority, Severity
severity,Implementation implementation)

  • id Issue的自定义名字,如: AddJavascriptInterfaceLogUtilsNotUsed

  • briefDescription ,explanation.描述性(不解释)

  • category 类型 如Category.USABILITY

  • priority 优先级(1-10)

  • severity 安全级别(Severity.ERROR报错)

  • implementation Issue的实现类,如 new Implementation( AddJavascriptInterfaceDetector.class, Scope.JAVA_FILE_SCOPE)),第一个参数为类名。

发送报告

Context(子类JavaContext,ClassContext)
public void report(Issue issue,Location location,String message)

  • issue 用Issue.create创建的类
  • location位置 context.getNameLocation(node)
  • message 提示消息
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容