博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 开发工具类 35_PatchUtils
阅读量:5120 次
发布时间:2019-06-13

本文共 12394 字,大约阅读时间需要 41 分钟。

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

1 import java.io.File;  2   3 import android.app.Activity;  4 import android.app.ProgressDialog;  5 import android.content.Context;  6 import android.content.Intent;  7 import android.net.Uri;  8 import android.os.AsyncTask;  9 import android.os.Bundle; 10 import android.text.TextUtils; 11 import android.view.View; 12 import android.view.View.OnClickListener; 13 import android.widget.Button; 14 import android.widget.TextView; 15 import android.widget.Toast; 16  17 import com.cundong.utils.PatchUtils; 18 import com.example.test.util.ApkUtils; 19 import com.example.test.util.SignUtils; 20 import com.example.test2.R; 21  22 /** 23  * 类说明: ApkPatchLibrary 使用 Demo 24  *  25  * @author  Cundong 26  * @version 1.5 27  */ 28 public class MainActivity extends Activity { 29  30     // 合成成功 31     private static final int WHAT_SUCCESS = 1; 32  33     // 合成的APK签名和已安装的签名不一致 34     private static final int WHAT_FAIL_SING = -1; 35  36     // 合成失败 37     private static final int WHAT_FAIL_ERROR = -2; 38  39     // 获取源文件失败 40     private static final int WHAT_FAIL_GET_SOURCE = -3; 41  42     private Context mContext = null; 43  44     private ProgressDialog mProgressDialog; 45     private TextView mResultView; 46     private Button mStartButton, mGithubButton; 47  48     private long mBeginTime, mEndTime; 49  50     @Override 51     protected void onCreate(Bundle savedInstanceState) { 52         super.onCreate(savedInstanceState); 53         setContentView(R.layout.activity_main); 54  55         mContext = getApplicationContext(); 56  57         mProgressDialog = new ProgressDialog(this); 58         mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 59         mProgressDialog.setMessage("doing.."); 60         mProgressDialog.setCancelable(false); 61  62         mResultView = (TextView) findViewById(R.id.textview4); 63         mStartButton = (Button) findViewById(R.id.start_btn); 64         mGithubButton = (Button) findViewById(R.id.github_btn); 65  66         mStartButton.setOnClickListener(new OnClickListener() { 67  68             @Override 69             public void onClick(View arg0) { 70  71                 File patchFile = new File(Constants.PATCH_PATH); 72                  73                 if (!ApkUtils.isInstalled(mContext, Constants.TEST_PACKAGENAME)) { 74                     Toast.makeText(mContext, getString(R.string.demo_info1), 75                             Toast.LENGTH_LONG).show(); 76                 } else if (!patchFile.exists()) { 77                     Toast.makeText(mContext, getString(R.string.demo_info2), 78                             Toast.LENGTH_LONG).show(); 79                 } else { 80                     new PatchApkTask().execute(); 81                 } 82             } 83         }); 84  85         mGithubButton.setOnClickListener(new OnClickListener() { 86  87             @Override 88             public void onClick(View v) { 89                 Intent intent = new Intent("android.intent.action.VIEW", Uri.parse("https://github.com/cundong/SmartAppUpdates")); 90                 startActivity(intent); 91             } 92         }); 93     } 94      95     private class PatchApkTask extends AsyncTask
{ 96 97 @Override 98 protected void onPreExecute() { 99 super.onPreExecute();100 101 mProgressDialog.show();102 103 mResultView.setText("");104 mBeginTime = System.currentTimeMillis();105 }106 107 @Override108 protected Integer doInBackground(String... params) {109 110 String oldApkSource = ApkUtils.getSourceApkPath(mContext,111 Constants.TEST_PACKAGENAME);112 113 if (!TextUtils.isEmpty(oldApkSource)) {114 115 int patchResult = PatchUtils.patch(oldApkSource,116 Constants.NEW_APK_PATH, Constants.PATCH_PATH);117 118 if (patchResult == 0) {119 120 String signatureNew = SignUtils121 .getUnInstalledApkSignature(Constants.NEW_APK_PATH);122 123 String signatureSource = SignUtils124 .getInstalledApkSignature(mContext,125 Constants.TEST_PACKAGENAME);126 127 if (!TextUtils.isEmpty(signatureNew)128 && !TextUtils.isEmpty(signatureSource)129 && signatureNew.equals(signatureSource)) {130 return WHAT_SUCCESS;131 } else {132 return WHAT_FAIL_SING;133 }134 } else {135 return WHAT_FAIL_ERROR;136 }137 } else {138 return WHAT_FAIL_GET_SOURCE;139 }140 }141 142 @Override143 protected void onPostExecute(Integer result) {144 super.onPostExecute(result);145 146 if (mProgressDialog.isShowing()) {147 mProgressDialog.dismiss();148 }149 150 mEndTime = System.currentTimeMillis();151 mResultView.setText("耗时: " + (mEndTime - mBeginTime) + "ms");152 153 switch (result) {154 case WHAT_SUCCESS: {155 156 String text = "新apk已合成成功:" + Constants.NEW_APK_PATH;157 showShortToast(text);158 159 ApkUtils.installApk(MainActivity.this, Constants.NEW_APK_PATH);160 break;161 }162 case WHAT_FAIL_SING: {163 String text = "新apk已合成失败,签名不一致";164 showShortToast(text);165 break;166 }167 case WHAT_FAIL_ERROR: {168 String text = "新apk已合成失败";169 showShortToast(text);170 break;171 }172 case WHAT_FAIL_GET_SOURCE: {173 String text = "无法获取packageName为" + Constants.TEST_PACKAGENAME174 + "的源apk文件,只能整包更新了!";175 showShortToast(text);176 break;177 }178 }179 }180 }181 182 private void showShortToast(final String text) {183 184 Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show();185 }186 187 static {188 System.loadLibrary("ApkPatchLibrary");189 }190 }

