增量更新操作詳解

增量更新操作詳解

               ONE Goal , ONE Passion !

簡介:


studio中操作步驟:

第一步:定義native方法

  • 直接copy兩個工具類到項目中,如圖1
    這裏寫圖片描述

DiffUtils文件: 生成補丁


       public class DiffUtils {

        /**
         * 本地方法 比較路徑爲oldPath的apk與newPath的apk之間差異,並生成patch(補丁)包,存儲於patchPath
         * 
         *
         * @return
         */
        public static native int genDiff(String oldApkPath, String newApkPath,
                                         String patchPath);
    }

PatchUtils文件: 合成apk

    public class PatchUtils {

        /**
         * native方法
         * 使用路徑爲oldApkPath的apk與路徑爲patchPath的補丁包,合成新的apk,並存儲於newApkPath
         * @param oldApkPath
         * @param newApkPath
         * @param patchPath
         * @return
         */
        public static native int patch(String oldApkPath, String newApkPath,
                                       String patchPath);
    }

第二步:使用javah命令生成兩個.h頭文件

  • 找到源文件G:\andirodWorkspace\PatchDemo\app\src\main\java路徑.
  • 右鍵shift + 右鍵. 打開命令行 輸入javah命令

    javah com.fy.patchdemo.utils.PatchUtils
    
    javah com.fy.patchdemo.utils.DiffUtils
    

如圖2:
這裏寫圖片描述

第三步:新建jni目錄

  1. 將生成兩個.h頭文件複製到jni目錄(注意:jni和java文件在同一個目錄)
  2. 將合成補丁的相關c文件導入jni目錄中.如圖3

這裏寫圖片描述

  1. 編寫我們定義的兩個本地方法.

可是有點哥們說,不會寫c代碼啊! 表擔心.兩個c文件有現成的只要我們修改一下就行了.

特別注意:兩個文件分別是diff.c patch.c文件

pathc.c文件
#include "com_fy_mypatch_apkutils_PatchUtils.h". 由於是直接copy的,所以這個頭文件名要改成剛剛自己生成的

這裏寫圖片描述
diff.c文件
#include “com_fy_mypatch_apkutils_DiffUtils.h” . 由於是直接copy的,所以這個頭文件名要改成剛剛自己生成的

這裏寫圖片描述

  • 4.還要修改兩個文件pathcutils.c 和 diffutils.c文件.

兩個文件中的方法名,一定要修改成相對應.h文件中生成的方法名.如圖:

這裏寫圖片描述


這裏寫圖片描述

第四步:編譯生成so文件

1.在gradle.properties最後添加一句:

  使用ndk開發可用
  android.useDeprecatedNdk=true

2.在build.gradle(modle)中配置:

  defaultConfig {
    applicationId "com.fy.patchdemo"
    minSdkVersion 15
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"

      配置如下 :
    ndk{
        moduleName "diff"         //生成的so名字
        abiFilters "armeabi", "armeabi-v7a", "x86"  //輸出指定三種abi體系結構下的so庫。目前可有可無。
    }
}

3.build-Make Project生成相應的so文件.編譯後在app-build-intermediates-ndk下查看生成的文件.此時已經有ndk文件了.

第五步:代碼部分

  1. MainActivity:

        public class MainActivity extends AppCompatActivity {

        private String oldapk = "mnt/sdcard/old.apk"; //當前apk文件.
        private String newapk = "mnt/sdcard/new.apk";//將要更新的最新apk (一般不會出現在我們的android代碼中,這裏爲了測試)
        private String pathapk = "mnt/sdcard/path.patch"; //old.apk 與 new.apk生成的補丁文件.   -----線下完成
        private String complexapk = "mnt/sdcard/newapk.apk";//合併後的apk (old.apk與path.patch文件生成最新apk)
        private ProgressDialog dialog;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            dialog = new ProgressDialog(this);
            dialog.setMessage("請稍後...");


        }


        static {
            System.loadLibrary("diff");
        }

        public void onclick(View view) {
            switch (view.getId()) {
                case R.id.add: //合成apk
                    //    dialog.show();
                    new Thread(new Runnable() {

                        @Override
                        public void run() {

                            // TODO Auto-generated method stub
                            PatchUtils.patch(oldapk, complexapk, pathapk);
                            runOnUiThread(new Runnable() {
                                public void run() {
                                    Toast.makeText(MainActivity.this, "補丁合成完畢", Toast.LENGTH_SHORT).show();
                                    dialog.dismiss();

                                    Intent intent = new Intent(Intent.ACTION_VIEW);
                                    intent.setDataAndType(Uri.parse("file:///sdcard/newapk.apk"),
                                            "application/vnd.android.package-archive");
                                    startActivity(intent);
                                }
                            });
                        }
                    }).start();

                    break;
                case R.id.diff://根據兩個版本apk生成補丁
                    //       dialog.show();
                    new Thread(new Runnable() {

                        @Override
                        public void run() {

                            DiffUtils.genDiff(oldapk, newapk, pathapk);
                            runOnUiThread(new Runnable() {
                                public void run() {
                                    Toast.makeText(MainActivity.this, "生成補丁完成", Toast.LENGTH_SHORT).show();
                                    dialog.dismiss();
                                }
                            });
                        }
                    }).start();

                    break;
                default:
                    break;
            }
        }
    }

第6步:測試

如果是測試.生成補丁.要先生成一個不同版本apk放到sd卡下,注意apk名字要和代碼中一致oldapk.

如果實際開發.後臺生成補丁包的名字也要和代碼一致:path. 代碼可以修改

第6步:測試效果

這裏寫圖片描述

——————實際開發————————-

  • 使用差分工具生成2個apk的差異文件(補丁).
    工具使用: 在bsdiff工具目錄下,右鍵+shift 打開命令行. 執行命令.即可生成補丁.

這裏寫圖片描述

  • 將生成的差異文件放到自己的服務器上
  • 用戶點擊省流量更新,下載差分文件(補丁),放到固定的位置(比如:/mnt/sdcard/path)
  • 將補丁與當前apk合併成新的apk.
//獲取本應用的apk包路徑
            public String getSelfApkPath() {
                List<ApplicationInfo> installList = getPackageManager().getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);  
                for (int i = 0; i < installList.size(); i++) {  
                    ApplicationInfo info=installList.get(i);  
                    if(info.packageName.equals(getPackageName())){

                        return info.sourceDir;
                    }
                }
                return null;
            }
  • 將舊的應用刪除.

附: 差分工具,以及項目demo
http://download.csdn.net/my

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