标签:
增量更新工具类【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 }
标签:
原文地址:http://www.cnblogs.com/renzimu/p/4720597.html