May 14, 2010

關於android app的向下相容

今天要做一個multi-touch的功能。事實上android的multi-touch在2.0版本以後系統才有支援。所以說,在我的小N1上使用這些API當然是沒有問題的。然而,應該不會有人想做了一隻程式卻要限定2.0以上才可以使用吧,畢竟1.5/1.6的市占率還是不低呢(版本分佈參考這邊)。尤其又有某些廠商遲遲不願替手機升級... 殘念...

言歸正傳。程式寫好之後,若沒有限定minSDK版本的話,是可以安裝的。安裝的時候或者upload到market的時候並不會檢查裡面是不是有用到哪些不支援的API。像這樣的API錯誤,會在run time才出現。

幸運的是,很快就找到相關文章有寫到解法了。

所以說,如果希望寫出來的程式能夠向下相容,ex.在2.0以上可以具有multi-touch的功能,但在舊版的android也至少不要當掉。該如何做呢?

android的Dalvik VM使用delayed class loading的作法。也就是說,class會在要被使用到的時候才會load起來。如果class沒有被用到,那就不會load,也就不會讓VM complain有VerificationError了。

所以我們查查API,發現可以使用android.os.Build.VERSION.SDK_INT來作為OS版本的判別,於是很開心的用下去的結果,卻發現怎麼在1.5 Cupcake上還是照樣掛點...囧...。原來,這個SDK_INT從1.6 Dount之後才開始出現,還真是搞笑了... XD

再檢查一下,原來我們應該要用Build.VERSION.SDK去做check。這是跟SDK_INT完全一樣的數字,只不過是String的版本。所以說,我們的code可以這樣寫
public boolean onTouchEvent(MotionEvent event) {
boolean hasMultiTouch = Integer.parseInt(Build.VERSION.SDK) >= 5;
int nPointer = hasMultiTouch ? WrapNew.getPointerCount(event) : 1;
// ...
}

至於裡面的WrapNew的class則是我們自己implement的一個static class,用來把那些舊版SDK不存在的method包起來的一個class。類似底下這樣
class WrapNew {
static int getPointerCount(MotionEvent event) {
return event.getPointerCount();
}
}

這樣一來,就可以避免VM發生VerificationError了。

詳細請參閱引用來源。這篇文章真的寫的超棒的,淺顯易懂,英文又不難。雖然我有把主要重點的地方翻譯/寫出來了,還是相當值得一看。