繁体   English   中英

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

[英]Can I override a hidden (but public) method and call its super method?

我需要覆盖一个非公共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);
}

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

反正有没有覆盖这个方法,并能够调用超级方法?

谢谢!

反正有没有覆盖这个方法,并能够调用超级方法?

不幸的是,正如在如何使用Java反射调用超类方法的问题的答案中解释的那样,您无法通过反射解决此问题。

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

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

  • adb pull / system / framework / *(这些都是jar文件)。 获得framework.jar可能就足够了。 解压缩它们。
  • 对于每一个,我相信会给你一个classes.dex和一个清单。 如果您只是获取类文件,请跳过下一步
  • dex2jar classes.dex和unjar 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 ),然后针对完整的源代码构建你的应用程序,这第一步基本上是通过已经编译完成的符号并与他们合作。

  1. 是的你可以:) - 问题的第一部分
  2. 不,你不能 - 第二个

解决方案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. 根据一些条件? 调用自己的实现还是回归原来的?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM