我可以覆盖隐藏(但公共)方法并调用其超级方法吗?

时间:2012-03-23 18:04:41

标签: java android reflection override

我需要覆盖非公开API,以便使用Android的WebView解决问题。

api是隐藏的,但它是公开的:

/**
 * ...
 *
 * @hide pending API council approval
 */
public boolean selectText() {
    ...
}

所以我可以通过简单地在我自己的WebView类中声明它来覆盖它,减去@Override:

public boolean selectText() {
    ...
}

是否可以从我的覆盖中调用super方法?通常我可以写:

public boolean selectText() {
    return super.selectText();
}

但该方法已隐藏,因此super.selectText()不可用。如果我使用反射:

public boolean selectText() {
    return (Boolean) WebView.class.getMethod("selectText").invoke(this, (Object[]) null);
}

我得到一个无限循环因为它调用了我的重写方法。

是否有覆盖此方法并且能够调用超级方法?

谢谢!

3 个答案:

答案 0 :(得分:4)

  

无论如何都要覆盖此方法并且能够调用超级   方法

不,不幸的是,正如问题How to call a superclass method using Java reflection的答案所解释的那样,你无法通过反思来解决这个问题。

答案 1 :(得分:1)

实际上有几种方法可以做到这一点,但它们需要一点劳动密集型,所以可能应该作为最后的手段使用。使用root设备,您可以从设备上的框架jar中提取符号,并将它们放入sdk / platforms /文件夹中的android.jar中。曾经有一个脚本来做这件事;在转换工作时失去了它。

记忆中的步骤(请注意,您可能会遇到麻烦,因为我不记得这些步骤......对于了解我想要了解的内容的高级用户而言:

  • adb pull / system / framework / *(这些都是jar文件)。有可能 足以获得framework.jar。拉开它们。
  • 我认为每个人都会给你一个classes.dex和一个清单。如果 你只需要获取类文件,跳过下一步
  • dex2jar classes.dex并解开classes_dex2jar.jar或者其他任何内容 输出来自dex2jar,它将为您提供一堆.class文件
  • 获取类文件并将它们添加到你的android sdk android.jar中 文件(sdk / platforms / android- #sdk#/ android.jar)。

我建议将android-#sdk#文件夹复制到android-1#sdk#文件夹中,这样android-19就会变成android-119,然后在文件夹中更改build.prop来说ro.build.version.sdk = 119,然后建立对抗sdk 119.这样你可以选择建立一个干净的119或你的黑客119.只是不要参考任何com.android.internal.R文件,因为这些ID不准确根据我的经验。

您现在可以针对这些符号进行编译并正确访问它们。虽然如果他们改变工作方式并不会生气,他们也没有义务保持与第三方应用程序的兼容性。

这是有效的,因为hide标记仅在SDK编译步骤中使用,并从位于sdk中的android.jar中删除这些符号。如果我们收集所有编译到设备上的符号并将它们粘贴到你的sdk jar中,就好像它们从未被剥离过一样。

或者你可以下拉并构建完整的android树(https://source.android.com/source/building.html),然后针对完整的源代码构建你的应用程序,第一步主要是通过获取已编译的符号并使用它们来解决。 / p>

答案 2 :(得分:0)

  1. 是的你可以:) - 问题的第一部分
  2. 不,你不能 - 第二个
  3. 解决方案1) - 最接近您想要达到的目标

    // to override method 
    // which IDE doesn't see - those that contains {@ hide} text in JavaDoc
    // simple create method with same signature
    // but remove annotation
    // as we don't know if method will be present or not in super class 
    //
    //@Override      
    public boolean callMethod(String arg) {
    
        //  can we do it ?
        // boolean result = super.callMethod(arg)
        // no  why ? 
        // You may think you could perhaps
        // use reflection and call specific superclass method 
        // on a subclass instance.
    
    
    /** 
     * If the underlying method is an instance method, it is 
     * invoked using dynamic method lookup as documented in The 
     * Java Language Specification, Second Edition, section 
     * 15.12.4.4; in particular, overriding based on the runtime
     * type of the target object will occur.
     */
    
    
       // but always you can see what super class is doing in its method 
       // and do the same by forward call in this method to newly created one
       // return modified  result 
      return doSomthingWhatSuperDo()
    }
    

    解决方案2)

    对象(调用此方法)是否属于您?并实现接口?

    如果是这样代理怎么样?

    1. 扩展课程
    2. 创建代理
    3. 使用代理
    4. 拦截方法调用
    5. 基于某些条件?调用自己的实现还是回归原来的?