Android之增量更新

Android之增量更新

標籤: 增量更新android源碼工具
311人閱讀 評論(0) 收藏 舉報
本文章已收錄於:
category_icon.jpg分類:

Android增量更新簡單描述:

簡單的說,就是在有一箇舊版本A的情況下,想在這個基礎上更新一個新版本B。那麼,我們不需要下載整個B,只需要下載A與B的差分包。將差分包下載到本地後,與舊版本A整合爲一個新的apk,這個apk大小與內容與新版本B完全一致,這就是增量更新。

假如,A的大小是5M,B的大小是8M,那麼差分包的大小S=(8-5)+差異文件的依賴(如上下文)。差分包的大小會大於3M。

Android增量更新如何實現:

這裏我們有用到一對工具,bsdiff.exe、bspatch.exe。可在後續的源碼中下載。


用工具,很容易達到這個效果,有兩個步驟:

假如,你將這對工具放置在如下路徑下:D:\zhao.yang\Downloads\test_UpdateSome\test\bsdiff4.3-win32,那麼,請先打開cmd,輸入命令: cd D:\zhao.yang\Downloads\test_UpdateSome\test\bsdiff4.3-win32 ,按Enter後,再輸入命令:cd d: ,進入該目錄下。

(1)新舊版本生成差分包

命令格式:bsdiff.exe 舊版本apk路徑  新版本apk路徑 差分包存儲路徑 

按這命令格式,我們寫出如下命令:

bsdiff.exe D:\Java\workspace\ApkPatchAndroidDemo\bin\ApkPatchAndroid_old.apk D:\JAVA\workspace\ApkPatchAndroidDemo\bin\ApkPatchAndroid_new.apk D:\JAVA\workspace\ApkPatchAndroidDemo\bin\test.patch

即可得到相應的差分包test.patch。

(2)整合差分包與舊版本apk

命令格式:bspatch.exe 舊版本apk路徑 新版本apk路徑 差分包存儲路徑

按這命令格式,我們寫出如下命令:

bspatch.exe D:\JAVA\workspace\ApkPatchAndroidDemo\bin\ApkPatchAndroid_old.apk D:\JAVA\workspace\ApkPatchAndroidDemo\bin\ApkPatchAndroid_2new.apk D:\JAVA\workspace\ApkPatchAndroidDemo\bin\test.patch


經過以上兩個步驟,我們完成了差分包生成,差分包與舊版本apk的整合,你會發現最後得到的apk就是你需要的apk。到這裏,用工具演示的增量更新的步驟就完成了。但是,在android中,當你在做android的增量更新時,是需要源碼實現的。

下方就介紹如何實現:

Android端整合差分包與舊版本apk的實現

這裏暫時將舊版本apk、差分包都放在SD卡的根目錄下。

這裏引入了一位高手寫的開源源碼,引用JNI實現整合。在主界面上無需寫什麼代碼,只要根據函數參數要求填入參數即可:

  1. package com.example.apkpatch2newapk;  
  2.   
  3.   
  4. import java.io.File;  
  5.   
  6. import com.dodola.patcher.utils.AppUtils;  
  7.   
  8. import android.os.Bundle;  
  9. import android.os.Environment;  
  10. import android.app.Activity;  
  11. import android.view.Menu;  
  12. import android.view.View;  
  13. import android.view.View.OnClickListener;  
  14. import android.widget.Button;  
  15.   
  16. public class MainActivity extends Activity {  
  17.   
  18.       
  19.     String oldApkPathString=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator +"ApkPatchAndroid_old.apk";  
  20.     String newApkPathString=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator +"ApkPatchAndOld2New.apk";  
  21.     String patchPathString=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator +"test.patch";  
  22.       
  23.     static {  
  24.         // 調用.so文件,引入打包庫  
  25.         System.loadLibrary("Patcher");  
  26.     }  
  27.   
  28.     @Override  
  29.     protected void onCreate(Bundle savedInstanceState) {  
  30.         super.onCreate(savedInstanceState);  
  31.         setContentView(R.layout.activity_main);  
  32.         Button btnButton=(Button)findViewById(R.id.btn);  
  33.         btnButton.setOnClickListener(new OnClickListener() {  
  34.               
  35.             @Override  
  36.             public void onClick(View v) {  
  37.                 // TODO Auto-generated method stub  
  38.                 AppUtils.patcher(oldApkPathString, newApkPathString, patchPathString);  
  39.             }  
  40.         });  
  41.           
  42.     }  
  43.   
  44. }  
