package com.github.lazylibrary.util; /** * Copyright 2014 Zhenguo Jin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ 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 android.app.ActivityManager; import android.app.ActivityManager.MemoryInfo; import android.app.ActivityManager.RunningAppProcessInfo; import android.app.ActivityManager.RunningServiceInfo; import android.app.ActivityManager.RunningTaskInfo; 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.PackageManager.NameNotFoundException; import android.content.pm.Signature; import android.net.Uri; import android.text.TextUtils; import javax.security.auth.x500.X500Principal; /** * APP工具类 * APP相关信息工具类。获取版本信息 * * @author jingle1267@163.com */ public final class AppUtils { private static final boolean DEBUG = true; private static final String TAG = "AppUtils"; /** * Don't let anyone instantiate this class. */ private AppUtils() { throw new Error("Do not need instantiate!"); } /** * 得到软件版本号 * * @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 * Android 7.0 或更高版本的应用私有目录被限制访问 * @param context 上下文 * @param file APK文件 * @paras authority provider->authority属性 */ public void installApk(Context context, File file,String authority) { Intent intent = new Intent(); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setAction(Intent.ACTION_VIEW); intent.setDataAndType(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N ? FileProvider.getUriForFile(context,authority,file): 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 servicesList = activityManager.getRunningServices(Integer.MAX_VALUE); for (RunningServiceInfo si : servicesList) { if (className.equals(si.service.getClassName())) { isRunning = true; } } return isRunning; } /** * 停止运行服务 * * @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 processInfoList = manager.getRunningAppProcesses(); if (processInfoList == null) { return true; } for (RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) { if (processInfo.pid == pid && processName.equalsIgnoreCase(processInfo.processName)) { return true; } } return false; } /** * whether application is in background * * * @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 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 (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 serviceList = am.getRunningServices(100); if (serviceList != null) { for (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 processList = am.getRunningAppProcesses(); if (processList != null) { for (RunningAppProcessInfo process : processList) { // 一般数值大于RunningAppProcessInfo.IMPORTANCE_SERVICE的进程都长时间没用或者空进程了 // 一般数值大于RunningAppProcessInfo.IMPORTANCE_VISIBLE的进程都是非可见进程,也就是在后台运行着 if (process.importance > 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); MemoryInfo mi = new MemoryInfo(); am.getMemoryInfo(mi); // 返回当前系统的可用内存 return (int) (mi.availMem / (1024 * 1024)); } /** * 获取系统中所有的应用 * * @param context 上下文 * @return 应用信息List */ public static List getAllApps(Context context) { List apps = new ArrayList(); PackageManager pManager = context.getPackageManager(); List 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 (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; } }