熱更新Tinker研究(一):運作tinker-sample-android
熱更新Tinker研究(二):結合源碼學習Dex格式
熱更新Tinker研究(三):加載更新檔
熱更新Tinker研究(四):TinkerLoader
熱更新Tinker研究(五):Application的隔離
熱更新Tinker研究(六):TinkerPatchPlugin
熱更新Tinker研究(七):Dex的patch檔案生成
熱更新Tinker研究(八):res和so的patch檔案生成
熱更新Tinker研究(九):Dex檔案的patch
熱更新Tinker研究(十):Res檔案的patch
熱更新Tinker研究(十一):so檔案的patch
熱更新Tinker研究(十一):so檔案的patch
一、重要檔案說明
1,關于so_meta.txt
相鄰元素用‘,’分隔,不同的item用行分隔。
示例如下:
libHelloJNI.so,lib/x86,bee6a211b80de30bd20a3c84f10c606,,b9e5ecfe8ee8ad0f4cd72bce783e662
libHelloJNI.so,lib/armeabi-v7a,bfa1eeb03f9b5d0c8bfa46b30384b436,,e8dcb4455b0b3395a29599f10def7ccc
libHelloJNI.so,lib/armeabi,f7065d883f7e9687967164e08f1913a,,a7492ed0923f006537797d8df547d60
具體如下面的表格
name | path | md5 | rawCrc | patchMd5 |
---|---|---|---|---|
libHelloJNI.so | lib/x86 | 8bee6a211b80de30bd20a3c84f10c606 | 1094172186 | 2b9e5ecfe8ee8ad0f4cd72bce783e662 |
libHelloJNI.so | lib/armeabi-v7a | bfa1eeb03f9b5d0c8bfa46b30384b436 | 2738641823 | e8dcb4455b0b3395a29599f10def7ccc |
libHelloJNI.so | lib/armeabi | 6f7065d883f7e9687967164e08f1913a | 3024247562 | 6a7492ed0923f006537797d8df547d60 |
name表示so檔案的名稱,path表示路徑,md5是新生成so檔案的校驗值,rawCrc是baskApk的crc,patchMd5是patch.so對應的md5值。
2,patch.so的格式
magic為辨別,這裡沒有進行特殊的校驗。ctrlBlockLen為第二個區域控制區域的長度,diffBlockLen為diffBlockData的長度,extraBlockLen為extraBlockData的長度。ctrl[]的三個值依次代表diffBlockData區域需要讀取的長度,extraBlockData區域需要讀取的長度以及oldPos的偏移量。
二、BSPatch中的patch
這裡根據newPos循環來控制patch的過程,
// byte[] newBuf = new byte[newsize + 1];
byte[] newBuf = new byte[newsize];
int oldpos = ;
int newpos = ;
int[] ctrl = new int[]; //控制數組
// int nbytes;
while (newpos < newsize) {
for (int i = ; i <= ; i++) {
ctrl[i] = ctrlBlockIn.readInt();
}
// ctrl[0]
if (newpos + ctrl[] > newsize) {
throw new IOException("Corrupt by wrong patch file.");
}
// Read ctrl[0] bytes from diffBlock stream
if (!BSUtil.readFromStream(diffBlockIn, newBuf, newpos, ctrl[])) {
throw new IOException("Corrupt by wrong patch file.");
}
for (int i = ; i < ctrl[]; i++) {
if ((oldpos + i >= ) && (oldpos + i < oldsize)) {
newBuf[newpos + i] += oldBuf[oldpos + i];
}
}
newpos += ctrl[];
oldpos += ctrl[];
if (newpos + ctrl[] > newsize) {
throw new IOException("Corrupt by wrong patch file.");
}
if (!BSUtil.readFromStream(extraBlockIn, newBuf, newpos, ctrl[])) {
throw new IOException("Corrupt by wrong patch file.");
}
newpos += ctrl[];
oldpos += ctrl[];
}
ctrlBlockIn.close();
diffBlockIn.close();
extraBlockIn.close();
return newBuf;
首先是讀取ctrl[]數組,然後從diffBuf中讀取ctrl[0]長度的資料到newBuf,再加上oldBuf中對應位置的資料,得到藍色區域。後面再是從extraBuf中讀取長度為ctrl1的資料,最後再将oldPos偏移ctrl2,重複上面的循環。最終得到新的so檔案。