package cm.android.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.res.AssetManager;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Debug;
import android.os.PowerManager;
import android.os.Process;
import android.provider.Settings;
import android.util.TypedValue;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import cm.android.applications.AppUtil;
import cm.java.util.IoUtil;
import cm.java.util.ReflectUtil;
import cm.java.util.Utils;
/**
* 常用工具类
*/
public final class AndroidUtils {
private static final Logger logger = LoggerFactory.getLogger(AndroidUtils.class);
private AndroidUtils() {
}
public static void closeQuietly(Cursor cursor) {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
public static boolean isEmpty(Bundle bundle) {
if (bundle == null || bundle.isEmpty()) {
return true;
}
return false;
}
/**
* 桩模块(Stub), 获取假数据,用于各个子功能单元测试
*/
public static byte[] getStubFile(Context cxt, String stubFileName) {
if (Utils.isEmpty(stubFileName)) {
return null;
}
InputStream inputStream = null;
try {
AssetManager assetManager = cxt.getAssets();
inputStream = assetManager.open(stubFileName);
byte[] bytes = cm.java.util.IoUtil.read(inputStream);
return bytes;
} catch (Exception e) {
logger.error("stubFileName = " + stubFileName, e);
} finally {
cm.java.util.IoUtil.closeQuietly(inputStream);
}
return null;
}
public static int getVersionCode(Context context) {
PackageInfo packageInfo = AppUtil.getPackageInfo(context.getPackageManager(), context.getPackageName(), 0);
if (packageInfo == null) {
return -1;
}
return packageInfo.versionCode;
}
public static String getVersionName(Context context) {
PackageInfo packageInfo = AppUtil.getPackageInfo(context.getPackageManager(), context.getPackageName(), 0);
if (packageInfo == null) {
return "";
}
return String.valueOf(packageInfo.versionName);
}
@Deprecated
public static String getSystemProperties(String key) {
String str = null;
try {
Class<?> c = Class.forName("android.os.SystemProperties");
Method get = c.getDeclaredMethod("get", String.class);
get.setAccessible(true);
str = (String) get.invoke(c, key);
} catch (ClassNotFoundException e) {
logger.error(e.getMessage(), e);
} catch (NoSuchMethodException e) {
logger.error(e.getMessage(), e);
} catch (IllegalAccessException e) {
logger.error(e.getMessage(), e);
} catch (InvocationTargetException e) {
logger.error(e.getMessage(), e);
}
logger.debug("getSystemProperties key = {},str = {}", key, str);
if (str == null) {
return "";
}
return str;
}
/**
* 加载Properties
*/
public static Properties loadProperties(Context context,
String propertiesName) {
Properties props = new Properties();
try {
int id = context.getResources().getIdentifier(propertiesName,
"raw", context.getPackageName());
InputStream is = context.getResources().openRawResource(id);
props.load(is);
} catch (Exception e) {
logger.error("Could not find the properties file.", e);
// e.printStackTrace();
}
return props;
}
/**
* 获取classes.dex文件CRC值
*/
@TargetApi(8)
public static long getDexCrc(Context context) {
long crc = 0;
ZipFile zf = null;
try {
zf = new ZipFile(context.getApplicationContext().getPackageCodePath());
ZipEntry ze = zf.getEntry("classes.dex");
crc = ze.getCrc();
return crc;
} catch (IOException e) {
logger.error("", e);
} finally {
if (zf != null) {
try {
zf.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
}
return 0;
}
public static boolean isDebuggable(ApplicationInfo applicationInfo) {
if ((applicationInfo.flags &= ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
return true;
}
return false;
}
public static boolean isDebuggable(Context context) {
try {
ApplicationInfo info = context.getApplicationInfo();
return isDebuggable(info);
} catch (Exception e) {
return false;
}
}
public static boolean isDebuggable(Context context, String packageName) {
PackageInfo pkginfo = AppUtil.getPackageInfo(context.getPackageManager(), packageName, 0);
if (pkginfo != null) {
return isDebuggable(pkginfo.applicationInfo);
}
return false;
}
public static boolean reboot(Context context) {
try {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
pm.reboot(context.getPackageName());
return true;
} catch (Exception e) {
logger.error("reboot error:" + e.getMessage(), e);
return false;
}
}
// public static void killProcess(Context context) {
// ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
// if (EnvironmentUtil.SdkUtil.hasFroyo()) {
// am.killBackgroundProcesses(context.getPackageName());
// } else {
// am.restartPackage(context.getPackageName());
// }
// android.os.Process.killProcess(android.os.Process.myPid());
// System.exit(0);
// }
/**
* Process.killProcessGroup(app.info.uid, app.pid);
*/
public static int killProcessGroup(Context context) {
Method killProcessGroup = ReflectUtil.getMethod(Process.class, "killProcessGroup", int.class, int.class);
if (killProcessGroup != null) {
return ReflectUtil.doMethod(Process.class, killProcessGroup, context.getApplicationInfo().uid, Process.myPid());
} else {
logger.error("killProcessGroup = null");
return -1;
}
}
public static void transferData(Bundle oldBundle, Bundle newBundle) {
if (oldBundle != null) {
newBundle.putAll(oldBundle);
}
}
public static void transferData(Intent oldIntent, Intent newIntent) {
if (oldIntent == null) {
return;
}
newIntent.putExtras(oldIntent);
}
public static boolean setAdbEnabled(Context context, int value) {
try {
return Settings.Secure.putInt(context.getContentResolver(), Settings.Global.ADB_ENABLED,
value);
} catch (SecurityException e) {
logger.error(e.getMessage(), e);
return false;
}
}
/**
* dip转px
*/
public static int dipToPx(final Context ctx, float dip) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dip, ctx.getResources().getDisplayMetrics());
}
public static <K, V> android.support.v4.util.ArrayMap<K, V> newMap() {
return new android.support.v4.util.ArrayMap<>();
}
public static <K, V> android.support.v4.util.ArrayMap<K, V> newMap(int capacity) {
return new android.support.v4.util.ArrayMap<>(capacity);
}
public static <K, V> android.support.v4.util.ArrayMap<K, V> newMap(Map<K, V> map) {
android.support.v4.util.ArrayMap<K, V> arrayMap = new android.support.v4.util.ArrayMap<>();
arrayMap.putAll(map);
return arrayMap;
}
public static int getMemCacheSizePercent(float percent) {
if (percent < 0.05f || percent > 0.8f) {
throw new IllegalArgumentException(
"setMemCacheSizePercent - percent must be "
+ "between 0.05 and 0.8 (inclusive)");
}
return Math.round(percent * Runtime.getRuntime().maxMemory() / 1024);
}
/**
* 打印内存信息以及dump Hprof
*/
public static void logMemoryInfo(Context context, File dumpDir) {
Logger logger = LoggerFactory.getLogger("LogMemoryInfo");
int pid = Process.myPid();
StringBuffer sb = new StringBuffer();
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
Debug.MemoryInfo memoryInfo = am.getProcessMemoryInfo(new int[]{pid})[0];
sb.append("** MEMINFO ** in pid ").append(pid).append("\n")
.append("processName : ").append(SystemUtil.getCurProcessName(context)).append("\n")
.append("totalPrivateDirty : ").append(memoryInfo.getTotalPrivateDirty()).append("\n")
.append("totalSharedDirty : ").append(memoryInfo.getTotalSharedDirty()).append("\n")
.append("totalPss : ").append(memoryInfo.getTotalPss()).append("\n")
.append("dalvikPrivateDirty : ").append(memoryInfo.dalvikPrivateDirty).append("\n")
.append("dalvikPss : ").append(memoryInfo.dalvikPss).append("\n")
.append("dalvikSharedDirty : ").append(memoryInfo.dalvikSharedDirty).append("\n")
.append("nativePrivateDirty : ").append(memoryInfo.nativePrivateDirty).append("\n")
.append("nativePss : ").append(memoryInfo.nativePss).append("\n")
.append("nativeSharedDirty : ").append(memoryInfo.nativeSharedDirty).append("\n")
.append("otherPrivateDirty : ").append(memoryInfo.otherPrivateDirty).append("\n")
.append("otherPss : ").append(memoryInfo.otherPss).append("\n")
.append("otherSharedDirty : ").append(memoryInfo.otherSharedDirty).append("\n");
logger.error("memory detail = {} ", sb.toString());
//TODO ggg 需保存多份,打印初次时,由于是多线程执行,导致并行
// 策略1:保存最近5份(异常时保存的5份都是最近的)
// 策略2:保存最近5天(每天保存最近一次,仅保存一份)
//:保存最新5份(每天仅保存一份)
if (dumpDir == null) {
return;
}
boolean dir = IoUtil.checkDirectory(dumpDir);
if (!dir) {
return;
}
try {
File[] files = dumpDir.listFiles();
if (files != null && files.length >= 5) {
//不用排序,listFiles默认就是按时间递增顺序排序的
int size = files.length;
while (size >= 5) {
IoUtil.delete(files[size - 1]);
size--;
}
}
String time = MyFormatter.formatDate("yyyyMMdd", System.currentTimeMillis());
String dumpName = String.format("dump-%s.dump", time);
File dumpFile = new File(dumpDir, dumpName);
Debug.dumpHprofData(dumpFile.getAbsolutePath());
} catch (IOException e) {
logger.error("error = {}", e.getMessage());
}
}
}