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;
}
}