天天看點

熱更新Tinker研究(十一):so檔案的patch熱更新Tinker研究(十一):so檔案的patch

熱更新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的格式

熱更新Tinker研究(十一):so檔案的patch熱更新Tinker研究(十一):so檔案的patch

magic為辨別,這裡沒有進行特殊的校驗。ctrlBlockLen為第二個區域控制區域的長度,diffBlockLen為diffBlockData的長度,extraBlockLen為extraBlockData的長度。ctrl[]的三個值依次代表diffBlockData區域需要讀取的長度,extraBlockData區域需要讀取的長度以及oldPos的偏移量。

二、BSPatch中的patch

熱更新Tinker研究(十一):so檔案的patch熱更新Tinker研究(十一):so檔案的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檔案。