1. 源碼版本適配
一般情況下來說,如果涉及到源碼反射,通常都需要適配各個版本,因此我們把與 so 修複相關的各大版本源碼都翻出來,具體的源碼細節,大家可以參考《Android 源碼分析實戰 - 動態加載修復 so 庫》
public void injectLoadPath(String soDir) throws Exception {
...
int version = Build.VERSION.SDK_INT;
if(version < Build.VERSION_CODES.M){
nativeLibraryPathElementsField = ReflectUtil.getFiled(pathList,"nativeLibraryDirectories");
}else if(version >= Build.VERSION_CODES.M){
nativeLibraryPathElementsField = ReflectUtil.getFiled(pathList, "nativeLibraryPathElements");
}
...
Object firstElement = null;
if(version < Build.VERSION_CODES.M){
firstElement = new File(soDir);
}else if(version >= Build.VERSION_CODES.M && version < Build.VERSION_CODES.O){
Constructor<?> elementConstructor = elementClass.getConstructor(File.class);
elementConstructor.setAccessible(true);
firstElement = elementConstructor.newInstance(new File(soDir));
}else if(version >= Build.VERSION_CODES.O){
Constructor<?> elementConstructor = elementClass.getConstructor(File.class, boolean.class, File.class, DexFile.class);
elementConstructor.setAccessible(true);
firstElement = elementConstructor.newInstance(new File(soDir),true, null, null);
}
...
}
寫出上面這樣的代碼,個人覺得應該差不多了。但我們平時寫代碼的時候,往往是想過要把代碼寫得更優雅,但就是感覺不知道該怎麼寫?因此我建議大家關於設計模式,一定要仔細學習理解但不要生搬硬套,學過之後要選擇性的忘記這些內容。我也曾聽同學說過,千萬不要學設計模式,設計模式會固化我們的思想,希望大家不要有這樣的錯覺。
2. AppCompatDelegate 源碼分析
我們可以先參考 Android 源碼,也就是看下 Google 工程師,是怎麼寫源碼適配代碼的
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
getDelegate().installViewFactory();
getDelegate().onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
}
public AppCompatDelegate getDelegate() {
if (mDelegate == null) {
mDelegate = AppCompatDelegate.create(this, this);
}
return mDelegate;
}
private static AppCompatDelegate create(Context context, Window window,
AppCompatCallback callback) {
final int sdk = Build.VERSION.SDK_INT;
if (sdk >= 23) {
return new AppCompatDelegateImplV23(context, window, callback);
} else if (sdk >= 14) {
return new AppCompatDelegateImplV14(context, window, callback);
} else if (sdk >= 11) {
return new AppCompatDelegateImplV11(context, window, callback);
} else {
return new AppCompatDelegateImplV7(context, window, callback);
}
}
3. 改造版本適配代碼
身經百戰後我們自然知道該怎麼寫,並不一定非得模仿系統源碼,就按照原來的代碼也行,這裏我只是舉一個例子。
public class SoHotFix {
private SoFix mSoFix;
public SoHotFix(Context context) {
Context applicationContext = context.getApplicationContext();
// 各大版本適配
final int sdk = Build.VERSION.SDK_INT;
if (sdk >= Build.VERSION_CODES.O) {
mSoFix = new SoFixImpV26(applicationContext);
} else if (sdk >= Build.VERSION_CODES.M) {
mSoFix = new SoFixImpV23(applicationContext);
} else {
mSoFix = new SoFixImpV20(applicationContext);
}
}
public void injectLoadPath(String soDir) throws Exception {
mSoFix.hotFix(soDir);
}
}
這是我們隨便挑的一個簡單的例子,只是想表達源碼其實是最好的學習資料,Linus Torvalds 曾說過 Read The Fucking Source Code。
視頻地址:https://pan.baidu.com/s/1COarOAlmOPCUlKsazho0Cw
視頻密碼:8lr0