zoukankan      html  css  js  c++  java
  • Android 开发工具类 35_PatchUtils

    增量更新工具类【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<String, Void, Integer> {
     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         @Override
    108         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 = SignUtils
    121                             .getUnInstalledApkSignature(Constants.NEW_APK_PATH);
    122 
    123                     String signatureSource = SignUtils
    124                             .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         @Override
    143         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_PACKAGENAME
    174                             + "的源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     Cundong
    13  * @date     2013-9-6
    14  * @version 1.0
    15  */
    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.apk
    34      * 
    35      * @param context
    36      * @param packageName
    37      * @return
    38      */
    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      * 安装Apk
    56      * 
    57      * @param context
    58      * @param apkPath
    59      */
    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<PackageInfo> apps = pm
     93                 .getInstalledPackages(PackageManager.GET_SIGNATURES);
     94 
     95         Iterator<PackageInfo> 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 }
  • 相关阅读:
    java图书管理系统界面版本+mysql数据库
    java数组实现的超市管理系统(控制台)
    Action<T>和Func<T>委托事例
    简单的委托示例
    使用静态方法CreateInstance()创建数组
    Span复习
    与预定义类型的用户类型强制转换
    实现自定义的索引运算符
    比较运算符的重载
    算术运算符的重载
  • 原文地址:https://www.cnblogs.com/renzimu/p/4720597.html
Copyright © 2011-2022 走看看