APK 工具类

1 import android.content.Context; 2 import android.content.Intent; 3 import android.content.pm.ApplicationInfo; 4 import android.content.pm.PackageManager; 5 import android.content.pm.PackageManager.NameNotFoundException; 6 import android.net.Uri; 7 import android.text.TextUtils; 8  9 /**10  * 类说明:  Apk工具类11  * 12  * @author     Cundong13  * @date     2013-9-614  * @version 1.015  */16 public class ApkUtils {17 18     public static boolean isInstalled(Context context, String packageName) {19         PackageManager pm = context.getPackageManager();20         boolean installed = false;21         try {22             pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);23             installed = true;24         } catch (Exception e) {25             e.printStackTrace();26         }27 28         return installed;29     }30 31     /**32      * 获取已安装Apk文件的源Apk文件33      * 如:/data/app/com.sina.weibo-1.apk34      * 35      * @param context36      * @param packageName37      * @return38      */39     public static String getSourceApkPath(Context context, String packageName) {40         if (TextUtils.isEmpty(packageName))41             return null;42 43         try {44             ApplicationInfo appInfo = context.getPackageManager()45                     .getApplicationInfo(packageName, 0);46             return appInfo.sourceDir;47         } catch (NameNotFoundException e) {48             e.printStackTrace();49         }50 51         return null;52     }53 54     /**55      * 安装Apk56      * 57      * @param context58      * @param apkPath59      */60     public static void installApk(Context context, String apkPath) {61 62         Intent intent = new Intent(Intent.ACTION_VIEW);63         intent.setDataAndType(Uri.parse("file://" + apkPath),64                 "application/vnd.android.package-archive");65 66         context.startActivity(intent);67     }68 }

apk 签名信息获取工具类

