增量更新工具类【https://github.com/cundong/SmartAppUpdates】

 import java.io.File;

 import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast; import com.cundong.utils.PatchUtils;
import com.example.test.util.ApkUtils;
import com.example.test.util.SignUtils;
import com.example.test2.R; /**
* 类说明: ApkPatchLibrary 使用 Demo
*
* @author Cundong
* @version 1.5
*/
public class MainActivity extends Activity { // 合成成功
private static final int WHAT_SUCCESS = 1; // 合成的APK签名和已安装的签名不一致
private static final int WHAT_FAIL_SING = -1; // 合成失败
private static final int WHAT_FAIL_ERROR = -2; // 获取源文件失败
private static final int WHAT_FAIL_GET_SOURCE = -3; private Context mContext = null; private ProgressDialog mProgressDialog;
private TextView mResultView;
private Button mStartButton, mGithubButton; private long mBeginTime, mEndTime; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); mContext = getApplicationContext(); mProgressDialog = new ProgressDialog(this);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setMessage("doing..");
mProgressDialog.setCancelable(false); mResultView = (TextView) findViewById(R.id.textview4);
mStartButton = (Button) findViewById(R.id.start_btn);
mGithubButton = (Button) findViewById(R.id.github_btn); mStartButton.setOnClickListener(new OnClickListener() { @Override
public void onClick(View arg0) { File patchFile = new File(Constants.PATCH_PATH); if (!ApkUtils.isInstalled(mContext, Constants.TEST_PACKAGENAME)) {
Toast.makeText(mContext, getString(R.string.demo_info1),
Toast.LENGTH_LONG).show();
} else if (!patchFile.exists()) {
Toast.makeText(mContext, getString(R.string.demo_info2),
Toast.LENGTH_LONG).show();
} else {
new PatchApkTask().execute();
}
}
}); mGithubButton.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
Intent intent = new Intent("android.intent.action.VIEW", Uri.parse("https://github.com/cundong/SmartAppUpdates"));
startActivity(intent);
}
});
} private class PatchApkTask extends AsyncTask<String, Void, Integer> { @Override
protected void onPreExecute() {
super.onPreExecute(); mProgressDialog.show(); mResultView.setText("");
mBeginTime = System.currentTimeMillis();
} @Override
protected Integer doInBackground(String... params) { String oldApkSource = ApkUtils.getSourceApkPath(mContext,
Constants.TEST_PACKAGENAME); if (!TextUtils.isEmpty(oldApkSource)) { int patchResult = PatchUtils.patch(oldApkSource,
Constants.NEW_APK_PATH, Constants.PATCH_PATH); if (patchResult == 0) { String signatureNew = SignUtils
.getUnInstalledApkSignature(Constants.NEW_APK_PATH); String signatureSource = SignUtils
.getInstalledApkSignature(mContext,
Constants.TEST_PACKAGENAME); if (!TextUtils.isEmpty(signatureNew)
&& !TextUtils.isEmpty(signatureSource)
&& signatureNew.equals(signatureSource)) {
return WHAT_SUCCESS;
} else {
return WHAT_FAIL_SING;
}
} else {
return WHAT_FAIL_ERROR;
}
} else {
return WHAT_FAIL_GET_SOURCE;
}
} @Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result); if (mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
} mEndTime = System.currentTimeMillis();
mResultView.setText("耗时: " + (mEndTime - mBeginTime) + "ms"); switch (result) {
case WHAT_SUCCESS: { String text = "新apk已合成成功:" + Constants.NEW_APK_PATH;
showShortToast(text); ApkUtils.installApk(MainActivity.this, Constants.NEW_APK_PATH);
break;
}
case WHAT_FAIL_SING: {
String text = "新apk已合成失败,签名不一致";
showShortToast(text);
break;
}
case WHAT_FAIL_ERROR: {
String text = "新apk已合成失败";
showShortToast(text);
break;
}
case WHAT_FAIL_GET_SOURCE: {
String text = "无法获取packageName为" + Constants.TEST_PACKAGENAME
+ "的源apk文件,只能整包更新了!";
showShortToast(text);
break;
}
}
}
} private void showShortToast(final String text) { Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show();
} static {
System.loadLibrary("ApkPatchLibrary");
}
}

APK 工具类

 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; /**
* 类说明: Apk工具类
*
* @author Cundong
* @date 2013-9-6
* @version 1.0
*/
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/com.sina.weibo-1.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);
}
}

