美文网首页
客户端合并差分文件实现更新(Android环境下)

客户端合并差分文件实现更新(Android环境下)

作者: 知用改创 | 来源:发表于2016-10-15 19:51 被阅读273次

客户端合并差分文件实现更新(Android环境下)

1. 下载差分文件

编写下载文件工具类DownloadUtils

package com.skyward.increment_update.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.os.Environment;

public class DownloadUtils {

    /**
     * 下载差分文件
     * @param url
     * @return
     * @throws Exception
     */
    public static File download(String url){
        File file = null;
        InputStream is = null;
        FileOutputStream os = null;
        try {
            file = new File(Environment.getExternalStorageDirectory(),Constants.PATCH_FILE);
            if (file.exists()) {
                file.delete();
            }
            HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
            conn.setDoInput(true);
            is = conn.getInputStream();
            os = new FileOutputStream(file);
            byte[] buffer = new byte[1024];
            int len = 0;
            while((len = is.read(buffer)) != -1){
                os.write(buffer, 0, len);
            }
        } catch(Exception e){
            e.printStackTrace();
        }finally{
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;
    }
    
}

2.将旧版本的apk文件和差分文件合并生成新版本的apk文件

  1. 添加本地支持,右击项目,点击Android Tools-> Add Native Support


    NDK开发配置
  2. 对Android项目进行NDK开发所需的相关配置


    NDK开发配置
  3. 编写Java本地方法

package com.skyward.increment_update.util;

public class BsPatch {

    /**
     * 合并差分文件
     * 
     * @param oldfile
     * @param newfile
     * @param patchfile
     */
    public native static void patch(String oldfile, String newfile, String patchfile);

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

4.使用javah命令生成头文件,并将其拷贝至项目的jni目录下。


javah命令生成头文件

5.去bsdiff/bspatch官网下载源码,bsdiff/bspatch源码下载地址。下载完成后,解压,将bspatch.c文件拷贝至项目的jni目录下。
6.进入bsdiff4.3-win32-src目录,用Visual Studio打开bspatch.dsp文件。

bspatch项目目录结构
7.在项目的jni目录下新建一个bzip2目录,将该bspatch项目所有的头文件和源文件(除bspatch.cpp外)拷贝至该目录下。
Java项目目录结构
8.修改bspatch.c文件,将其中的main函数修改为bspatch_main。用C语言实现Java本地方法调用bspatch_main方法。
#include "com_skyward_increment_update_util_BsPatch.h"
//可以将bzip2目录下所有的源文件都引入进来,也可以在Android.mk文件中编译所有源文件
//#include "bzip2/bzlib.c"
//#include "bzip2/crctable.c"
//#include "bzip2/compress.c"
//#include "bzip2/decompress.c"
//#include "bzip2/randtable.c"
//#include "bzip2/blocksort.c"
//#include "bzip2/huffman.c"

#include "bzip2/bzlib.h"
#include "bzip2/bzlib_private.h"
JNIEXPORT void JNICALL Java_com_skyward_increment_1update_util_BsPatch_patch
  (JNIEnv *env, jclass jcls, jstring oldfile_jstr, jstring newfile_jstr, jstring patchfile_jstr){
    int argc = 4;
    char* oldfile = (char*)(*env)->GetStringUTFChars(env,oldfile_jstr, NULL);
    char* newfile = (char*)(*env)->GetStringUTFChars(env,newfile_jstr, NULL);
    char* patchfile = (char*)(*env)->GetStringUTFChars(env,patchfile_jstr, NULL);

    char *argv[4];
    argv[0] = "bspatch";
    argv[1] = oldfile;
    argv[2] = newfile;
    argv[3] = patchfile;

    bspatch_main(argc,argv);

    (*env)->ReleaseStringUTFChars(env,oldfile_jstr, oldfile);
    (*env)->ReleaseStringUTFChars(env,newfile_jstr, newfile);
    (*env)->ReleaseStringUTFChars(env,patchfile_jstr, patchfile);
}

9.编写Android.mk文件

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := bspatch
LOCAL_SRC_FILES := bspatch.c bzip2/blocksort.c bzip2/bzlib.c bzip2/compress.c bzip2/crctable.c bzip2/decompress.c bzip2/huffman.c bzip2/randtable.c

include $(BUILD_SHARED_LIBRARY)

10.编写AndroidManifest.xml

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

3.安装新版本的apk文件

package com.skyward.increment_update;

import java.io.File;

import com.skyward.increment_update.util.ApkUtils;
import com.skyward.increment_update.util.BsPatch;
import com.skyward.increment_update.util.Constants;
import com.skyward.increment_update.util.DownloadUtils;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new ApkUpdateTask().execute();
    }
    
    class ApkUpdateTask extends AsyncTask<Void, Void, Boolean> {

        @Override
        protected Boolean doInBackground(Void... params) {
            try {
                
                // 1. 下载差分文件
                File patch_file = DownloadUtils.download(Constants.URL_PATCH_DOWNLOAD_WINDOWS);
                Log.d("skyward", "下载差分文件");
                // 2. 合并差分文件
                String oldfile = ApkUtils.getSourceApkPath(MainActivity.this, getPackageName());
                BsPatch.patch(oldfile, Constants.NEW_APK_PATH, patch_file.getAbsolutePath());
                Log.d("skyward", "合并差分文件");
                return true;
            } catch (Exception e) {
                return false;
            }
            
        }
        
        protected void onPostExecute(Boolean result) {
            // 3. 安装apk
            if(result){
                Toast.makeText(MainActivity.this, "您正在进行无流量更新", Toast.LENGTH_SHORT).show();
                ApkUtils.installApk(MainActivity.this, Constants.NEW_APK_PATH);
            }
        };
    }
}

测试

至于测试在这里就不再赘述。简述一下步骤:

  1. 运行服务端的程序,生成差分文件
  2. 将生成的差分文件部署到服务端,供客户端下载
  3. 在手机端安装旧版本的apk文件


    安装新版本
    新版本apk

要注意:新旧版本的apk包名要一致

总结

本文只是简单介绍了一下增量更新的基本原理和步骤,代码还有很多地方可以完善的,比如服务端应该对各个apk版本进行版本控制,生成各个不同版本之间的apk文件。客户端的代码也可以优化,比如一般在后台服务中下在差分文件,下载差分文件时,应该检查当前客户端的版本号,下载对应的差分包。

相关文章

网友评论

      本文标题:客户端合并差分文件实现更新(Android环境下)

      本文链接:https://www.haomeiwen.com/subject/adhoyttx.html