1 import java.io.File;  2 import java.lang.reflect.Constructor;  3 import java.lang.reflect.Field;  4 import java.lang.reflect.Method;  5 import java.util.Iterator;  6 import java.util.List;  7   8 import android.content.Context;  9 import android.content.pm.PackageInfo; 10 import android.content.pm.PackageManager; 11 import android.content.pm.Signature; 12 import android.util.DisplayMetrics; 13  14 /** 15  * 类说明:  apk 签名信息获取工具类 16  *  17  * @author     Cundong 18  * @date     2013-9-6 19  * @version 1.0 20  */ 21 public class SignUtils { 22  23     /** 24      * 获取未安装Apk的签名 25      *  26      * @param apkPath 27      * @return 28      */ 29     public static String getUnInstalledApkSignature(String apkPath) { 30         String PATH_PackageParser = "android.content.pm.PackageParser"; 31  32         try { 33             Class
pkgParserCls = Class.forName(PATH_PackageParser); 34 Class
[] typeArgs = new Class[1]; 35 typeArgs[0] = String.class; 36 Constructor
pkgParserCt = pkgParserCls.getConstructor(typeArgs); 37 Object[] valueArgs = new Object[1]; 38 valueArgs[0] = apkPath; 39 Object pkgParser = pkgParserCt.newInstance(valueArgs); 40 41 DisplayMetrics metrics = new DisplayMetrics(); 42 metrics.setToDefaults(); 43 44 typeArgs = new Class[4]; 45 typeArgs[0] = File.class; 46 typeArgs[1] = String.class; 47 typeArgs[2] = DisplayMetrics.class; 48 typeArgs[3] = Integer.TYPE; 49 50 Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod( 51 "parsePackage", typeArgs); 52 valueArgs = new Object[4]; 53 valueArgs[0] = new File(apkPath); 54 valueArgs[1] = apkPath; 55 valueArgs[2] = metrics; 56 valueArgs[3] = PackageManager.GET_SIGNATURES; 57 Object pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser, 58 valueArgs); 59 60 typeArgs = new Class[2]; 61 typeArgs[0] = pkgParserPkg.getClass(); 62 typeArgs[1] = Integer.TYPE; 63 64 Method pkgParser_collectCertificatesMtd = pkgParserCls 65 .getDeclaredMethod("collectCertificates", typeArgs); 66 valueArgs = new Object[2]; 67 valueArgs[0] = pkgParserPkg; 68 valueArgs[1] = PackageManager.GET_SIGNATURES; 69 pkgParser_collectCertificatesMtd.invoke(pkgParser, valueArgs); 70 71 Field packageInfoFld = pkgParserPkg.getClass().getDeclaredField( 72 "mSignatures"); 73 Signature[] info = (Signature[]) packageInfoFld.get(pkgParserPkg); 74 return info[0].toCharsString(); 75 } catch (Exception e) { 76 e.printStackTrace(); 77 } 78 79 return null; 80 } 81 82 /** 83 * 获取已安装apk签名 84 * 85 * @param context 86 * @param packageName 87 * @return 88 */ 89 public static String getInstalledApkSignature(Context context, 90 String packageName) { 91 PackageManager pm = context.getPackageManager(); 92 List
apps = pm 93 .getInstalledPackages(PackageManager.GET_SIGNATURES); 94 95 Iterator
iter = apps.iterator(); 96 while (iter.hasNext()) { 97 PackageInfo packageinfo = iter.next(); 98 String thisName = packageinfo.packageName; 99 if (thisName.equals(packageName)) {100 return packageinfo.signatures[0].toCharsString();101 }102 }103 104 return null;105 }106 }

 

转载于:https://www.cnblogs.com/renzimu/p/4720597.html

你可能感兴趣的文章
关于PHP会话:session和cookie
查看>>
STM32F10x_RTC秒中断
查看>>
display:none和visiblity:hidden区别
查看>>
C#double转化成字符串 保留小数位数, 不以科学计数法的形式出现。
查看>>
SpringMVC学习总结(三)——Controller接口详解(1)
查看>>
牛的障碍Cow Steeplechase
查看>>
Zookeeper选举算法原理
查看>>
嵌入式成长轨迹52 【Zigbee项目】【CC2430基础实验】【在PC用串口收数并发数】...
查看>>
3月29日AM
查看>>
利用IP地址查询接口来查询IP归属地
查看>>
HTML元素定义 ID,Class,Style的优先级
查看>>
【实数二分/前缀和维护】Best Cow Fences
查看>>
构造者模式
查看>>
浮点数转化为字符串
查看>>
http和https的区别
查看>>
Hbuild在线云ios打包失败,提示BuildConfigure Failed 31013 App Store 图标 未找到 解决方法...
查看>>
找到树中指定id的所有父节点
查看>>
今天新开通了博客
查看>>
Linux命令应用大词典-第4章 目录和文件操作
查看>>
A + B Problem II
查看>>