apk 签名信息获取工具类

 import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List; import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.util.DisplayMetrics; /**
* 类说明: apk 签名信息获取工具类
*
* @author Cundong
* @date 2013-9-6
* @version 1.0
*/
public class SignUtils { /**
* 获取未安装Apk的签名
*
* @param apkPath
* @return
*/
public static String getUnInstalledApkSignature(String apkPath) {
String PATH_PackageParser = "android.content.pm.PackageParser"; try {
Class<?> pkgParserCls = Class.forName(PATH_PackageParser);
Class<?>[] typeArgs = new Class[1];
typeArgs[0] = String.class;
Constructor<?> pkgParserCt = pkgParserCls.getConstructor(typeArgs);
Object[] valueArgs = new Object[1];
valueArgs[0] = apkPath;
Object pkgParser = pkgParserCt.newInstance(valueArgs); DisplayMetrics metrics = new DisplayMetrics();
metrics.setToDefaults(); typeArgs = new Class[4];
typeArgs[0] = File.class;
typeArgs[1] = String.class;
typeArgs[2] = DisplayMetrics.class;
typeArgs[3] = Integer.TYPE; Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod(
"parsePackage", typeArgs);
valueArgs = new Object[4];
valueArgs[0] = new File(apkPath);
valueArgs[1] = apkPath;
valueArgs[2] = metrics;
valueArgs[3] = PackageManager.GET_SIGNATURES;
Object pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser,
valueArgs); typeArgs = new Class[2];
typeArgs[0] = pkgParserPkg.getClass();
typeArgs[1] = Integer.TYPE; Method pkgParser_collectCertificatesMtd = pkgParserCls
.getDeclaredMethod("collectCertificates", typeArgs);
valueArgs = new Object[2];
valueArgs[0] = pkgParserPkg;
valueArgs[1] = PackageManager.GET_SIGNATURES;
pkgParser_collectCertificatesMtd.invoke(pkgParser, valueArgs); Field packageInfoFld = pkgParserPkg.getClass().getDeclaredField(
"mSignatures");
Signature[] info = (Signature[]) packageInfoFld.get(pkgParserPkg);
return info[0].toCharsString();
} catch (Exception e) {
e.printStackTrace();
} return null;
} /**
* 获取已安装apk签名
*
* @param context
* @param packageName
* @return
*/
public static String getInstalledApkSignature(Context context,
String packageName) {
PackageManager pm = context.getPackageManager();
List<PackageInfo> apps = pm
.getInstalledPackages(PackageManager.GET_SIGNATURES); Iterator<PackageInfo> iter = apps.iterator();
while (iter.hasNext()) {
PackageInfo packageinfo = iter.next();
String thisName = packageinfo.packageName;
if (thisName.equals(packageName)) {
return packageinfo.signatures[0].toCharsString();
}
} return null;
}
}

最新文章

  1. H3 BPM让天下没有难用的流程之功能介绍
  2. Mac下安装Matlab R2015b
  3. activity与fragment之间传递数据
  4. HDU 5884 Sort -2016 ICPC 青岛赛区网络赛
  5. SharePoint Iframe 报错“此内容不能显示在一个框架中”&lt;续&gt;
  6. Asp.net MVC 3实例学习之ExtShop(四)——完成产品列表页
  7. Javascript&amp;Jquery获取浏览器和屏幕各种高度宽度方法总结及运用
  8. linux命令之uname
  9. VS2010在网络共享目录使用IntelliSense、ipch、sdf和SQL Compact Server相关问题
  10. C++接口的定义与实现的详细过程
  11. Git时光机穿梭之工作区和暂存区
  12. java继承中的初始化顺序
  13. Windows下MongoDB常用命令
  14. JAVA IO分析二:字节数组流、基本数据&amp;对象类型的数据流、打印流
  15. Sqoop-1.4.5用户手册
  16. Sql Server2014数据库清理日志
  17. ASP.NET Core 集成测试中结合 WebApplicationFactory 使用 SQLite 内存数据库
  18. 2018最完整ITTO分节整理指导(PMP项目管理入门必备)
  19. IntelliJ IDEA配置
  20. js运用3

热门文章

  1. vue2.x和vue1.0
  2. VB网络编程中Winsock的使用
  3. 笔记 Bioinformatics Algorithms Chapter1
  4. wx.setStorageSync(KEY,DATA)
  5. Update Node.js Package.json
  6. C#-VS发布网站-准备待发布网站-摘
  7. 《ARM Cortex-M3权威指南》笔记(1)
  8. 【Andorid开发框架学习】之Mina开发之Mina简介
  9. Brain Rules: 12 Principles for Surviving and Thriving at Work, Home, and School
  10. caffe 教程