33
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
package cn.shangyu.gdxzExpert.netease.util;
|
||||
|
||||
|
||||
/**
|
||||
* Created by winnie on 2017/12/21.
|
||||
*/
|
||||
|
||||
public class LogHelper {
|
||||
|
||||
public static void init() {
|
||||
// AVChatKit.setiLogUtil(new ILogUtil() {
|
||||
// @Override
|
||||
// public void ui(String msg) {
|
||||
// LogUtil.ui(msg);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void e(String tag, String msg) {
|
||||
// LogUtil.e(tag, msg);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void i(String tag, String msg) {
|
||||
// LogUtil.i(tag, msg);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void d(String tag, String msg) {
|
||||
// LogUtil.d(tag, msg);
|
||||
// }
|
||||
// });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package cn.shangyu.gdxzExpert.netease.util.crash;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
|
||||
public class AppCrashHandler {
|
||||
|
||||
private Context context;
|
||||
|
||||
private UncaughtExceptionHandler uncaughtExceptionHandler;
|
||||
|
||||
private static AppCrashHandler instance;
|
||||
|
||||
private AppCrashHandler(Context context) {
|
||||
this.context = context;
|
||||
|
||||
// get default
|
||||
uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
|
||||
|
||||
// install
|
||||
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
|
||||
@Override
|
||||
public void uncaughtException(Thread thread, final Throwable ex) {
|
||||
// save log
|
||||
saveException(ex, true);
|
||||
|
||||
// uncaught
|
||||
uncaughtExceptionHandler.uncaughtException(thread, ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static AppCrashHandler getInstance(Context mContext) {
|
||||
if (instance == null) {
|
||||
instance = new AppCrashHandler(mContext);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public final void saveException(Throwable ex, boolean uncaught) {
|
||||
CrashSaver.save(context, ex, uncaught);
|
||||
}
|
||||
|
||||
public void setUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
|
||||
if (handler != null) {
|
||||
this.uncaughtExceptionHandler = handler;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package cn.shangyu.gdxzExpert.netease.util.crash;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.netease.nim.uikit.common.util.storage.StorageType;
|
||||
import com.netease.nim.uikit.common.util.storage.StorageUtil;
|
||||
import com.netease.nim.uikit.common.util.string.MD5;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.LineNumberReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
class CrashSaver {
|
||||
|
||||
public static final void save(Context context, Throwable ex,
|
||||
boolean uncaught) {
|
||||
|
||||
if (!StorageUtil.isExternalStorageExist()) {// 如果没有sdcard,则不存储
|
||||
return;
|
||||
}
|
||||
Writer writer = null;
|
||||
PrintWriter printWriter = null;
|
||||
String stackTrace = "";
|
||||
try {
|
||||
writer = new StringWriter();
|
||||
printWriter = new PrintWriter(writer);
|
||||
ex.printStackTrace(printWriter);
|
||||
Throwable cause = ex.getCause();
|
||||
while (cause != null) {
|
||||
cause.printStackTrace(printWriter);
|
||||
cause = cause.getCause();
|
||||
}
|
||||
stackTrace = writer.toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
try {
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (printWriter != null) {
|
||||
printWriter.close();
|
||||
}
|
||||
}
|
||||
String signature = stackTrace.replaceAll("\\([^\\(]*\\)", "");
|
||||
String filename = MD5.getStringMD5(signature);
|
||||
if (TextUtils.isEmpty(filename)) {
|
||||
return;
|
||||
}
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
Date date = new Date();
|
||||
String timestamp = sdf.format(date);
|
||||
BufferedWriter mBufferedWriter = null;
|
||||
try {
|
||||
File mFile = new File(StorageUtil.getWritePath(
|
||||
filename + ".crashlog", StorageType.TYPE_LOG));
|
||||
File pFile = mFile.getParentFile();
|
||||
if (!pFile.exists()) {// 如果文件夹不存在,则先创建文件夹
|
||||
pFile.mkdirs();
|
||||
}
|
||||
int count = 1;
|
||||
if (mFile.exists()) {
|
||||
LineNumberReader reader = null;
|
||||
try {
|
||||
reader = new LineNumberReader(new FileReader(mFile));
|
||||
String line = reader.readLine();
|
||||
if (line.startsWith("count")) {
|
||||
int index = line.indexOf(":");
|
||||
if (index != -1) {
|
||||
String count_str = line.substring(++index);
|
||||
if (count_str != null) {
|
||||
count_str = count_str.trim();
|
||||
count = Integer.parseInt(count_str);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
mFile.delete();
|
||||
}
|
||||
|
||||
mFile.createNewFile();
|
||||
|
||||
mBufferedWriter = new BufferedWriter(new FileWriter(mFile, true));// 追加模式写文件
|
||||
mBufferedWriter.append(CrashSnapshot.snapshot(context, uncaught, timestamp, stackTrace, count));
|
||||
mBufferedWriter.flush();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (mBufferedWriter != null) {
|
||||
try {
|
||||
mBufferedWriter.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
package cn.shangyu.gdxzExpert.netease.util.crash;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.StatFs;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.Secure;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.netease.nim.uikit.api.NimUIKit;
|
||||
import com.netease.nim.uikit.common.util.sys.NetworkUtil;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import cn.shangyu.gdxzExpert.netease.util.sys.InstallUtil;
|
||||
import cn.shangyu.gdxzExpert.netease.util.sys.SysInfoUtil;
|
||||
|
||||
|
||||
public class CrashSnapshot {
|
||||
|
||||
private static long mTotalMemory = -1;
|
||||
|
||||
/**
|
||||
* 检测手机是否Rooted
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static boolean isRooted() {
|
||||
boolean isSdk = isGoogleSdk();
|
||||
Object tags = Build.TAGS;
|
||||
if ((!isSdk) && (tags != null)
|
||||
&& (((String) tags).contains("test-keys"))) {
|
||||
return true;
|
||||
}
|
||||
if (new File("/system/app/Superuser.apk").exists()) {
|
||||
return true;
|
||||
}
|
||||
if ((!isSdk) && (new File("/system/xbin/su").exists())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isGoogleSdk() {
|
||||
String str = Settings.Secure.getString(NimUIKit.getContext().getContentResolver(), Secure.ANDROID_ID);
|
||||
return ("sdk".equals(Build.PRODUCT))
|
||||
|| ("google_sdk".equals(Build.PRODUCT)) || (str == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取手机剩余电量
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static String battery() {
|
||||
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
|
||||
Intent intent = NimUIKit.getContext().registerReceiver(null, filter);
|
||||
int level = intent.getIntExtra("level", -1);
|
||||
int scale = intent.getIntExtra("scale", -1);
|
||||
if (scale == -1) {
|
||||
return "--";
|
||||
} else {
|
||||
return String.format(Locale.US, "%d %%", (level * 100) / scale);
|
||||
}
|
||||
}
|
||||
|
||||
private static long getAvailMemory() {
|
||||
ActivityManager am = (ActivityManager) NimUIKit.getContext()
|
||||
.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
|
||||
am.getMemoryInfo(mi);
|
||||
return mi.availMem;
|
||||
}
|
||||
|
||||
private static String parseFile(File file, String filter) {
|
||||
String str = null;
|
||||
if (file.exists()) {
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
br = new BufferedReader(new FileReader(file), 1024);
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
Pattern pattern = Pattern.compile("\\s*:\\s*");
|
||||
String[] ret = pattern.split(line, 2);
|
||||
if (ret != null && ret.length > 1 && ret[0].equals(filter)) {
|
||||
str = ret[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
private static long getSize(String size, String uint, int factor) {
|
||||
return Long.parseLong(size.split(uint)[0].trim()) * factor;
|
||||
}
|
||||
|
||||
private static synchronized long getTotalMemory() {
|
||||
if (mTotalMemory == -1) {
|
||||
long total = 0L;
|
||||
String str;
|
||||
try {
|
||||
if (!TextUtils.isEmpty(str = parseFile(
|
||||
new File("/proc/meminfo"), "MemTotal"))) {
|
||||
str = str.toUpperCase(Locale.US);
|
||||
if (str.endsWith("KB")) {
|
||||
total = getSize(str, "KB", 1024);
|
||||
} else if (str.endsWith("MB")) {
|
||||
total = getSize(str, "MB", 1048576);
|
||||
} else if (str.endsWith("GB")) {
|
||||
total = getSize(str, "GB", 1073741824);
|
||||
} else {
|
||||
total = -1;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
mTotalMemory = total;
|
||||
}
|
||||
return mTotalMemory;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@SuppressLint("NewApi")
|
||||
private static long[] getSdCardMemory() {
|
||||
long[] sdCardInfo = new long[2];
|
||||
String state = Environment.getExternalStorageState();
|
||||
if (Environment.MEDIA_MOUNTED.equals(state)) {
|
||||
File sdcardDir = Environment.getExternalStorageDirectory();
|
||||
StatFs sf = new StatFs(sdcardDir.getPath());
|
||||
if (Build.VERSION.SDK_INT >= 18) {
|
||||
long bSize = sf.getBlockSizeLong();
|
||||
long bCount = sf.getBlockCountLong();
|
||||
long availBlocks = sf.getAvailableBlocksLong();
|
||||
sdCardInfo[0] = bSize * bCount;
|
||||
sdCardInfo[1] = bSize * availBlocks;
|
||||
} else {
|
||||
long bSize = sf.getBlockSize();
|
||||
long bCount = sf.getBlockCount();
|
||||
long availBlocks = sf.getAvailableBlocks();
|
||||
sdCardInfo[0] = bSize * bCount;
|
||||
sdCardInfo[1] = bSize * availBlocks;
|
||||
}
|
||||
}
|
||||
return sdCardInfo;
|
||||
}
|
||||
|
||||
private static String disk() {
|
||||
long[] info = getSdCardMemory();
|
||||
long total = info[0];
|
||||
long avail = info[1];
|
||||
if (total <= 0) {
|
||||
return "--";
|
||||
} else {
|
||||
float ratio = (float) ((avail * 100) / total);
|
||||
return String.format(Locale.US, "%.01f%% [%s]", ratio, getSizeWithUnit(total));
|
||||
}
|
||||
}
|
||||
|
||||
private static String ram() {
|
||||
long total = getTotalMemory();
|
||||
long avail = getAvailMemory();
|
||||
if (total <= 0) {
|
||||
return "--";
|
||||
} else {
|
||||
float ratio = (float) ((avail * 100) / total);
|
||||
return String.format(Locale.US, "%.01f%% [%s]", ratio, getSizeWithUnit(total));
|
||||
}
|
||||
}
|
||||
|
||||
private static String getSizeWithUnit(long size) {
|
||||
if (size >= 1073741824) {
|
||||
float i = (float) (size / 1073741824);
|
||||
return String.format(Locale.US, "%.02f GB", i);
|
||||
} else if (size >= 1048576) {
|
||||
float i = (float) (size / 1048576);
|
||||
return String.format(Locale.US, "%.02f MB", i);
|
||||
} else {
|
||||
float i = (float) (size / 1024);
|
||||
return String.format(Locale.US, "%.02f KB", i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String snapshot(Context context, boolean uncaught, String timestamp, String trace, int count) {
|
||||
Map<String, String> info = new LinkedHashMap<String, String>();
|
||||
info.put("count: ", String.valueOf(count));
|
||||
info.put("time: ", timestamp);
|
||||
info.put("device: ", SysInfoUtil.getPhoneModelWithManufacturer());
|
||||
info.put("android: ", SysInfoUtil.getOsInfo());
|
||||
info.put("system: ", Build.DISPLAY);
|
||||
info.put("battery: ", battery());
|
||||
info.put("rooted: ", isRooted() ? "yes" : "no");
|
||||
info.put("ram: ", ram());
|
||||
info.put("disk: ", disk());
|
||||
info.put("ver: ", String.format("%d", InstallUtil.getVersionCode(context)));
|
||||
info.put("caught: ", uncaught ? "no" : "yes");
|
||||
info.put("network: ", NetworkUtil.getNetworkInfo(context));
|
||||
Iterator<Map.Entry<String, String>> iterator = info.entrySet().iterator();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, String> entry = iterator.next();
|
||||
if (entry != null) {
|
||||
sb.append(entry.getKey()).append(entry.getValue());
|
||||
sb.append(System.getProperty("line.separator"));
|
||||
}
|
||||
}
|
||||
sb.append(System.getProperty("line.separator"));
|
||||
sb.append(trace);
|
||||
sb.append(System.getProperty("line.separator"));
|
||||
sb.append(System.getProperty("line.separator"));
|
||||
sb.append(System.getProperty("line.separator"));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package cn.shangyu.gdxzExpert.netease.util.sys;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.netease.nim.uikit.api.NimUIKit;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class InstallUtil {
|
||||
private static final String TAG = "InstallUtil";
|
||||
|
||||
private static int versionCode;
|
||||
|
||||
private static String versionName;
|
||||
|
||||
/**
|
||||
* 是否已安装app
|
||||
*
|
||||
* @param context
|
||||
* @param packageName
|
||||
* @return
|
||||
*/
|
||||
public static boolean isAppInstalled(Context context, String packageName) {
|
||||
try {
|
||||
if (TextUtils.isEmpty(packageName))
|
||||
return false;
|
||||
return context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_ACTIVITIES) != null;
|
||||
} catch (NameNotFoundException localNameNotFoundException) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开app
|
||||
*
|
||||
* @param packageName
|
||||
* @param context
|
||||
*/
|
||||
public static void openApp(Context context, String packageName) {
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
Intent intent = packageManager.getLaunchIntentForPackage(packageName);
|
||||
if (intent != null)
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 某个app的版本号,未安装时返回null
|
||||
*/
|
||||
public static final String getVersionName(Context context, String packageName) {
|
||||
try {
|
||||
PackageInfo pi = context.getPackageManager().getPackageInfo(packageName, 0);
|
||||
if (pi != null) {
|
||||
return pi.versionName;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static final int getVersionCode(Context context) {
|
||||
if (versionCode == 0) {
|
||||
loadVersionInfo(context);
|
||||
}
|
||||
|
||||
return versionCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 易信版本号
|
||||
*/
|
||||
public static final String getVersionName(Context context) {
|
||||
if (TextUtils.isEmpty(versionName)) {
|
||||
loadVersionInfo(context);
|
||||
}
|
||||
|
||||
return versionName;
|
||||
}
|
||||
|
||||
private static final void loadVersionInfo(Context context) {
|
||||
try {
|
||||
PackageInfo pi = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
|
||||
if (pi != null) {
|
||||
versionCode = pi.versionCode;
|
||||
versionName = pi.versionName;
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 安装apk文件
|
||||
*/
|
||||
public static void installApk(String filepath) {
|
||||
NimUIKit.getContext().startActivity(getInstallApkIntent(filepath));
|
||||
}
|
||||
|
||||
/**
|
||||
* 安装apk文件
|
||||
*/
|
||||
private static Intent getInstallApkIntent(String filepath) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
File file = new File(filepath);
|
||||
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
|
||||
return intent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package cn.shangyu.gdxzExpert.netease.util.sys;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.PowerManager;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class SysInfoUtil {
|
||||
public static final String getOsInfo() {
|
||||
return android.os.Build.VERSION.RELEASE;
|
||||
}
|
||||
|
||||
public static final String getPhoneModelWithManufacturer() {
|
||||
return Build.MANUFACTURER + " " + android.os.Build.MODEL;
|
||||
}
|
||||
|
||||
public static final String getPhoneMode() {
|
||||
return Build.MODEL;
|
||||
}
|
||||
|
||||
public static final boolean isAppOnForeground(Context context) {
|
||||
ActivityManager manager = (ActivityManager) context
|
||||
.getApplicationContext().getSystemService(
|
||||
Context.ACTIVITY_SERVICE);
|
||||
String packageName = context.getApplicationContext().getPackageName();
|
||||
List<ActivityManager.RunningAppProcessInfo> list = manager
|
||||
.getRunningAppProcesses();
|
||||
if (list == null)
|
||||
return false;
|
||||
boolean ret = false;
|
||||
Iterator<ActivityManager.RunningAppProcessInfo> it = list.iterator();
|
||||
while (it.hasNext()) {
|
||||
ActivityManager.RunningAppProcessInfo appInfo = it.next();
|
||||
if (appInfo.processName.equals(packageName)
|
||||
&& appInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static final boolean isScreenOn(Context context) {
|
||||
PowerManager powerManager = (PowerManager) context
|
||||
.getSystemService(Context.POWER_SERVICE);
|
||||
return powerManager.isScreenOn();
|
||||
}
|
||||
|
||||
public static boolean stackResumed(Context context) {
|
||||
ActivityManager manager = (ActivityManager) context
|
||||
.getApplicationContext().getSystemService(
|
||||
Context.ACTIVITY_SERVICE);
|
||||
String packageName = context.getApplicationContext().getPackageName();
|
||||
List<RunningTaskInfo> recentTaskInfos = manager.getRunningTasks(1);
|
||||
if (recentTaskInfos != null && recentTaskInfos.size() > 0) {
|
||||
RunningTaskInfo taskInfo = recentTaskInfos.get(0);
|
||||
if (taskInfo.baseActivity.getPackageName().equals(packageName) && taskInfo.numActivities > 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user