content: package com.rsen.github.androidutilcode;
  
  import android.annotation.SuppressLint;
  import android.app.Activity;
  import android.app.ActivityManager;
  import android.content.Context;
  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 java.io.File;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.List;
  
  /**
   * <pre>
   *     author: Blankj
   *     blog  : http://blankj.com
   *     time  : 2016/8/2
   *     desc  : App相关工具类
   * </pre>
   */
  public class AppUtils {
  
      private AppUtils() {
          throw new UnsupportedOperationException("u can't instantiate me...");
      }
  
      /**
       * 判断App是否安装
       *
       * @param context     上下文
       * @param packageName 包名
       * @return {@code true}: 已安装<br>{@code false}: 未安装
       */
      public static boolean isInstallApp(Context context, String packageName) {
          return !StringUtils.isSpace(packageName) && IntentUtils.getLaunchAppIntent(context, packageName) != null;
      }
  
      /**
       * 安装App(支持6.0)
       *
       * @param context  上下文
       * @param filePath 文件路径
       */
      public static void installApp(Context context, String filePath) {
          installApp(context, FileUtils.getFileByPath(filePath));
      }
  
      /**
       * 安装App(支持6.0)
       *
       * @param context 上下文
       * @param file    文件
       */
      public static void installApp(Context context, File file) {
          if (!FileUtils.isFileExists(file)) return;
          context.startActivity(IntentUtils.getInstallAppIntent(file));
      }
  
      /**
       * 安装App(支持6.0)
       *
       * @param activity    activity
       * @param filePath    文件路径
       * @param requestCode 请求值
       */
      public static void installApp(Activity activity, String filePath, int requestCode) {
          installApp(activity, FileUtils.getFileByPath(filePath), requestCode);
      }
  
      /**
       * 安装App(支持6.0)
       *
       * @param activity    activity
       * @param file        文件
       * @param requestCode 请求值
       */
      public static void installApp(Activity activity, File file, int requestCode) {
          if (!FileUtils.isFileExists(file)) return;
          activity.startActivityForResult(IntentUtils.getInstallAppIntent(file), requestCode);
      }
  
      /**
       * 静默安装App
       * <p>非root需添加权限 {@code <uses-permission android:name="android.permission.INSTALL_PACKAGES" />}</p>
       *
       * @param context  上下文
       * @param filePath 文件路径
       * @return {@code true}: 安装成功<br>{@code false}: 安装失败
       */
      public static boolean installAppSilent(Context context, String filePath) {
          File file = FileUtils.getFileByPath(filePath);
          if (!FileUtils.isFileExists(file)) return false;
          String command = "LD_LIBRARY_PATH=/vendor/lib:/system/lib pm install " + filePath;
          ShellUtils.CommandResult commandResult = ShellUtils.execCmd(command, !isSystemApp(context), true);
          return commandResult.successMsg != null && commandResult.successMsg.toLowerCase().contains("success");
      }
  
      /**
       * 卸载App
       *
       * @param context     上下文
       * @param packageName 包名
       */
      public static void uninstallApp(Context context, String packageName) {
          if (StringUtils.isSpace(packageName)) return;
          context.startActivity(IntentUtils.getUninstallAppIntent(packageName));
      }
  
      /**
       * 卸载App
       *
       * @param activity    activity
       * @param packageName 包名
       * @param requestCode 请求值
       */
      public static void uninstallApp(Activity activity, String packageName, int requestCode) {
          if (StringUtils.isSpace(packageName)) return;
          activity.startActivityForResult(IntentUtils.getUninstallAppIntent(packageName), requestCode);
      }
  
      /**
       * 静默卸载App
       * <p>非root需添加权限 {@code <uses-permission android:name="android.permission.DELETE_PACKAGES" />}</p>
       *
       * @param context     上下文
       * @param packageName 包名
       * @param isKeepData  是否保留数据
       * @return {@code true}: 卸载成功<br>{@code false}: 卸载成功
       */
      public static boolean uninstallAppSilent(Context context, String packageName, boolean isKeepData) {
          if (StringUtils.isSpace(packageName)) return false;
          String command = "LD_LIBRARY_PATH=/vendor/lib:/system/lib pm uninstall " + (isKeepData ? "-k " : "") + packageName;
          ShellUtils.CommandResult commandResult = ShellUtils.execCmd(command, !isSystemApp(context), true);
          return commandResult.successMsg != null && commandResult.successMsg.toLowerCase().contains("success");
      }
  
      /**
       * 打开App
       *
       * @param context     上下文
       * @param packageName 包名
       */
      public static void launchApp(Context context, String packageName) {
          if (StringUtils.isSpace(packageName)) return;
          context.startActivity(IntentUtils.getLaunchAppIntent(context, packageName));
      }
  
      /**
       * 打开App
       *
       * @param activity    activity
       * @param packageName 包名
       * @param requestCode 请求值
       */
      public static void launchApp(Activity activity, String packageName, int requestCode) {
          if (StringUtils.isSpace(packageName)) return;
          activity.startActivityForResult(IntentUtils.getLaunchAppIntent(activity, packageName), requestCode);
      }
  
      /**
       * 获取App包名
       *
       * @param context 上下文
       * @return App包名
       */
      public static String getAppPackageName(Context context) {
          return context.getPackageName();
      }
  
      /**
       * 获取App具体设置
       *
       * @param context 上下文
       */
      public static void getAppDetailsSettings(Context context) {
          getAppDetailsSettings(context, context.getPackageName());
      }
  
      /**
       * 获取App具体设置
       *
       * @param context     上下文
       * @param packageName 包名
       */
      public static void getAppDetailsSettings(Context context, String packageName) {
          if (StringUtils.isSpace(packageName)) return;
          context.startActivity(IntentUtils.getAppDetailsSettingsIntent(packageName));
      }
  
      /**
       * 获取App名称
       *
       * @param context 上下文
       * @return App名称
       */
      public static String getAppName(Context context) {
          return getAppName(context, context.getPackageName());
      }
  
      /**
       * 获取App名称
       *
       * @param context     上下文
       * @param packageName 包名
       * @return App名称
       */
      public static String getAppName(Context context, String packageName) {
          if (StringUtils.isSpace(packageName)) return null;
          try {
              PackageManager pm = context.getPackageManager();
              PackageInfo pi = pm.getPackageInfo(packageName, 0);
              return pi == null ? null : pi.applicationInfo.loadLabel(pm).toString();
          } catch (PackageManager.NameNotFoundException e) {
              e.printStackTrace();
              return null;
          }
      }
  
      /**
       * 获取App图标
       *
       * @param context 上下文
       * @return App图标
       */
      public static Drawable getAppIcon(Context context) {
          return getAppIcon(context, context.getPackageName());
      }
  
      /**
       * 获取App图标
       *
       * @param context     上下文
       * @param packageName 包名
       * @return App图标
       */
      public static Drawable getAppIcon(Context context, String packageName) {
          if (StringUtils.isSpace(packageName)) return null;
          try {
              PackageManager pm = context.getPackageManager();
              PackageInfo pi = pm.getPackageInfo(packageName, 0);
              return pi == null ? null : pi.applicationInfo.loadIcon(pm);
          } catch (PackageManager.NameNotFoundException e) {
              e.printStackTrace();
              return null;
          }
      }
  
      /**
       * 获取App路径
       *
       * @param context 上下文
       * @return App路径
       */
      public static String getAppPath(Context context) {
          return getAppPath(context, context.getPackageName());
      }
  
      /**
       * 获取App路径
       *
       * @param context     上下文
       * @param packageName 包名
       * @return App路径
       */
      public static String getAppPath(Context context, String packageName) {
          if (StringUtils.isSpace(packageName)) return null;
          try {
              PackageManager pm = context.getPackageManager();
              PackageInfo pi = pm.getPackageInfo(packageName, 0);
              return pi == null ? null : pi.applicationInfo.sourceDir;
          } catch (PackageManager.NameNotFoundException e) {
              e.printStackTrace();
              return null;
          }
      }
  
      /**
       * 获取App版本号
       *
       * @param context 上下文
       * @return App版本号
       */
      public static String getAppVersionName(Context context) {
          return getAppVersionName(context, context.getPackageName());
      }
  
      /**
       * 获取App版本号
       *
       * @param context     上下文
       * @param packageName 包名
       * @return App版本号
       */
      public static String getAppVersionName(Context context, String packageName) {
          if (StringUtils.isSpace(packageName)) return null;
          try {
              PackageManager pm = context.getPackageManager();
              PackageInfo pi = pm.getPackageInfo(packageName, 0);
              return pi == null ? null : pi.versionName;
          } catch (PackageManager.NameNotFoundException e) {
              e.printStackTrace();
              return null;
          }
      }
  
      /**
       * 获取App版本码
       *
       * @param context 上下文
       * @return App版本码
       */
      public static int getAppVersionCode(Context context) {
          return getAppVersionCode(context, context.getPackageName());
      }
  
      /**
       * 获取App版本码
       *
       * @param context     上下文
       * @param packageName 包名
       * @return App版本码
       */
      public static int getAppVersionCode(Context context, String packageName) {
          if (StringUtils.isSpace(packageName)) return -1;
          try {
              PackageManager pm = context.getPackageManager();
              PackageInfo pi = pm.getPackageInfo(packageName, 0);
              return pi == null ? -1 : pi.versionCode;
          } catch (PackageManager.NameNotFoundException e) {
              e.printStackTrace();
              return -1;
          }
      }
  
      /**
       * 判断App是否是系统应用
       *
       * @param context 上下文
       * @return {@code true}: 是<br>{@code false}: 否
       */
      public static boolean isSystemApp(Context context) {
          return isSystemApp(context, context.getPackageName());
      }
  
      /**
       * 判断App是否是系统应用
       *
       * @param context     上下文
       * @param packageName 包名
       * @return {@code true}: 是<br>{@code false}: 否
       */
      public static boolean isSystemApp(Context context, String packageName) {
          if (StringUtils.isSpace(packageName)) return false;
          try {
              PackageManager pm = context.getPackageManager();
              ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
              return ai != null && (ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
          } catch (PackageManager.NameNotFoundException e) {
              e.printStackTrace();
              return false;
          }
      }
  
      /**
       * 判断App是否是Debug版本
       *
       * @param context 上下文
       * @return {@code true}: 是<br>{@code false}: 否
       */
      public static boolean isAppDebug(Context context) {
          return isAppDebug(context, context.getPackageName());
      }
  
      /**
       * 判断App是否是Debug版本
       *
       * @param context     上下文
       * @param packageName 包名
       * @return {@code true}: 是<br>{@code false}: 否
       */
      public static boolean isAppDebug(Context context, String packageName) {
          if (StringUtils.isSpace(packageName)) return false;
          try {
              PackageManager pm = context.getPackageManager();
              ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
              return ai != null && (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
          } catch (PackageManager.NameNotFoundException e) {
              e.printStackTrace();
              return false;
          }
      }
  
      /**
       * 获取App签名
       *
       * @param context 上下文
       * @return App签名
       */
      public static Signature[] getAppSignature(Context context) {
          return getAppSignature(context, context.getPackageName());
      }
  
      /**
       * 获取App签名
       *
       * @param context     上下文
       * @param packageName 包名
       * @return App签名
       */
      @SuppressLint("PackageManagerGetSignatures")
      public static Signature[] getAppSignature(Context context, String packageName) {
          if (StringUtils.isSpace(packageName)) return null;
          try {
              PackageManager pm = context.getPackageManager();
              PackageInfo pi = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
              return pi == null ? null : pi.signatures;
          } catch (PackageManager.NameNotFoundException e) {
              e.printStackTrace();
              return null;
          }
      }
  
      /**
       * 获取应用签名的的SHA1值
       * <p>可据此判断高德，百度地图key是否正确</p>
       *
       * @param context 上下文
       * @return 应用签名的SHA1字符串, 比如：53:FD:54:DC:19:0F:11:AC:B5:22:9E:F1:1A:68:88:1B:8B:E8:54:42
       */
      public static String getAppSignatureSHA1(Context context) {
          return getAppSignatureSHA1(context, context.getPackageName());
      }
  
      /**
       * 获取应用签名的的SHA1值
       * <p>可据此判断高德，百度地图key是否正确</p>
       *
       * @param context     上下文
       * @param packageName 包名
       * @return 应用签名的SHA1字符串, 比如：53:FD:54:DC:19:0F:11:AC:B5:22:9E:F1:1A:68:88:1B:8B:E8:54:42
       */
      public static String getAppSignatureSHA1(Context context, String packageName) {
          Signature[] signature = getAppSignature(context, packageName);
          if (signature == null) return null;
          return EncryptUtils.encryptSHA1ToString(signature[0].toByteArray()).
                  replaceAll("(?<=[0-9A-F]{2})[0-9A-F]{2}", ":$0");
      }
  
      /**
       * 判断App是否处于前台
       *
       * @param context 上下文
       * @return {@code true}: 是<br>{@code false}: 否
       */
      public static boolean isAppForeground(Context context) {
          ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
          List<ActivityManager.RunningAppProcessInfo> infos = manager.getRunningAppProcesses();
          if (infos == null || infos.size() == 0) return false;
          for (ActivityManager.RunningAppProcessInfo info : infos) {
              if (info.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                  return info.processName.equals(context.getPackageName());
              }
          }
          return false;
      }
  
      /**
       * 判断App是否处于前台
       * <p>当不是查看当前App，且SDK >= 22时，
       * 需添加权限 {@code <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>}</p>
       *
       * @param context     上下文
       * @param packageName 包名
       * @return {@code true}: 是<br>{@code false}: 否
       */
      public static boolean isAppForeground(Context context, String packageName) {
          return !StringUtils.isSpace(packageName) && packageName.equals(ProcessUtils.getForegroundProcessName(context));
      }
  
      /**
       * 封装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  isSystem;
  
          public Drawable getIcon() {
              return icon;
          }
  
          public void setIcon(Drawable icon) {
              this.icon = icon;
          }
  
          public boolean isSystem() {
              return isSystem;
          }
  
          public void setSystem(boolean isSystem) {
              this.isSystem = isSystem;
          }
  
          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 版本码
           * @param isSystem    是否系统应用
           */
          public AppInfo(String packageName, String name, Drawable icon, String packagePath,
                         String versionName, int versionCode, boolean isSystem) {
              this.setName(name);
              this.setIcon(icon);
              this.setPackageName(packageName);
              this.setPackagePath(packagePath);
              this.setVersionName(versionName);
              this.setVersionCode(versionCode);
              this.setSystem(isSystem);
          }
  
          @Override
          public String toString() {
              return "App包名：" + getPackageName() + "\n" +
                      "App名称：" + getName() + "\n" +
                      "App图标：" + getIcon() + "\n" +
                      "App路径：" + getPackagePath() + "\n" +
                      "App版本号：" + getVersionName() + "\n" +
                      "App版本码：" + getVersionCode() + "\n" +
                      "是否系统App：" + isSystem() + "\n";
          }
      }
  
      /**
       * 获取App信息
       * <p>AppInfo（名称，图标，包名，版本号，版本Code，是否系统应用）</p>
       *
       * @param context 上下文
       * @return 当前应用的AppInfo
       */
      public static AppInfo getAppInfo(Context context) {
          return getAppInfo(context, context.getPackageName());
      }
  
      /**
       * 获取App信息
       * <p>AppInfo（名称，图标，包名，版本号，版本Code，是否系统应用）</p>
       *
       * @param context     上下文
       * @param packageName 包名
       * @return 当前应用的AppInfo
       */
      public static AppInfo getAppInfo(Context context, String packageName) {
          try {
              PackageManager pm = context.getPackageManager();
              PackageInfo pi = pm.getPackageInfo(packageName, 0);
              return getBean(pm, pi);
          } catch (PackageManager.NameNotFoundException e) {
              e.printStackTrace();
              return null;
          }
      }
  
      /**
       * 得到AppInfo的Bean
       *
       * @param pm 包的管理
       * @param pi 包的信息
       * @return AppInfo类
       */
      private static AppInfo getBean(PackageManager pm, PackageInfo pi) {
          if (pm == null || pi == null) return null;
          ApplicationInfo ai = pi.applicationInfo;
          String packageName = pi.packageName;
          String name = ai.loadLabel(pm).toString();
          Drawable icon = ai.loadIcon(pm);
          String packagePath = ai.sourceDir;
          String versionName = pi.versionName;
          int versionCode = pi.versionCode;
          boolean isSystem = (ApplicationInfo.FLAG_SYSTEM & ai.flags) != 0;
          return new AppInfo(packageName, name, icon, packagePath, versionName, versionCode, isSystem);
      }
  
      /**
       * 获取所有已安装App信息
       * <p>{@link #getBean(PackageManager, PackageInfo)}（名称，图标，包名，包路径，版本号，版本Code，是否系统应用）</p>
       * <p>依赖上面的getBean方法</p>
       *
       * @param context 上下文
       * @return 所有已安装的AppInfo列表
       */
      public static List<AppInfo> getAppsInfo(Context context) {
          List<AppInfo> list = new ArrayList<>();
          PackageManager pm = context.getPackageManager();
          // 获取系统中安装的所有软件信息
          List<PackageInfo> installedPackages = pm.getInstalledPackages(0);
          for (PackageInfo pi : installedPackages) {
              AppInfo ai = getBean(pm, pi);
              if (ai == null) continue;
              list.add(ai);
          }
          return list;
      }
  
      /**
       * 清除App所有数据
       *
       * @param context  上下文
       * @param dirPaths 目录路径
       * @return {@code true}: 成功<br>{@code false}: 失败
       */
      public static boolean cleanAppData(Context context, String... dirPaths) {
          File[] dirs = new File[dirPaths.length];
          int i = 0;
          for (String dirPath : dirPaths) {
              dirs[i++] = new File(dirPath);
          }
          return cleanAppData(context, dirs);
      }
  
      /**
       * 清除App所有数据
       *
       * @param context 上下文
       * @param dirs    目录
       * @return {@code true}: 成功<br>{@code false}: 失败
       */
      public static boolean cleanAppData(Context context, File... dirs) {
          boolean isSuccess = CleanUtils.cleanInternalCache(context);
          isSuccess &= CleanUtils.cleanInternalDbs(context);
          isSuccess &= CleanUtils.cleanInternalSP(context);
          isSuccess &= CleanUtils.cleanInternalFiles(context);
          isSuccess &= CleanUtils.cleanExternalCache(context);
          for (File dir : dirs) {
              isSuccess &= CleanUtils.cleanCustomCache(dir);
          }
          return isSuccess;
      }
  }
  