package com.xjf.repository.utils; import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.text.TextUtils; import android.view.View; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileFilter; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.security.MessageDigest; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import javax.security.auth.x500.X500Principal; /** * ----------------------------------------------------------------- * User:xijiufu * Email:xjfsml@163.com * Version:1.0 * Time:2017/4/18--0:45 * Function: app操作工具 * ModifyHistory: * ----------------------------------------------------------------- */ public class AppUtils { private static final boolean DEBUG = true; private AppUtils() { throw new UnsupportedOperationException("u can't fuck me..."); } /** * 安装App * <p>根据路径安装App</p> * * @param context 上下文 * @param filePath 文件路径 */ public static void installApp(Context context, String filePath) { installApp(context, new File(filePath)); } /** * 安装App * <p>根据文件安装App</p> * * @param context 上下文 * @param file 文件 */ public static void installApp(Context context, File file) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } /** * 卸载指定包名的App * * @param context 上下文 * @param packageName 包名 */ public void uninstallApp(Context context, String packageName) { Intent intent = new Intent(Intent.ACTION_DELETE); intent.setData(Uri.parse("package:" + packageName)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } /** * 封装App信息的Bean类 */ public static class AppInfo { private String name; private Drawable icon; private String packageName; private String packagePath; private String versionName; private int versionCode; private boolean isSD; private boolean isUser; public Drawable getIcon() { return icon; } public void setIcon(Drawable icon) { this.icon = icon; } public boolean isSD() { return isSD; } public void setSD(boolean SD) { isSD = SD; } public boolean isUser() { return isUser; } public void setUser(boolean user) { isUser = user; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPackageName() { return packageName; } public void setPackageName(String packagName) { this.packageName = packagName; } public String getPackagePath() { return packagePath; } public void setPackagePath(String packagePath) { this.packagePath = packagePath; } public int getVersionCode() { return versionCode; } public void setVersionCode(int versionCode) { this.versionCode = versionCode; } public String getVersionName() { return versionName; } public void setVersionName(String versionName) { this.versionName = versionName; } /** * @param name 名称 * @param icon 图标 * @param packageName 包名 * @param packagePath 包路径 * @param versionName 版本号 * @param versionCode 版本Code * @param isSD 是否安装在SD卡 * @param isUser 是否是用户程序 */ public AppInfo(String name, Drawable icon, String packageName, String packagePath, String versionName, int versionCode, boolean isSD, boolean isUser) { this.setName(name); this.setIcon(icon); this.setPackageName(packageName); this.setPackagePath(packagePath); this.setVersionName(versionName); this.setVersionCode(versionCode); this.setSD(isSD); this.setUser(isUser); } } /** * 获取当前App信息 * <p>AppInfo(名称,图标,包名,版本号,版本Code,是否安装在SD卡,是否是用户程序)</p> * * @param context 上下文 * @return 当前应用的AppInfo */ public static AppInfo getAppInfo(Context context) { PackageManager pm = context.getPackageManager(); PackageInfo pi = null; try { pi = pm.getPackageInfo(context.getApplicationContext().getPackageName(), 0); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return pi != null ? getBean(pm, pi) : null; } /** * 得到AppInfo的Bean * * @param pm 包的管理 * @param pi 包的信息 * @return AppInfo类 */ private static AppInfo getBean(PackageManager pm, PackageInfo pi) { ApplicationInfo ai = pi.applicationInfo; String name = ai.loadLabel(pm).toString(); Drawable icon = ai.loadIcon(pm); String packageName = pi.packageName; String packagePath = ai.sourceDir; String versionName = pi.versionName; int versionCode = pi.versionCode; boolean isSD = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM; boolean isUser = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != ApplicationInfo.FLAG_SYSTEM; return new AppInfo(name, icon, packageName, packagePath, versionName, versionCode, isSD, isUser); } /** * 获取所有已安装App信息 * <p>{@link #getBean(PackageManager, PackageInfo)}(名称,图标,包名,包路径,版本号,版本Code,是否安装在SD卡,是否是用户程序)</p> * <p>依赖上面的getBean方法</p> * * @param context 上下文 * @return 所有已安装的AppInfo列表 */ public static List<AppInfo> getAllAppsInfo(Context context) { List<AppInfo> list = new ArrayList<>(); PackageManager pm = context.getPackageManager(); // 获取系统中安装的所有软件信息 List<PackageInfo> installedPackages = pm.getInstalledPackages(0); for (PackageInfo pi : installedPackages) { if (pi != null) { list.add(getBean(pm, pi)); } } return list; } /** * 根据包名获取意图 * * @param context 上下文 * @param packageName 包名 * @return 意图 */ private static Intent getIntentByPackageName(Context context, String packageName) { return context.getPackageManager().getLaunchIntentForPackage(packageName); } /** * 根据包名判断App是否安装 * * @param context 上下文 * @param packageName 包名 * @return {@code true}: 已安装<br>{@code false}: 未安装 */ public static boolean isInstallApp(Context context, String packageName) { return getIntentByPackageName(context, packageName) != null; } /** * 打开指定包名的App * * @param context 上下文 * @param packageName 包名 * @return {@code true}: 打开成功<br>{@code false}: 打开失败 */ public static boolean openAppByPackageName(Context context, String packageName) { Intent intent = getIntentByPackageName(context, packageName); if (intent != null) { context.startActivity(intent); return true; } return false; } /** * 打开指定包名的App应用信息界面 * * @param context 上下文 * @param packageName 包名 */ public static void openAppInfo(Context context, String packageName) { Intent intent = new Intent(); intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); intent.setData(Uri.parse("package:" + packageName)); context.startActivity(intent); } /** * 可用来做App信息分享 * * @param context 上下文 * @param info 分享信息 */ public static void shareAppInfo(Context context, String info) { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT, info); context.startActivity(intent); } /** * 判断当前App处于前台还是后台 * <p>需添加权限 {@code <uses-permission android:name="android.permission.GET_TASKS"/>}</p> * <p>并且必须是系统应用该方法才有效</p> * * @param context 上下文 * @return {@code true}: 后台<br>{@code false}: 前台 */ public static boolean isAppBackground(Context context) { ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); @SuppressWarnings("deprecation") List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1); if (!tasks.isEmpty()) { ComponentName topActivity = tasks.get(0).topActivity; if (!topActivity.getPackageName().equals(context.getPackageName())) { return true; } } return false; } /** * 获取application中指定的meta-data * * @return 如果没有获取成功(没有对应值,或者异常),则返回值为空 */ public static String getAppMetaData(Context ctx, String key) { if (ctx == null || TextUtils.isEmpty(key)) { return null; } String resultData = null; try { PackageManager packageManager = ctx.getPackageManager(); if (packageManager != null) { ApplicationInfo applicationInfo = packageManager.getApplicationInfo(ctx.getPackageName(), PackageManager.GET_META_DATA); if (applicationInfo != null) { if (applicationInfo.metaData != null) { resultData = applicationInfo.metaData.getString(key); } } } } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return resultData; } /** * 统一设置点击事件 * * @param listener * @param views */ public static void setClick(View.OnClickListener listener, View... views) { for (View v : views) { v.setOnClickListener(listener); } } /** * 得到软件版本号 * * @param context 上下文 * @return 当前版本Code */ public static int getVerCode(Context context) { int verCode = -1; try { String packageName = context.getPackageName(); verCode = context.getPackageManager() .getPackageInfo(packageName, 0).versionCode; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return verCode; } /** * 获取应用运行的最大内存 * * @return 最大内存 */ public static long getMaxMemory() { return Runtime.getRuntime().maxMemory() / 1024; } /** * 得到软件显示版本信息 * * @param context 上下文 * @return 当前版本信息 */ public static String getVerName(Context context) { String verName = ""; try { String packageName = context.getPackageName(); verName = context.getPackageManager() .getPackageInfo(packageName, 0).versionName; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return verName; } /** * 安装apk * * @param context 上下文 * @param file APK文件 */ public static void installApk(Context context, File file) { Intent intent = new Intent(); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setAction(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); context.startActivity(intent); } /** * 安装apk * * @param context 上下文 * @param file APK文件uri */ public static void installApk(Context context, Uri file) { Intent intent = new Intent(); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setAction(Intent.ACTION_VIEW); intent.setDataAndType(file, "application/vnd.android.package-archive"); context.startActivity(intent); } /** * 卸载apk * * @param context 上下文 * @param packageName 包名 */ public static void uninstallApk(Context context, String packageName) { Intent intent = new Intent(Intent.ACTION_DELETE); Uri packageURI = Uri.parse("package:" + packageName); intent.setData(packageURI); context.startActivity(intent); } /** * 检测服务是否运行 * * @param context 上下文 * @param className 类名 * @return 是否运行的状态 */ public static boolean isServiceRunning(Context context, String className) { boolean isRunning = false; ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningServiceInfo> servicesList = activityManager.getRunningServices(Integer.MAX_VALUE); for (ActivityManager.RunningServiceInfo si : servicesList) { if (className.equals(si.service.getClassName())) { isRunning = true; } } return isRunning; } /** * 获取手机厂商与型号 * * @return */ public static String getPhoneModel() { return android.os.Build.MANUFACTURER + "-----" + android.os.Build.MODEL + "-----" + android.os.Build.VERSION.RELEASE; } /** * 获取手机品牌 * * @return */ public static String getPhoneName() { return Build.MANUFACTURER; } /** * 获取手机品牌型号 * * @return */ public static String getPhoneVersion() { return Build.MODEL; } /** * 获取手机系统版本号 * * @return */ public static String getPhoneSystemVersion() { return Build.VERSION.RELEASE; } /** * 针对小米手机单独处理 判断是否小米手机 初始化推送的地方都判断是否是小米手机 * * @return */ public static boolean isXiaoMiOS() { String phoneName = getPhoneName(); if (phoneName.equals("Xiaomi")) { return true; } return false; } /** * 停止运行服务 * * @param context 上下文 * @param className 类名 * @return 是否执行成功 */ public static boolean stopRunningService(Context context, String className) { Intent intent_service = null; boolean ret = false; try { intent_service = new Intent(context, Class.forName(className)); } catch (Exception e) { e.printStackTrace(); } if (intent_service != null) { ret = context.stopService(intent_service); } return ret; } /** * 得到CPU核心数 * * @return CPU核心数 */ public static int getNumCores() { try { File dir = new File("/sys/devices/system/cpu/"); File[] files = dir.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { if (Pattern.matches("cpu[0-9]", pathname.getName())) { return true; } return false; } }); return files.length; } catch (Exception e) { return 1; } } /** * whether this process is named with processName * * @param context 上下文 * @param processName 进程名 * @return 是否含有当前的进程 */ public static boolean isNamedProcess(Context context, String processName) { if (context == null || TextUtils.isEmpty(processName)) { return false; } int pid = android.os.Process.myPid(); ActivityManager manager = (ActivityManager) context.getSystemService( Context.ACTIVITY_SERVICE); List<ActivityManager.RunningAppProcessInfo> processInfoList = manager.getRunningAppProcesses(); if (processInfoList == null) { return true; } for (ActivityManager.RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) { if (processInfo.pid == pid && processName.equalsIgnoreCase(processInfo.processName)) { return true; } } return false; } /** * whether application is in background * <ul> * <li>need use permission android.permission.GET_TASKS in Manifest.xml</li> * </ul> * * @param context 上下文 * @return if application is in background return true, otherwise return * false */ public static boolean isApplicationInBackground(Context context) { ActivityManager am = (ActivityManager) context.getSystemService( Context.ACTIVITY_SERVICE); List<ActivityManager.RunningTaskInfo> taskList = am.getRunningTasks(1); if (taskList != null && !taskList.isEmpty()) { ComponentName topActivity = taskList.get(0).topActivity; if (topActivity != null && !topActivity.getPackageName() .equals(context.getPackageName())) { return true; } } return false; } /** * 获取应用签名 * * @param context 上下文 * @param pkgName 包名 * @return 返回应用的签名 */ public static String getSign(Context context, String pkgName) { try { PackageInfo pis = context.getPackageManager() .getPackageInfo(pkgName, PackageManager.GET_SIGNATURES); return hexdigest(pis.signatures[0].toByteArray()); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); return null; } } /** * 将签名字符串转换成需要的32位签名 * * @param paramArrayOfByte 签名byte数组 * @return 32位签名字符串 */ private static String hexdigest(byte[] paramArrayOfByte) { final char[] hexDigits = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102}; try { MessageDigest localMessageDigest = MessageDigest.getInstance("MD5"); localMessageDigest.update(paramArrayOfByte); byte[] arrayOfByte = localMessageDigest.digest(); char[] arrayOfChar = new char[32]; for (int i = 0, j = 0; ; i++, j++) { if (i >= 16) { return new String(arrayOfChar); } int k = arrayOfByte[i]; arrayOfChar[j] = hexDigits[(0xF & k >>> 4)]; arrayOfChar[++j] = hexDigits[(k & 0xF)]; } } catch (Exception e) { e.printStackTrace(); } return ""; } /** * 清理后台进程与服务 * * @param context 应用上下文对象context * @return 被清理的数量 */ public static int gc(Context context) { long i = getDeviceUsableMemory(context); int count = 0; // 清理掉的进程数 ActivityManager am = (ActivityManager) context.getSystemService( Context.ACTIVITY_SERVICE); // 获取正在运行的service列表 List<ActivityManager.RunningServiceInfo> serviceList = am.getRunningServices(100); if (serviceList != null) { for (ActivityManager.RunningServiceInfo service : serviceList) { if (service.pid == android.os.Process.myPid()) continue; try { android.os.Process.killProcess(service.pid); count++; } catch (Exception e) { e.getStackTrace(); } } } // 获取正在运行的进程列表 List<ActivityManager.RunningAppProcessInfo> processList = am.getRunningAppProcesses(); if (processList != null) { for (ActivityManager.RunningAppProcessInfo process : processList) { // 一般数值大于RunningAppProcessInfo.IMPORTANCE_SERVICE的进程都长时间没用或者空进程了 // 一般数值大于RunningAppProcessInfo.IMPORTANCE_VISIBLE的进程都是非可见进程,也就是在后台运行着 if (process.importance > ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) { // pkgList 得到该进程下运行的包名 String[] pkgList = process.pkgList; for (String pkgName : pkgList) { if (DEBUG) { } try { am.killBackgroundProcesses(pkgName); count++; } catch (Exception e) { // 防止意外发生 e.getStackTrace(); } } } } } if (DEBUG) { } return count; } /** * 获取设备的可用内存大小 * * @param context 应用上下文对象context * @return 当前内存大小 */ public static int getDeviceUsableMemory(Context context) { ActivityManager am = (ActivityManager) context.getSystemService( Context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo(); am.getMemoryInfo(mi); // 返回当前系统的可用内存 return (int) (mi.availMem / (1024 * 1024)); } /** * 获取系统中所有的应用 * * @param context 上下文 * @return 应用信息List */ public static List<PackageInfo> getAllApps(Context context) { List<PackageInfo> apps = new ArrayList<PackageInfo>(); PackageManager pManager = context.getPackageManager(); List<PackageInfo> paklist = pManager.getInstalledPackages(0); for (int i = 0; i < paklist.size(); i++) { PackageInfo pak = paklist.get(i); if ((pak.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) <= 0) { // customs applications apps.add(pak); } } return apps; } /** * 获取手机系统SDK版本 * * @return 如API 17 则返回 17 */ public static int getSDKVersion() { return android.os.Build.VERSION.SDK_INT; } /** * 是否Dalvik模式 * * @return 结果 */ public static boolean isDalvik() { return "Dalvik".equals(getCurrentRuntimeValue()); } /** * 是否ART模式 * * @return 结果 */ public static boolean isART() { String currentRuntime = getCurrentRuntimeValue(); return "ART".equals(currentRuntime) || "ART debug build".equals(currentRuntime); } /** * 获取手机当前的Runtime * * @return 正常情况下可能取值Dalvik, ART, ART debug build; */ public static String getCurrentRuntimeValue() { try { Class<?> systemProperties = Class.forName( "android.os.SystemProperties"); try { Method get = systemProperties.getMethod("get", String.class, String.class); if (get == null) { return "WTF?!"; } try { final String value = (String) get.invoke(systemProperties, "persist.sys.dalvik.vm.lib", /* Assuming default is */"Dalvik"); if ("libdvm.so".equals(value)) { return "Dalvik"; } else if ("libart.so".equals(value)) { return "ART"; } else if ("libartd.so".equals(value)) { return "ART debug build"; } return value; } catch (IllegalAccessException e) { return "IllegalAccessException"; } catch (IllegalArgumentException e) { return "IllegalArgumentException"; } catch (InvocationTargetException e) { return "InvocationTargetException"; } } catch (NoSuchMethodException e) { return "SystemProperties.get(String key, String def) method is not found"; } } catch (ClassNotFoundException e) { return "SystemProperties class is not found"; } } private final static X500Principal DEBUG_DN = new X500Principal( "CN=Android Debug,O=Android,C=US"); /** * 检测当前应用是否是Debug版本 * * @param ctx 上下文 * @return 是否是Debug版本 */ public static boolean isDebuggable(Context ctx) { boolean debuggable = false; try { PackageInfo pinfo = ctx.getPackageManager() .getPackageInfo(ctx.getPackageName(), PackageManager.GET_SIGNATURES); Signature signatures[] = pinfo.signatures; for (int i = 0; i < signatures.length; i++) { CertificateFactory cf = CertificateFactory.getInstance("X.509"); ByteArrayInputStream stream = new ByteArrayInputStream( signatures[i].toByteArray()); X509Certificate cert = (X509Certificate) cf.generateCertificate( stream); debuggable = cert.getSubjectX500Principal().equals(DEBUG_DN); if (debuggable) break; } } catch (PackageManager.NameNotFoundException e) { } catch (CertificateException e) { } return debuggable; } /** * 比较版本号的大小,前者大则返回一个正数,后者大返回一个负数,相等则返回0 支持4.1.2,4.1.23.4.1.rc111这种形式 * * @param version1 * @param version2 * @return */ public static int compareVersion(String version1, String version2) throws Exception { if (version1 == null || version2 == null) { throw new Exception("compareVersion error:illegal params."); } String[] versionArray1 = version1.split("\\.");//注意此处为正则匹配,不能用"."; String[] versionArray2 = version2.split("\\."); int idx = 0; int minLength = Math.min(versionArray1.length, versionArray2.length);//取最小长度值 int diff = 0; while (idx < minLength && (diff = versionArray1[idx].length() - versionArray2[idx].length()) == 0//先比较长度 && (diff = versionArray1[idx].compareTo(versionArray2[idx])) == 0) {//再比较字符 ++idx; } //如果已经分出大小,则直接返回,如果未分出大小,则再比较位数,有子版本的为大; diff = (diff != 0) ? diff : versionArray1.length - versionArray2.length; return diff; } }