本文共 21279 字,大约阅读时间需要 70 分钟。
(创建于2017/12/17)
1.服务器生成差分包
服务器生成通常是在web项目中进行的,和客户端开发类似,先生成动态库,然后调用,我们创建一个web项目如下目录结构创建过程中涉及到一些问题
a.eclipse无法创建web项目,说明你的eclipse并没有下载一下需要的插件,百度可以找到答案(1)在确定联网的情况下,在help->install new software下根据你的eclipse版本选择下拉框选项,例如eclipse indigo,所选情况如下:
或者我的是luna
(3)安装这几个插件,耐心等待........安装完成之后,会自动弹出对话框让你重启eclipse,重启下就行,此时,就可以新建web项目了,如下:
这时就可以创建web工程了,这只是一个小插曲,其实我们可以直接写Java工程的,不过为了模拟的真实一些
2.接下来创建native方法,生成头文件,放入到visual studio中编写代码
public class DiffUtils { static{ System.loadLibrary("ndk_update"); } public native static void diff(String old,String newFile,String patchFile);}
/* DO NOT EDIT THIS FILE - it is machine generated */#include/* Header for class ndk_update_server_DiffUtils */#ifndef _Included_ndk_update_server_DiffUtils#define _Included_ndk_update_server_DiffUtils#ifdef __cplusplusextern "C" {#endif/* * Class: ndk_update_server_DiffUtils * Method: diff * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V */JNIEXPORT void JNICALL Java_ndk_1update_1server_DiffUtils_diff (JNIEnv *, jclass, jstring, jstring, jstring);#ifdef __cplusplus}#endif#endif
3.as工程目录概览
源文件中8个文件和头文件中的两个文件bzlib.h和bzilib_private.h都是bsdiff中拷贝过来的,有一点需要注意,as
时windows环境,所以我们下载的bsdiff需要时Windows版的 在bsdiff.cpp文件中写代码,如下/*- * Copyright 2003-2005 Colin Percival * All rights reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted providing that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE.*/#include#include "bzlib.h"#include #include //#include //#include #include #include //#include #include "ndk_update_server_DiffUtils.h"#include #include #include typedef unsigned char u_char;typedef long pid_t;template void err(int i, const char* str, T arg) { char lastErrorTxt[1024]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,NULL,GetLastError(),0,lastErrorTxt,1024,NULL); printf("%s",lastErrorTxt); printf(str, arg); exit(i);}void err(int i, const char* str) { char lastErrorTxt[1024]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,NULL,GetLastError(),0,lastErrorTxt,1024,NULL); printf("%s",lastErrorTxt); if (str!=NULL) { printf("%s",str); } exit(i);}template void errx(int i, const char* str, T arg) { printf(str, arg); exit(i);}void errx(int i, const char* str) { printf("%s",str); exit(i);}#define MIN(x,y) (((x)<(y)) ? (x) : (y))static void split(off_t *I,off_t *V,off_t start,off_t len,off_t h){ off_t i,j,k,x,tmp,jj,kk; if(len<16) { for(k=start;k start) split(I,V,start,jj-start,h); for(i=0;i kk) split(I,V,kk,start+len-kk,h);}static void qsufsort(off_t *I,off_t *V,u_char *old,off_t oldsize){ off_t buckets[256]; off_t i,h,len; for(i=0;i<256;i++) buckets[i]=0; for(i=0;i 0;i--) buckets[i]=buckets[i-1]; buckets[0]=0; for(i=0;i y) { *pos=I[st]; return x; } else { *pos=I[en]; return y; } }; x=st+(en-st)/2; if(memcmp(old+I[x],_new,MIN(oldsize-I[x],newsize))<0) { return search(I,old,oldsize,_new,newsize,x,en,pos); } else { return search(I,old,oldsize,_new,newsize,st,x,pos); };}static void offtout(off_t x,u_char *buf){ off_t y; if(x<0) y=-x; else y=x; buf[0]=y%256;y-=buf[0]; y=y/256;buf[1]=y%256;y-=buf[1]; y=y/256;buf[2]=y%256;y-=buf[2]; y=y/256;buf[3]=y%256;y-=buf[3]; y=y/256;buf[4]=y%256;y-=buf[4]; y=y/256;buf[5]=y%256;y-=buf[5]; y=y/256;buf[6]=y%256;y-=buf[6]; y=y/256;buf[7]=y%256; if(x<0) buf[7]|=0x80;}int diff(int argc,char *argv[]){ int fd; u_char *old,*_new; off_t oldsize,newsize; off_t *I,*V; off_t scan,pos,len; off_t lastscan,lastpos,lastoffset; off_t oldscore,scsc; off_t s,Sf,lenf,Sb,lenb; off_t overlap,Ss,lens; off_t i; off_t dblen,eblen; u_char *db,*eb; u_char buf[8]; u_char header[32]; FILE * pf; BZFILE * pfbz2; int bz2err; if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]); /* Allocate oldsize+1 bytes instead of oldsize bytes to ensure that we never try to malloc(0) and get a NULL pointer */ //org: //if(((fd=open(argv[1],O_RDONLY,0))<0) || // ((oldsize=lseek(fd,0,SEEK_END))==-1) || // ((old=malloc(oldsize+1))==NULL) || // (lseek(fd,0,SEEK_SET)!=0) || // (read(fd,old,oldsize)!=oldsize) || // (close(fd)==-1)) err(1,"%s",argv[1]); //new: //Read in chunks, don't rely on read always returns full data! if(((fd=open(argv[1],O_RDONLY|O_BINARY|O_NOINHERIT,0))<0) || ((oldsize=lseek(fd,0,SEEK_END))==-1) || ((old=(u_char*)malloc(oldsize+1))==NULL) || (lseek(fd,0,SEEK_SET)!=0)) err(1,"%s",argv[1]); int r=oldsize; while (r>0 && (i=read(fd,old+oldsize-r,r))>0) r-=i; if (r>0 || close(fd)==-1) err(1,"%s",argv[1]); if(((I=(off_t*)malloc((oldsize+1)*sizeof(off_t)))==NULL) || ((V=(off_t*)malloc((oldsize+1)*sizeof(off_t)))==NULL)) err(1,NULL); qsufsort(I,V,old,oldsize); free(V); /* Allocate newsize+1 bytes instead of newsize bytes to ensure that we never try to malloc(0) and get a NULL pointer */ //org: //if(((fd=open(argv[2],O_RDONLY,0))<0) || // ((newsize=lseek(fd,0,SEEK_END))==-1) || // ((_new=malloc(newsize+1))==NULL) || // (lseek(fd,0,SEEK_SET)!=0) || // (read(fd,_new,newsize)!=newsize) || // (close(fd)==-1)) err(1,"%s",argv[2]); //new: //Read in chunks, don't rely on read always returns full data! if(((fd=open(argv[2],O_RDONLY|O_BINARY|O_NOINHERIT,0))<0) || ((newsize=lseek(fd,0,SEEK_END))==-1) || ((_new=(u_char*)malloc(newsize+1))==NULL) || (lseek(fd,0,SEEK_SET)!=0)) err(1,"%s",argv[2]); r=newsize; while (r>0 && (i=read(fd,_new+newsize-r,r))>0) r-=i; if (r>0 || close(fd)==-1) err(1,"%s",argv[1]); if(((db=(u_char*)malloc(newsize+1))==NULL) || ((eb=(u_char*)malloc(newsize+1))==NULL)) err(1,NULL); dblen=0; eblen=0; /* Create the patch file */ //org: //if ((pf = fopen(argv[3], "w")) == NULL) //new: //if((fd=open(argv[3],O_CREAT|O_TRUNC|O_WRONLY|O_BINARY|O_NOINHERIT,0666))<0) if ((pf = fopen(argv[3], "wb")) == NULL) err(1,"%s",argv[3]); /* Header is 0 8 "BSDIFF40" 8 8 length of bzip2ed ctrl block 16 8 length of bzip2ed diff block 24 8 length of new file */ /* File is 0 32 Header 32 ?? Bzip2ed ctrl block ?? ?? Bzip2ed diff block ?? ?? Bzip2ed extra block */ memcpy(header,"BSDIFF40",8); offtout(0, header + 8); offtout(0, header + 16); offtout(newsize, header + 24); if (fwrite(header, 32, 1, pf) != 1) err(1, "fwrite(%s)", argv[3]); /* Compute the differences, writing ctrl as we go */ if ((pfbz2 = BZ2_bzWriteOpen(&bz2err, pf, 9, 0, 0)) == NULL) errx(1, "BZ2_bzWriteOpen, bz2err = %d", bz2err); scan=0;len=0; lastscan=0;lastpos=0;lastoffset=0; while(scan oldscore+8)) break; if((scan+lastoffset Sf*2-lenf) { Sf=s; lenf=i; }; }; lenb=0; if(scan =lastscan+i)&&(pos>=i);i++) { if(old[pos-i]==_new[scan-i]) s++; if(s*2-i>Sb*2-lenb) { Sb=s; lenb=i; }; }; }; if(lastscan+lenf>scan-lenb) { overlap=(lastscan+lenf)-(scan-lenb); s=0;Ss=0;lens=0; for(i=0;i Ss) { Ss=s; lens=i+1; }; }; lenf+=lens-overlap; lenb-=lens; }; for(i=0;i GetStringUTFChars(old_path, NULL)); char * newfile = (char *)(env->GetStringUTFChars(new_path, NULL)); char * patchfile = (char *)(env->GetStringUTFChars(patch_path, NULL)); //定义参数 char *argv[4]; argv[0] = "renzhenming"; argv[1]=oldfile; argv[2]= newfile; argv[3]=patchfile; diff(argc, argv); env->ReleaseStringUTFChars(old_path, oldfile); env->ReleaseStringUTFChars(new_path, newfile); env->ReleaseStringUTFChars(patch_path, patchfile);}
然后生成动态库,放到eclipse web工程目录下,写工程调用生成差分包
public class UpdateTest { public static void main(String[] args) { DiffUtils.diff(ConstantsWin.OLD_APK_PATH, ConstantsWin.NEW_APK_PATH, ConstantsWin.PATCH_PATH); System.out.println("差分包生成成功"); }}
2.客户端合并差分包生成新包
创建native方法生成头文件
public class BsPatch { /** * 合并 * * @param oldfile * @param newfile * @param patchfile */ public native static void patch(String oldfile, String newfile, String patchfile); static{ System.loadLibrary("bspatch"); } }
/* DO NOT EDIT THIS FILE - it is machine generated */#include/* Header for class com_example_ndk_patch_utils_BsPatch */#ifndef _Included_com_example_ndk_patch_utils_BsPatch#define _Included_com_example_ndk_patch_utils_BsPatch#ifdef __cplusplusextern "C" {#endif/* * Class: com_example_ndk_patch_utils_BsPatch * Method: patch * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V */JNIEXPORT void JNICALL Java_com_example_ndk_1patch_utils_BsPatch_patch (JNIEnv *, jclass, jstring, jstring, jstring);#ifdef __cplusplus}#endif#endif
创建jni目录,将头文件复制进去,添加bspatch.c文件和相关的bzip文件,注意,Android系统是基于Linux的,所以这里的文件需要是Linux版本的
然后在右键add native support,然后在添加ndk的相关头文件的目录
D:\application\java\android-ndk-r10e\toolchains\arm-linux-androideabi-4.8\prebuilt\windows-x86_64\lib\gcc\arm-linux-androideabi\4.8\includeD:\application\java\android-ndk-r10e\toolchains\arm-linux-androideabi-4.8\prebuilt\windows-x86_64\lib\gcc\arm-linux-androideabi\4.8\include-fixedD:\application\java\android-ndk-r10e\platforms\android-18\arch-arm\usr\include
然后似乎就没有问题了,这里遇到过问题,有可能是add native和添加ndk目录的时机不对,导致c文件中或者头文件中的属性类之类的爆红,显示无法resolve,不知道
何故,不过后来按上边的顺序就可以了,也是坑bspathc中添加合并的代码,注意一些相关头文件的引入
/*- * Copyright 2003-2005 Colin Percival * All rights reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted providing that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#if 0__FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59:06 cperciva Exp $");#endif#include "com_example_ndk_patch_utils_BsPatch.h"#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#include #include #include #include #include static off_t offtin(u_char *buf){ off_t y; y=buf[7]&0x7F; y=y*256;y+=buf[6]; y=y*256;y+=buf[5]; y=y*256;y+=buf[4]; y=y*256;y+=buf[3]; y=y*256;y+=buf[2]; y=y*256;y+=buf[1]; y=y*256;y+=buf[0]; if(buf[7]&0x80) y=-y; return y;}int bspatch_main(int argc,char * argv[]){ FILE * f, * cpf, * dpf, * epf; BZFILE * cpfbz2, * dpfbz2, * epfbz2; int cbz2err, dbz2err, ebz2err; int fd; ssize_t oldsize,newsize; ssize_t bzctrllen,bzdatalen; u_char header[32],buf[8]; u_char *old, *new; off_t oldpos,newpos; off_t ctrl[3]; off_t lenread; off_t i; if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]); /* Open patch file */ if ((f = fopen(argv[3], "r")) == NULL) err(1, "fopen(%s)", argv[3]); /* File format: 0 8 "BSDIFF40" 8 8 X 16 8 Y 24 8 sizeof(newfile) 32 X bzip2(control block) 32+X Y bzip2(diff block) 32+X+Y ??? bzip2(extra block) with control block a set of triples (x,y,z) meaning "add x bytes from oldfile to x bytes from the diff block; copy y bytes from the extra block; seek forwards in oldfile by z bytes". */ /* Read header */ if (fread(header, 1, 32, f) < 32) { if (feof(f)) errx(1, "Corrupt patch\n"); err(1, "fread(%s)", argv[3]); } /* Check for appropriate magic */ if (memcmp(header, "BSDIFF40", 8) != 0) errx(1, "Corrupt patch\n"); /* Read lengths from header */ bzctrllen=offtin(header+8); bzdatalen=offtin(header+16); newsize=offtin(header+24); if((bzctrllen<0) || (bzdatalen<0) || (newsize<0)) errx(1,"Corrupt patch\n"); /* Close patch file and re-open it via libbzip2 at the right places */ if (fclose(f)) err(1, "fclose(%s)", argv[3]); if ((cpf = fopen(argv[3], "r")) == NULL) err(1, "fopen(%s)", argv[3]); if (fseeko(cpf, 32, SEEK_SET)) err(1, "fseeko(%s, %lld)", argv[3], (long long)32); if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL) errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err); if ((dpf = fopen(argv[3], "r")) == NULL) err(1, "fopen(%s)", argv[3]); if (fseeko(dpf, 32 + bzctrllen, SEEK_SET)) err(1, "fseeko(%s, %lld)", argv[3], (long long)(32 + bzctrllen)); if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL) errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err); if ((epf = fopen(argv[3], "r")) == NULL) err(1, "fopen(%s)", argv[3]); if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET)) err(1, "fseeko(%s, %lld)", argv[3], (long long)(32 + bzctrllen + bzdatalen)); if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL) errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err); if(((fd=open(argv[1],O_RDONLY,0))<0) || ((oldsize=lseek(fd,0,SEEK_END))==-1) || ((old=malloc(oldsize+1))==NULL) || (lseek(fd,0,SEEK_SET)!=0) || (read(fd,old,oldsize)!=oldsize) || (close(fd)==-1)) err(1,"%s",argv[1]); if((new=malloc(newsize+1))==NULL) err(1,NULL); oldpos=0;newpos=0; while(newpos newsize) errx(1,"Corrupt patch\n"); /* Read diff string */ lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]); if ((lenread < ctrl[0]) || ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END))) errx(1, "Corrupt patch\n"); /* Add old data to diff string */ for(i=0;i =0) && (oldpos+i newsize) errx(1,"Corrupt patch\n"); /* Read extra string */ lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]); if ((lenread < ctrl[1]) || ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END))) errx(1, "Corrupt patch\n"); /* Adjust pointers */ newpos+=ctrl[1]; oldpos+=ctrl[2]; }; /* Clean up the bzip2 reads */ BZ2_bzReadClose(&cbz2err, cpfbz2); BZ2_bzReadClose(&dbz2err, dpfbz2); BZ2_bzReadClose(&ebz2err, epfbz2); if (fclose(cpf) || fclose(dpf) || fclose(epf)) err(1, "fclose(%s)", argv[3]); /* Write the new file */ if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) || (write(fd,new,newsize)!=newsize) || (close(fd)==-1)) err(1,"%s",argv[2]); free(new); free(old); return 0;}JNIEXPORT void JNICALL Java_com_example_ndk_1patch_utils_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);}
其他文件上源码好了,自己看吧,我是懒得写了,这个笔记的过程,并不是一步一步就可以实现的,而是我实现之后按照记忆写的,有些地方肯定还有坑
MainActivity.java
package com.example.ndk_patch;import java.io.File;import com.example.ndk_patch.utils.ApkUtils;import com.example.ndk_patch.utils.BsPatch;import com.example.ndk_patch.utils.Constants;import com.example.ndk_patch.utils.DownloadUtils;import android.app.Activity;import android.os.AsyncTask;import android.os.Bundle;import android.os.Handler;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 Handler().postDelayed(new Runnable() { @Override public void run() { new ApkUpdateTask().execute(); } }, 2000); } class ApkUpdateTask extends AsyncTask{ @Override protected Boolean doInBackground(Void... params) { try { System.out.println("开始合并"); File patchFile = new File(Constants.PATCH_FILE_PATH); if (patchFile.exists()) { //获取当前应用的apk文件/data/app/app String oldfile = ApkUtils.getSourceApkPath(MainActivity.this, getPackageName()); //2.合并得到最新版本的APK文件 String newfile = Constants.NEW_APK_PATH; String patchfile = patchFile.getAbsolutePath(); BsPatch.patch(oldfile, newfile, patchfile); }else{ return false; } } catch (Exception e) { e.printStackTrace(); return false; } return true; } @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); //3.安装 if(result){ System.out.println("合并成功"); Toast.makeText(MainActivity.this, "合并成功,您正在进行无流量更新", Toast.LENGTH_SHORT).show(); ApkUtils.installApk(MainActivity.this, Constants.NEW_APK_PATH); } } }}
ApkUtils.java
package com.example.ndk_patch.utils;import android.content.Context;import android.content.Intent;import android.content.pm.ApplicationInfo;import android.content.pm.PackageManager;import android.content.pm.PackageManager.NameNotFoundException;import android.net.Uri;import android.text.TextUtils;public class ApkUtils { public static boolean isInstalled(Context context, String packageName) { PackageManager pm = context.getPackageManager(); boolean installed = false; try { pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES); installed = true; } catch (Exception e) { e.printStackTrace(); } return installed; } /** * 获取已安装Apk文件的源Apk文件 * 如:/data/app/my.apk * * @param context * @param packageName * @return */ public static String getSourceApkPath(Context context, String packageName) { if (TextUtils.isEmpty(packageName)) return null; try { ApplicationInfo appInfo = context.getPackageManager() .getApplicationInfo(packageName, 0); return appInfo.sourceDir; } catch (NameNotFoundException e) { e.printStackTrace(); } return null; } /** * 安装Apk * * @param context * @param apkPath */ public static void installApk(Context context, String apkPath) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.parse("file://" + apkPath), "application/vnd.android.package-archive"); context.startActivity(intent); }}
BsPatch.java
package com.example.ndk_patch.utils;public class BsPatch { /** * 合并 * * @param oldfile * @param newfile * @param patchfile */ public native static void patch(String oldfile, String newfile, String patchfile); static{ System.loadLibrary("bspatch"); } }
Constants.java
import java.io.File;import android.os.Environment;public class Constants { public static final String SD_CARD = Environment.getExternalStorageDirectory() + File.separator; public static final String NEW_APK_PATH = SD_CARD+"apk_new.apk"; public static final String PATCH_FILE = "apk.patch"; public static final String PATCH_FILE_PATH = SD_CARD+PATCH_FILE; }
转载地址:http://bkonl.baihongyu.com/