package com.anyun.exam.lib; import android.Manifest; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.net.Uri; import android.os.Build; import android.provider.Settings; import android.util.Log; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.List; import java.util.Locale; import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; import androidx.core.content.FileProvider; public class InstallUtil { public static final String TAG = InstallUtil.class.getCanonicalName(); private static InstallUtil instance = null; private Context context; public static InstallUtil getInstance(Context context) { if (instance == null) { synchronized (InstallUtil.class) { if (instance == null) { instance = new InstallUtil(context); } } } return instance; } private InstallUtil(Context context) { this.context = context; } public int getVerCode() { int verCode = 0; try { verCode = context.getPackageManager(). getPackageInfo(context.getPackageName(), 0).versionCode; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } Log.d(TAG, "APP 版本 = " + verCode); return verCode; } public String getVerName() { String verName = ""; try { verName = context.getPackageManager(). getPackageInfo(context.getPackageName(), 0).versionName; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return verName; } public String getPackageName() { String name = ""; try { name = context.getPackageManager(). getPackageInfo(context.getPackageName(), 0).packageName; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return name; } public class AppInfo { public String appName=""; public String packageName=""; public String versionName=""; public int versionCode=0; } public AppInfo getAppInfo(String packageName) { List packages = context.getPackageManager().getInstalledPackages(0); for (PackageInfo packageInfo : packages) { if (packageName.equals(packageInfo.packageName)) { AppInfo appInfo = new AppInfo(); appInfo.appName= packageInfo.applicationInfo.loadLabel(context.getPackageManager()).toString(); appInfo.packageName = packageInfo.packageName; appInfo.versionName = packageInfo.versionName; appInfo.versionCode = packageInfo.versionCode; return appInfo; } } return null; } public Signature[] getSignature() { Signature[] signs = null; try { PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); signs = info.signatures; } catch (Exception e) { e.printStackTrace(); } return signs; } public Signature[] getSignature(String archiveFilePath) { Signature[] signs = null; try { PackageInfo info = context.getPackageManager().getPackageArchiveInfo(archiveFilePath, PackageManager.GET_SIGNATURES); signs = info.signatures; } catch (Exception e) { e.printStackTrace(); } return signs; } public String getVersionNameFromApk(Context context, String archiveFilePath) { PackageManager pm = context.getPackageManager(); PackageInfo packInfo = pm.getPackageArchiveInfo(archiveFilePath, PackageManager.GET_ACTIVITIES); return packInfo.versionName; } public int getVersionCodeFromApk(Context context, String archiveFilePath) { PackageManager pm = context.getPackageManager(); PackageInfo packInfo = pm.getPackageArchiveInfo(archiveFilePath, PackageManager.GET_ACTIVITIES); return packInfo.versionCode; } public String getPackageNameFromApk(Context context, String archiveFilePath) { PackageManager pm = context.getPackageManager(); PackageInfo packInfo = pm.getPackageArchiveInfo(archiveFilePath, PackageManager.GET_ACTIVITIES); return packInfo.packageName; } public void InstallApp(String path) { File file = new File(path); if (file.exists() && file.isFile()) { try { Log.d(TAG, "升级app 文件存在 当前ver " + getVerCode() + " 当前Name " + getVerName() + " 目标ver " + getVersionCodeFromApk(context, file.getAbsolutePath()) + " 目标name " + getVersionNameFromApk(context, file.getAbsolutePath())); Signature[] sig = getSignature(); Signature[] sig2 = getSignature(file.getAbsolutePath()); if ( getFingerprint(sig[0], "SHA-1").equals(getFingerprint(sig2[0], "SHA-1"))) { if ( getVerCode() < getVersionCodeFromApk(context, file.getAbsolutePath()) || (getVerCode() == getVersionCodeFromApk(context, file.getAbsolutePath()) && !getVerName().equals(getVersionNameFromApk(context, file.getAbsolutePath())))) { Log.d(TAG, "安装文件 " + file.getAbsolutePath()); String result = execCommand("pm", "install", "-i", getPackageName(), "--user", "0", "-r", "-d", file.getAbsolutePath()); Log.d(TAG, "安装结果 " + result); } else { file.delete(); } } else { file.delete(); } } catch (Exception e) { Log.e(TAG, "安装发生错误 " + e.getMessage()); } } } public void InstallAppNormal(Context context, String path) { File file = new File(path); Log.d(TAG, "ManualInstall " + path); if (file.exists() && file.isFile()) { Signature[] sig = getSignature(); Signature[] sig2 = getSignature(file.getAbsolutePath()); if (getFingerprint(sig[0], "SHA-1").equals(getFingerprint(sig2[0], "SHA-1")) && (getVerCode() < getVersionCodeFromApk(context, file.getAbsolutePath()) || (getVerCode() == getVersionCodeFromApk(context, file.getAbsolutePath()) && !getVerName().equals(getVersionNameFromApk(context, file.getAbsolutePath()))))) { Intent intent = new Intent(Intent.ACTION_VIEW); Uri data; String type = "application/vnd.android.package-archive"; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { data = Uri.fromFile(file); } else { intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); String authority = context.getPackageName() + ".fileProvider"; data = FileProvider.getUriForFile(context, authority, file); } intent.setDataAndType(data, type); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } else { Log.d(TAG, "File illegal"); } } else { Log.d(TAG, "File not exist"); } } public String getFingerprint(Signature signature, String hashAlgorithm) { if (signature == null) { return null; } try { MessageDigest digest = MessageDigest.getInstance(hashAlgorithm); return toHexadecimalString(digest.digest(signature.toByteArray())); } catch(NoSuchAlgorithmException e) { // ignore } return null; } private String toHexadecimalString(byte[] value) { StringBuffer sb = new StringBuffer(); int len = value.length; for (int i = 0; i < len; i++) { int num = ((int) value[i]) & 0xff; if (num < 0x10) { sb.append('0'); } sb.append(Integer.toHexString(num)); if (i < len - 1) { sb.append(':'); } } return sb.toString().toUpperCase(Locale.US); } public String execCommand(String ...command) { java.lang.Process process=null; InputStream errIs=null; InputStream inIs=null; String result=""; try { process = new ProcessBuilder().command(command).start(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int read = -1; errIs=process.getErrorStream(); while((read=errIs.read())!=-1){ baos.write(read); } inIs=process.getInputStream(); while((read=inIs.read())!=-1){ baos.write(read); } result=new String(baos.toByteArray()); if(inIs!=null) inIs.close(); if(errIs!=null) errIs.close(); process.destroy(); } catch (IOException e) { result = e.getMessage(); } return result; } /* private void checkIsAndroidO() { if (Build.VERSION.SDK_INT >= 26) { if (context.getPackageManager().canRequestPackageInstalls()) { mMainPresenter.installApk(); } else { //请求安装未知应用来源的权限 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES},INSTALL_PACKAGES_REQUEST_CODE); } } else { mMainPresenter.installApk(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case INSTALL_PACKAGES_REQUEST_CODE: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { mMainPresenter.installApk(); } else { // 引导用户手动开启安装权限 Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES); startActivityForResult(intent, GET_UNKNOWN_APP_SOURCES); } break; default: break; } }*/ }