Android 开发工具类 35_PatchUtils
增量更新工具类【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;
}
}
Android 开发工具类 35_PatchUtils的更多相关文章
- Android开发工具类
7种无须编程的DIY开发工具 你知道几个? 现如今,各种DIY开发工具不断的出现,使得企业和个人在短短几分钟内就能完成应用的创建和发布,大大节省了在时间和资金上的投入.此外,DIY工 具的出现,也帮助 ...
- android开发工具类之获得WIFI IP地址或者手机网络IP
有的时候我们需要获得WIFI的IP地址获得手机网络的IP地址,这是一个工具类,专门解决这个问题,这里需要两个权限: <uses-permission android:name="and ...
- android开发工具类总结(一)
一.日志工具类 Log.java public class L { private L() { /* 不可被实例化 */ throw new UnsupportedOperationException ...
- Android 开发工具类 13_ SaxService
网络 xml 解析方式 package com.example.dashu_saxxml; import java.io.IOException; import java.io.InputStream ...
- Android 开发工具类 06_NetUtils
跟网络相关的工具类: 1.判断网络是否连接: 2.判断是否是 wifi 连接: 3.打开网络设置界面: import android.app.Activity; import android.cont ...
- Android 开发工具类 03_HttpUtils
Http 请求的工具类: 1.异步的 Get 请求: 2.异步的 Post 请求: 3.Get 请求,获得返回数据: 4.向指定 URL 发送 POST方法的请求. import java.io.Bu ...
- Android 开发工具类 19_NetworkStateReceiver
检测网络状态改变类: 1.注册网络状态广播: 2.检查网络状态: 3.注销网络状态广播: 4.获取当前网络状态,true为网络连接成功,否则网络连接失败: 5.注册网络连接观察者: 6.注销网络连接观 ...
- Android 开发工具类 27_多线程下载大文件
多线程下载大文件时序图 FileDownloader.java package com.wangjialin.internet.service.downloader; import java.io.F ...
- Android 开发工具类 12_PullXmlTools
xml 格式数据 <?xml version="1.0" encoding="UTF-8"?> <user-list> <user ...
随机推荐
- css的三种使用方式:行内样式,内嵌样式,外部引用样式
三中的使用方法的简单实例如下: 行内样式: <!doctype html> <html> <head> <meta charset="UTF-8&q ...
- 第84讲:Scala中List和ListBuffer设计实现思考
今天来学习了scala中的list和ListBuffer scala list 内部很多操作是listbuffer做的,因为改变元素,listbuffer非常高效,tl是var类型的 ,但是他属于s ...
- FileZilla_server在Windows和Linnx下的部署安装
1. FileZilla官网下载FileZilla Server服务器,目前最新版本为0.9.53. 2. 安装FileZilla服务器.除以下声明的地方外,其它均采用默认模式,如安装路径等. 2.1 ...
- execl 导入
/** * 导入Excel功能 是把execl表中的数据添加到数据表中 */ public function import(){ if (!empty($_FILES)) { $file = re ...
- Ubuntu12.04搭建自有源
其实,这个工作比较简单,主要两步:apt-mirror和apache.(这里的系统是ubuntu12.04) 1.apt-mirror 1.1 安装 一如既往地简单,直接sudo apt-get in ...
- 关于 cxGrid 的过滤问题
http://bbs.csdn.net/topics/390536919 关于 cxGrid 的过滤问题 [问题点数:20分,结帖人zhengyc653] 不显示删除回复 ...
- 微信内置浏览器私有接口WeixinJSBridge介绍
原文地址:http://www.3lian.com/edu/2015/05-25/216227.html 这篇文章主要介绍了微信内置浏览器私有接口WeixinJSBridge介绍,本文讲解了发送给好友 ...
- Java框架知识点总结
一.Struts1的运行原理 在启动时通过前端总控制器ActionServlet加载struts-config.xml并进行解析,当用户在jsp页面发送请求被struts1的核心控制器ActionSe ...
- 基于opencv3.0下的人脸检测和检测部分的高斯模糊处理
如题 这里将任务分解为三大部分: 1.录播放视频 2.人脸检测 3.部分高斯模糊 其中重点放在人脸检测和部分高斯模糊上 1.录播放视频(以opencv中的VideoCapture类进行实现) 首先罗列 ...
- [UWP开发] 在低版本中使用亚克力刷以及部分高版本控件
写于2018.10.3 仅在我的PC(17763)和WP(Limia 950 XL 15254)上测试过 微软在build 16299中引入了亚克力刷,但是Win10m并没有活那么久,lumia手机在 ...