package com.secondworld.univeralsdk;
|
|
import android.content.Context;
|
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageManager;
|
import android.os.Build;
|
import android.os.Looper;
|
import android.os.SystemClock;
|
import android.widget.Toast;
|
|
import java.io.File;
|
import java.io.FileOutputStream;
|
import java.io.FilenameFilter;
|
import java.io.PrintWriter;
|
import java.io.StringWriter;
|
import java.io.Writer;
|
import java.text.DateFormat;
|
import java.text.SimpleDateFormat;
|
import java.util.Calendar;
|
import java.util.Date;
|
import java.util.HashMap;
|
import java.util.Map;
|
|
/**
|
* Created by Administrator on 2018/7/19 0019.
|
*/
|
|
public class CrashCatchUtil implements Thread.UncaughtExceptionHandler
|
{
|
private static final String TAG = "CrashCatchUtil";
|
private Context m_Context;
|
private Thread.UncaughtExceptionHandler m_UncaughtExceptionHandler;
|
private Map<String, String> m_DevicceInfo = new HashMap<>();
|
|
private CrashCatchUtil() {}
|
|
private static CrashCatchUtil m_Instance;
|
|
public static CrashCatchUtil getInstance()
|
{
|
if (m_Instance == null)
|
{
|
m_Instance = new CrashCatchUtil();
|
}
|
return m_Instance;
|
}
|
|
public void init(Context context)
|
{
|
m_Context = context;
|
m_UncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
|
Thread.setDefaultUncaughtExceptionHandler(this);
|
autoClear(5);
|
}
|
|
@Override
|
public void uncaughtException(Thread thread, Throwable throwable)
|
{
|
if (!handleException(throwable) && m_UncaughtExceptionHandler != null)
|
{
|
m_UncaughtExceptionHandler.uncaughtException(thread, throwable);
|
}
|
else
|
{
|
SystemClock.sleep(3000);
|
android.os.Process.killProcess(android.os.Process.myPid());
|
System.exit(1);
|
}
|
}
|
|
private void recordDeviceInfo()
|
{
|
m_DevicceInfo.clear();
|
m_DevicceInfo.put("brand", Build.BRAND);
|
m_DevicceInfo.put("model", Build.MODEL);
|
m_DevicceInfo.put("android_version", String.valueOf(Build.VERSION.SDK_INT));
|
try
|
{
|
PackageManager _pkgMgr = m_Context.getPackageManager();
|
PackageInfo _pkgInfo = _pkgMgr.getPackageInfo(m_Context.getPackageName(),
|
PackageManager.GET_ACTIVITIES);
|
if (_pkgInfo != null)
|
{
|
m_DevicceInfo.put("versionName", _pkgInfo.versionName);
|
m_DevicceInfo.put("versionCode", String.valueOf(_pkgInfo.versionCode));
|
}
|
} catch (PackageManager.NameNotFoundException e)
|
{
|
e.printStackTrace();
|
}
|
}
|
|
private boolean handleException(Throwable throwable)
|
{
|
if (throwable == null)
|
{
|
return false;
|
}
|
|
try
|
{
|
new Thread(new Runnable()
|
{
|
@Override
|
public void run()
|
{
|
Looper.prepare();
|
Toast.makeText(m_Context, "程序出现异常,即将重启", Toast.LENGTH_LONG).show();
|
Looper.loop();
|
}
|
}).start();
|
|
recordDeviceInfo();
|
|
save(throwable);
|
|
SystemClock.sleep(3000);
|
|
} catch (Exception e)
|
{
|
e.printStackTrace();
|
}
|
return true;
|
}
|
|
private String save(Throwable throwable) throws Exception
|
{
|
StringBuffer sb = new StringBuffer();
|
try
|
{
|
SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
String date = sDateFormat.format(new Date());
|
sb.append("\r\n" + date + "\n");
|
for (Map.Entry<String, String> entry : m_DevicceInfo.entrySet())
|
{
|
String key = entry.getKey();
|
String value = entry.getValue();
|
sb.append(key + "=" + value + "\n");
|
}
|
|
Writer writer = new StringWriter();
|
PrintWriter printWriter = new PrintWriter(writer);
|
throwable.printStackTrace(printWriter);
|
Throwable cause = throwable.getCause();
|
while (cause != null)
|
{
|
cause.printStackTrace(printWriter);
|
cause = cause.getCause();
|
}
|
printWriter.flush();
|
printWriter.close();
|
String result = writer.toString();
|
sb.append(result);
|
|
String fileName = writeFile(sb.toString());
|
return fileName;
|
} catch (Exception e)
|
{
|
sb.append("写入崩溃日志时, 出现了异常状况...\r\n");
|
writeFile(sb.toString());
|
}
|
return null;
|
|
}
|
|
private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
|
|
private String writeFile(String sb) throws Exception
|
{
|
String time = formatter.format(new Date());
|
String fileName = "crash-" + time + ".log";
|
String path = getPath();
|
File dir = new File(getPath());
|
if (!dir.exists())
|
{
|
dir.mkdirs();
|
}
|
FileOutputStream fos = new FileOutputStream(path + fileName, true);
|
fos.write(sb.getBytes());
|
fos.flush();
|
fos.close();
|
return fileName;
|
}
|
|
private String getPath()
|
{
|
return m_Context.getExternalFilesDir("").getAbsolutePath()
|
+ File.separator
|
+ "crash"
|
+ File.separator;
|
}
|
|
/**
|
* 文件删除
|
*
|
* @param autoClearDay 文件保存天数
|
*/
|
public void autoClear(final int autoClearDay)
|
{
|
delete(getPath(), new FilenameFilter()
|
{
|
@Override
|
public boolean accept(File file, String filename)
|
{
|
String s = FileUtil.getFileNameWithoutExtension(filename);
|
int day = autoClearDay < 0 ? autoClearDay : -1 * autoClearDay;
|
String date = "crash-" + getOtherDay(day);
|
return date.compareTo(s) >= 0;
|
}
|
});
|
}
|
|
private void delete(String path, FilenameFilter filter)
|
{
|
File _file = new File(path);
|
if (!_file.exists())
|
{
|
return;
|
}
|
File[] _files = _file.listFiles(filter);
|
for (int i = _files.length - 1; i >= 0; i--)
|
{
|
_files[i].delete();
|
}
|
}
|
|
private String getOtherDay(int offset)
|
{
|
Calendar _calendar = Calendar.getInstance();
|
_calendar.add(Calendar.DATE, offset);
|
return formatter.format(_calendar.getTime());
|
}
|
}
|