2012-03-23 47 views
9

有一個非公開API,我需要重寫,以便解決與Android的WebView怪癖。我可以重寫一個隱藏的(但是公共的)方法並調用它的超級方法嗎?

API是隱藏的,但它是公共的:

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

這樣我就可以通過簡單地在自己的WebView類聲明它覆蓋它,減去@Override:

public boolean selectText() { 
    ... 
} 

是否有可能從我的重寫調用超級方法?通常情況下,我可以寫:

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

但這種方法是隱藏的,所以super.selectText()不可用。如果我使用反射:

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

我得到一個無限循環,因爲它調用了我的重寫方法。

有無論如何重寫此方法並能夠調用超級方法嗎?

謝謝!

+0

沒有。 AFAIK這是不可能的。 – kosa 2012-03-23 18:07:11

+1

請參閱http://stackoverflow.com/questions/5411434/how-to-call-a-superclass-method-using-java-reflection和http://stackoverflow.com/questions/2100412/java-reflection-accessing-方法與默認修飾符在超級類和http://stackoverflow.com/questions/9771933/invoking-super-class-method-without-its-instance-using-reflection一些想法 – CommonsWare 2012-03-23 18:10:05

+0

是它是絕對有必要重寫該方法?爲什麼不調用你的方法'doSelectText()',然後使用反射來調用'selectText()'? – 2012-03-23 18:18:15

回答

1

實際上有兩種方法可以做到這一點,但他們有點勞動密集型,所以可能應該作爲最後的手段。使用紮根設備,您可以從設備上的框架瓶中提取符號,並將它們放入sdk/platforms /文件夾中的android.jar中。曾經有一個腳本來做到這一點;在轉換工作中失去了它。從內存

步驟(注意,你可能會遇到麻煩,因爲我不記得步驟......對於誰明白我想要知道的高級用戶):

  • ADB拉/ 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不是準確以我的經驗。

您現在可以針對這些符號進行編譯並且可以很好地訪問它們。儘管如果他們改變工作方式,不要生氣,他們沒有義務保持與第三方應用程序的兼容性。

這是有效的,因爲隱藏標記只在SDK編譯步驟中使用,並從位於sdk中的android.jar中刪除這些符號。如果我們收集編譯到設備上的所有符號並將它們粘貼到sdk jar中,就好像它們從未被剝離過。

或者,您可以下拉並構建完整的Android樹(https://source.android.com/source/building.html),然後針對完整源構建應用程序,第一步基本上是通過使用已編譯的符號並與它們一起工作來獲得。

0
  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. ?稱自己的執行還是回落到原來的?