Android实现App增量更新代码实现。

一、增量更新实现思路

   1)服务端生成patch差分包:

         值得注意的是,需要对用户安装的不同版本,生成不同的差分包,为了是让用户安装的所有版本都升级为最新的版本。

   2)客户端请求差分包:

         客户端在请求的时候,会把客户端的版本发送给服务端,服务端根据不同的版本,下发不同的差分包。

   3)客户端合成新的安装包:

          客户端通过调用native代码,将安装的包和下载的差分包生成新的安装包。这时需要对生成的安装包进行md5校验,保证生成的和最新的包是一样的。

二、服务端生成差分包的方法

      通过bsdiff命令生成差分包:bsdiff old.apk new.apk patch.apk

       old.apk是原apk路径,new.apk目前apk路径,patch.apk是生成的差分包的文件路径。

       命令下载:https://download.csdn.net/download/niuyongzhi/88366198?spm=1001.2014.3001.5501

执行命令:

生成的文件:

三、客户端生成新的安装包

        在没有服务端的情况下,客户端测试,可以把生成的patch包拷贝到sdcard目录下,当做是已经从服务端下载好的patch包。

        客户端调用native代码:

public static native int patch(String oldApkPath, String newApkPath,
			String patchPath);

     1)oldApkpath:安装在手机中的Apk包,可以通过一下代码获取。

     2)newApkPath:即合成新的Apk后的路径。

     3)patchPath:存放在sdcard的差分包路径。

  /**
     * 获取已安装Apk路径
     * packageName 报名
     */
    public static String getOldApkPath(Context context, String packageName) {
        if (TextUtils.isEmpty(packageName))
            return null;

        try {
            ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(packageName, 0);
            return appInfo.sourceDir;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        return null;
    }

   4)新的安装包生成后,进行md5校验,校验通过调用安装apk代码:

MD5校验代码:

private static String bytes2Hex(byte[] src) {
		char[] res = new char[src.length * 2];
		final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
		for (int i = 0, j = 0; i < src.length; i++) {
			res[j++] = hexDigits[src[i] >>> 4 & 0x0f];
			res[j++] = hexDigits[src[i] & 0x0f];
		}

		return new String(res);
	}

	public static String getMd5ByFile(File file) {
		String value = null;
		FileInputStream in = null;
		try {
			in = new FileInputStream(file);

			MessageDigest digester = MessageDigest.getInstance("MD5");
			byte[] bytes = new byte[8192];
			int byteCount;
			while ((byteCount = in.read(bytes)) > 0) {
				digester.update(bytes, 0, byteCount);
			}
			value = bytes2Hex(digester.digest());
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (null != in) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return value;
	}

调用系统api进行新包安装:

 public static void installApk(Context context, File file) {
        boolean canInstall = true;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            canInstall = context.getPackageManager().canRequestPackageInstalls();
        }
        if (canInstall) {
            Uri uri;
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            if (Build.VERSION.SDK_INT >= 24) {
                uri = FileProvider.getUriForFile(context, "com.example.patch.fileProvider", file);
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            } else {
                uri = Uri.fromFile(file);

            }
            intent.setDataAndType(uri, "application/vnd.android.package-archive");
            context.startActivity(intent);

        } else {
            context.startActivity(new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES));
        }
    }

这时,就完成了apk增量升级。

四:客户端编译native代码生成so库,供java端进行新版合成的进行调用。

  1)File->New->New Module 选择Android Native Library,创建一个Native module项目。

  2)将bip2的c层代码拷贝到cpp目录下。

3)配置CMakeLists.txt。红色框的代码是要编译的代码。绿色框中apk_pacth是编译后生成的so库的名字。

 

4)java层创建Native方法

public class PatchUtils {

	public static native int patch(String oldApkPath, String newApkPath,
			String patchPath);
}

5)Android Studio会自动提示生成JNI层对应的方法。如果没有,通过javac -h 或javah生成头文件。

javac -h 生成的头文件命令由三部分组成:

1)javac -h

2) 生成的头文件存放的路径

3)要生成头文件Native方法所在java类的路径。

命令执行会生成一个class文件和一个.h文件。

头文件长这个样子:

 4)编写JNI层代码。JNI大家都不陌生,他是连接Java和Native的桥梁。


/*
 * Class:     com_example_utils_PatchUtils
 * Method:    patch
 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_example_utils_PatchUtils_patch(JNIEnv *env,
                                                               jclass obj, jstring old, jstring new, jstring patch) {

    char * ch[4];
    ch[0] = "bspatch";
    ch[1] = (char*) ((*env)->GetStringUTFChars(env, old, 0));
    ch[2] = (char*) ((*env)->GetStringUTFChars(env, new, 0));
    ch[3] = (char*) ((*env)->GetStringUTFChars(env, patch, 0));

    __android_log_print(ANDROID_LOG_INFO, "ApkPatchLibrary", "old = %s ", ch[1]);
    __android_log_print(ANDROID_LOG_INFO, "ApkPatchLibrary", "new = %s ", ch[2]);
    __android_log_print(ANDROID_LOG_INFO, "ApkPatchLibrary", "patch = %s ", ch[3]);

    int ret = applypatch(4, ch);

    __android_log_print(ANDROID_LOG_INFO, "ApkPatchLibrary", "applypatch result = %d ", ret);

    (*env)->ReleaseStringUTFChars(env, old, ch[1]);
    (*env)->ReleaseStringUTFChars(env, new, ch[2]);
    (*env)->ReleaseStringUTFChars(env, patch, ch[3]);

    return ret;
}

bsdiff命令下载地址:https://download.csdn.net/download/niuyongzhi/88366198

代码下载地址:https://download.csdn.net/download/niuyongzhi/88374161

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

niuyongzhi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值