package com.hotpatch; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.os.Build; import android.text.TextUtils; import android.util.DisplayMetrics; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.math.BigInteger; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Iterator; import java.util.List; public class Utils { /** * Get the Signature of apk file which is not installed. * * @param apkPath * @return */ public static String getApkSignature(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; Object[] valueArgs = new Object[1]; valueArgs[0] = apkPath; Object pkgParser; if (Build.VERSION.SDK_INT > 19) { pkgParser = pkgParserCls.newInstance(); } else { Constructor constructor = pkgParserCls.getConstructor(typeArgs); pkgParser = constructor.newInstance(valueArgs); } DisplayMetrics metrics = new DisplayMetrics(); metrics.setToDefaults(); Object pkgParserPkg = null; if (Build.VERSION.SDK_INT > 19) { typeArgs = new Class[2]; typeArgs[0] = File.class; typeArgs[1] = int.class; Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod( "parsePackage", typeArgs); pkgParser_parsePackageMtd.setAccessible(true); valueArgs = new Object[2]; valueArgs[0] = new File(apkPath); valueArgs[1] = PackageManager.GET_SIGNATURES; pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser, valueArgs); } else { typeArgs = new Class[4]; typeArgs[0] = File.class; typeArgs[1] = String.class; typeArgs[2] = DisplayMetrics.class; typeArgs[3] = int.class; Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod( "parsePackage", typeArgs); pkgParser_parsePackageMtd.setAccessible(true); valueArgs = new Object[4]; valueArgs[0] = new File(apkPath); valueArgs[1] = apkPath; valueArgs[2] = metrics; valueArgs[3] = PackageManager.GET_SIGNATURES; pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser, valueArgs); } typeArgs = new Class[2]; typeArgs[0] = pkgParserPkg.getClass(); typeArgs[1] = int.class; 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; } /** * Get the Signature of the apk file which package name is @param packageName * * @param context * @param packageName * @return packageSignatrue */ public static String getInstallPackageSignature(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; } public static String getMd5ByFile(File file) { String value = null; FileInputStream in=null; try { in = new FileInputStream(file); MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length()); MessageDigest md5 = MessageDigest.getInstance("MD5"); md5.update(byteBuffer); BigInteger bi = new BigInteger(1, md5.digest()); value = bi.toString(16); } catch (Exception e) { e.printStackTrace(); } finally { if (null != in) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } return value; } public static String md5(String string) { byte[] hash; try { hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8")); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("Huh, MD5 should be supported?", e); } catch (UnsupportedEncodingException e) { throw new RuntimeException("Huh, UTF-8 should be supported?", e); } StringBuilder hex = new StringBuilder(hash.length * 2); for (byte b : hash) { if ((b & 0xFF) < 0x10) hex.append("0"); hex.append(Integer.toHexString(b & 0xFF)); } return hex.toString(); } public static String getCacheApkFilePath(Context ctx,String fileUrl){ return ctx.getExternalCacheDir()+"/"+md5(fileUrl)+".apk"; } /** * * Compare the patch apk to the apk which package name is ctx.getPackageName() * @param ctx * @param apkFile the patch apk * @return the result of compare * **/ public static boolean isSignEqual(Context ctx,String apkFile){ String packageSign=getInstallPackageSignature(ctx,ctx.getPackageName()); String apkFileSign=getApkSignature(apkFile); return TextUtils.equals(packageSign,apkFileSign); } public static String getVersionName(Context context) { try { PackageManager packageManager = context.getPackageManager(); PackageInfo packInfo = packageManager.getPackageInfo(context.getPackageName(), 0); String version =String.valueOf(packInfo.versionName); return version; } catch (Exception e) { e.printStackTrace(); } return null; } }