save_snippets.png
package com.example.apkpatch2newapk;


import java.io.File;

import com.dodola.patcher.utils.AppUtils;

import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {

	
	String oldApkPathString=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator +"ApkPatchAndroid_old.apk";
	String newApkPathString=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator +"ApkPatchAndOld2New.apk";
	String patchPathString=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator +"test.patch";
	
	static {
		// 調用.so文件,引入打包庫
		System.loadLibrary("Patcher");
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Button btnButton=(Button)findViewById(R.id.btn);
		btnButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				AppUtils.patcher(oldApkPathString, newApkPathString, patchPathString);
			}
		});
		
	}

}

重點還在於patcher這個函數中。

  1. package com.dodola.patcher.utils;  
  2.   
  3. import java.io.File;  
  4.   
  5. import android.content.Context;  
  6. import android.content.Intent;  
  7. import android.net.Uri;  
  8.   
  9. /**  
  10.  *應用程序的工具類  
  11.  * @author Administrator  
  12.  *  
  13.  */  
  14. public class AppUtils {  
  15.   
  16.     /**  
  17.      * 安裝一個應用程序  
  18.      * @param context  
  19.      * @param apkfile  
  20.      */  
  21.     public static void installApplication(Context context,File apkfile){  
  22.       /*   <action android:name="android.intent.action.VIEW" />  
  23.          <category android:name="android.intent.category.DEFAULT" />  
  24.          <data android:scheme="content" />  
  25.          <data android:scheme="file" />  
  26.          <data android:mimeType="application/vnd.android.package-archive" />*/  
  27.         Intent intent = new Intent();  
  28.         intent.setAction("android.intent.action.VIEW");  
  29.         intent.addCategory("android.intent.category.DEFAULT");  
  30. //      intent.setType("application/vnd.android.package-archive");  
  31. //      intent.setData(Uri.fromFile(apkfile));  
  32.         intent.setDataAndType(Uri.fromFile(apkfile), "application/vnd.android.package-archive");  
  33.         context.startActivity(intent);  
  34.     }  
  35.       
  36.     /**  
  37.      * 調用.so庫中的方法,合併apk  
  38.      *   
  39.      * @param old  
  40.      *            舊Apk地址  
  41.      * @param newapk  
  42.      *            新apk地址(名字)  
  43.      * @param patch  
  44.      *            增量包地址  
  45.      */  
  46.     public static native void patcher(String old, String newapk, String patch);  
  47. }  
save_snippets.png
package com.dodola.patcher.utils;

import java.io.File;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;

/**
 *應用程序的工具類
 * @author Administrator
 *
 */
public class AppUtils {

	/**
	 * 安裝一個應用程序
	 * @param context
	 * @param apkfile
	 */
	public static void installApplication(Context context,File apkfile){
	  /*   <action android:name="android.intent.action.VIEW" />
         <category android:name="android.intent.category.DEFAULT" />
         <data android:scheme="content" />
         <data android:scheme="file" />
         <data android:mimeType="application/vnd.android.package-archive" />*/
		Intent intent = new Intent();
		intent.setAction("android.intent.action.VIEW");
		intent.addCategory("android.intent.category.DEFAULT");
//		intent.setType("application/vnd.android.package-archive");
//		intent.setData(Uri.fromFile(apkfile));
		intent.setDataAndType(Uri.fromFile(apkfile), "application/vnd.android.package-archive");
		context.startActivity(intent);
	}
	
	/**
	 * 調用.so庫中的方法,合併apk
	 * 
	 * @param old
	 *            舊Apk地址
	 * @param newapk
	 *            新apk地址(名字)
	 * @param patch
	 *            增量包地址
	 */
	public static native void patcher(String old, String newapk, String patch);
}
整合的開源源碼內容,主要是jni實現的c/c++代碼,感興趣的可以在下方的源碼下載中看。

注意:

(1)不熟悉jni的同學,這裏要注意一點,jni的方法與包名是相關的,因此如果想用這個方法,最方便的是把包名也一起復制過去即可。

(2)該方法是需要用到NDK環境的,如果沒有這個環境,可以到如下地址下載:

NDK下載鏈接:http://pan.baidu.com/s/1bn0H75P 密碼:6cje

(3)可在Window-Preferences-NDK中配置下載的NDK。


源碼與工具下載:

http://download.csdn.net/detail/yangzhaomuma/9448393





NDK下載鏈接:http://pan.baidu.com/s/1bn0H75P 密碼:6cje
1
0

我的同類文章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章