使用AndFix進行Hot fix


AndFix簡介

AndFix是一個Android App的在線熱補丁框架。使用此框架,我們能夠在不重複發版的情況下,在線修改App中的Bug。AndFix就是 “Android Hot-Fix”的縮寫。

AndFix Github地址

就目前來說,AndFix支持Android 2.3到6.0版本,並且支持arm 與 X86系統架構的設備。完美支持Dalvik與ART的Runtime。

AndFix 的補丁文件是以 .apatch 結尾的文件。

AndFix原理

AndFix的原理很簡單。就是針對項目中原有方法的替換取代工作

而我們打一個在線的補丁包,也就有了如下的步驟邏輯:

AndFix 實例

Gradle依賴

dependencies {
    compile 'com.alipay.euler:andfix:0.3.1@aar'
}

配置Gradle

由於是進行hot fix,所以生成patch的兩個release apk是需要簽名的,再次我們需要創建一個臨時的簽名。這裏不講如何生成安卓簽名,生成好籤名後,配置簽名的到gradle文件中,下面是我建立的一個臨時簽名

    signingConfigs {
        debug {
            storeFile file('./../test_ks.jks')
            storePassword '123456'
            keyAlias '123456'
            keyPassword '123456'
        }
    }

代碼部分(version1 apk)

在清單文件中添加sdcard的權限,因爲apk需要訪問patch文件。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

配置一個自定義的Application。

public class AppContext extends Application {


    static AppContext instance;

    public static AppContext getInstance() {
        return instance;
    }

    PatchManager patchManager;

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        patchManager = new PatchManager(this);
        patchManager.init(BuildConfig.VERSION_NAME);
        patchManager.loadPatch();
    }

    public PatchManager getPatchManager() {
        return patchManager;
    }
}

寫一個界面代碼 
邏輯是這樣的,當點擊ActionButton的時候,會彈出一個Snackbar,點擊Snackbar上的按鈕,會彈出一個Toast。同時界面再啓動的時候會在加載一個.apatch文件,如果文件存在,則會添加這個補丁文件。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        String path = "/mnt/sdcard/out.apatch";
        if (new File(path).exists()) {
            Log.e("Test", "have some patch");
            try {
                AppContext.getInstance().getPatchManager().addPatch(path);
            } catch (Exception e) {
                Log.e("Test", "Test", e);
            }
        } else {
            Log.e("Test", "have no patch");
        }

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                showToast("11111");
                            }
                        }).show();
            }
        });
    }

    void showToast(String msg) {
        Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
    }
}

然後運行程序,會直接在手機上運行,然後我們找到項目的路徑中找到app-debug.apk文件,複製出來命名爲1.apk。

app/build/outputs/apk/app-debug.apk

代碼部分(version2 apk)

修改剛剛界面中代碼,修改如下,當點擊ActionButton,直接彈出Toast。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        String path = "/mnt/sdcard/out.apatch";
        if (new File(path).exists()) {
            Log.e("Test", "have some patch");
            try {
                AppContext.getInstance().getPatchManager().addPatch(path);
            } catch (Exception e) {
                Log.e("Test", "Test", e);
            }
        } else {
            Log.e("Test", "have no patch");
        }

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showToast("2222");
            }
        });
    }

    void showToast(String msg) {
        Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
    }
}

同樣運行程序後,複製運行過後的apk文件,命名爲2.apk

生成.apatch文件

下載Apatch文件生成工具,然後解壓縮,同時剛剛複製出來的2個apk文件,複製到同一個目錄下面,還有相對應的簽名文件。

運行下面的命令,即可生成一個apatch文件。

./apkpatch.sh -f 2.apk -t 1.apk -o ./ -k test_ks.jks -p 123456 -a 123456 -e 123456

工具的命令文檔如下:

usage: apkpatch -f <new> -t <old> -o <output> -k <keystore> -p <***> -a <alias> -e <***>
 -a,--alias <alias> keystore entry alias.  -e,--epassword <***> keystore entry password.  -f,--from <loc> new Apk file path.  -k,--keystore <loc> keystore path.  -n,--name <name> patch name.  -o,--out <dir> output dir.  -p,--kpassword <***> keystore password.  -t,--to <loc> old Apk file path.

我這邊生成的apatch文件如下:

 2-df8a710835742d3b84c9d9e47ca7f8d2.apatch

重命名爲out.apatch

驗證

把手機上的運行的卸載,重新安裝上1.apk,運行程序,然後通過命令導入out.apatch,再次運行1.apk,發現1.apk+apatch文件運行的效果和2.apk一樣。

adb push out.apatch /mnt/sdcard/

總結

我這邊只是簡單運行了下AndFix,寫了一個demo,考慮到實際項目中需求,可以在程序運行的時候,直接向服務器請求補丁文件,如果有文件需要更新,則下載文件,等到文件下載完成後,即可保證bug的修復。

原文來自: http://blog.csdn.net//guijiaoba/article/details/49936821


發佈了16 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章