下面列出了怎么用android.app.ApplicationErrorReport的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Report a serious error in the current process. May or may not cause
* the process to terminate (depends on system settings).
*
* @param tag to record with the error
* @param t exception describing the error site and conditions
*/
public static void wtf(String tag, Throwable t, boolean system) {
try {
if (ActivityManager.getService().handleApplicationWtf(
mApplicationObject, tag, system,
new ApplicationErrorReport.ParcelableCrashInfo(t))) {
// The Activity Manager has already written us off -- now exit.
Process.killProcess(Process.myPid());
System.exit(10);
}
} catch (Throwable t2) {
if (t2 instanceof DeadObjectException) {
// System process is dead; ignore
} else {
Slog.e(TAG, "Error reporting WTF", t2);
Slog.e(TAG, "Original WTF:", t);
}
}
}
/**
* Always process the violation on the UI thread. This ensures other crash reports are not
* corrupted. Since each individual user has a very small chance of uploading each violation,
* and we have a hard cap of 3 per session, this will not affect performance too much.
*
* @param violationInfo The violation info from the StrictMode violation in question.
*/
@UiThread
private static void reportStrictModeViolation(Object violationInfo) {
try {
Field crashInfoField = violationInfo.getClass().getField("crashInfo");
ApplicationErrorReport.CrashInfo crashInfo =
(ApplicationErrorReport.CrashInfo) crashInfoField.get(violationInfo);
String stackTrace = crashInfo.stackTrace;
if (stackTrace == null) {
Log.d(TAG, "StrictMode violation stack trace was null.");
} else {
Log.d(TAG, "Upload stack trace: " + stackTrace);
JavaExceptionReporter.reportStackTrace(stackTrace);
}
} catch (Exception e) {
// Ignore all exceptions.
Log.d(TAG, "Could not handle observed StrictMode violation.", e);
}
}
/**
* Always process the violation on the UI thread. This ensures other crash reports are not
* corrupted. Since each individual user has a very small chance of uploading each violation,
* and we have a hard cap of 3 per session, this will not affect performance too much.
*
* @param violationInfo The violation info from the StrictMode violation in question.
*/
@UiThread
private static void reportStrictModeViolation(Object violationInfo) {
try {
Field crashInfoField = violationInfo.getClass().getField("crashInfo");
ApplicationErrorReport.CrashInfo crashInfo =
(ApplicationErrorReport.CrashInfo) crashInfoField.get(violationInfo);
String stackTrace = crashInfo.stackTrace;
if (stackTrace == null) {
Log.d(TAG, "StrictMode violation stack trace was null.");
} else {
Log.d(TAG, "Upload stack trace: " + stackTrace);
JavaExceptionReporter.reportStackTrace(stackTrace);
}
} catch (Exception e) {
// Ignore all exceptions.
Log.d(TAG, "Could not handle observed StrictMode violation.", e);
}
}
/**
* Always process the violation on the UI thread. This ensures other crash reports are not
* corrupted. Since each individual user has a very small chance of uploading each violation,
* and we have a hard cap of 3 per session, this will not affect performance too much.
*
* @param violationInfo The violation info from the StrictMode violation in question.
*/
@UiThread
private static void reportStrictModeViolation(Object violationInfo) {
try {
Field crashInfoField = violationInfo.getClass().getField("crashInfo");
ApplicationErrorReport.CrashInfo crashInfo =
(ApplicationErrorReport.CrashInfo) crashInfoField.get(violationInfo);
String stackTrace = crashInfo.stackTrace;
if (stackTrace == null) {
Log.d(TAG, "StrictMode violation stack trace was null.");
} else {
Log.d(TAG, "Upload stack trace: " + stackTrace);
JavaExceptionReporter.reportStackTrace(stackTrace);
}
} catch (Exception e) {
// Ignore all exceptions.
Log.d(TAG, "Could not handle observed StrictMode violation.", e);
}
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public static void showDefaultReportActivity(Context context, Throwable th)
{
String packageName = context.getPackageName();
PackageManager pm = context.getPackageManager();
// Not perfect.. but it'll have to do.
ApplicationErrorReport report = new ApplicationErrorReport();
report.installerPackageName = pm.getInstallerPackageName(packageName);
report.packageName = packageName;
report.processName = packageName;
report.time = System.currentTimeMillis();
report.systemApp = false;
report.type = ApplicationErrorReport.TYPE_CRASH;
report.crashInfo = new ApplicationErrorReport.CrashInfo(th);
sAppContext.startActivity(new Intent(Intent.ACTION_APP_ERROR)
.setPackage("com.google.android.feedback")
.putExtra(Intent.EXTRA_BUG_REPORT, report)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
/**
* Bring up the "unexpected error" dialog box for a crashing app.
* Deal with edge cases (intercepts from instrumented applications,
* ActivityController, error intent receivers, that sort of thing).
* @param r the application crashing
* @param crashInfo describing the failure
*/
void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
try {
crashApplicationInner(r, crashInfo, callingPid, callingUid);
} finally {
Binder.restoreCallingIdentity(origId);
}
}
void startAppProblemLocked(ProcessRecord app) {
// If this app is not running under the current user, then we
// can't give it a report button because that would require
// launching the report UI under a different user.
app.errorReportReceiver = null;
for (int userId : mService.mUserController.getCurrentProfileIds()) {
if (app.userId == userId) {
app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
mContext, app.info.packageName, app.info.flags);
}
}
mService.skipCurrentReceiverLocked(app);
}
Intent createAppErrorIntentLocked(ProcessRecord r,
long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
ApplicationErrorReport report = createAppErrorReportLocked(r, timeMillis, crashInfo);
if (report == null) {
return null;
}
Intent result = new Intent(Intent.ACTION_APP_ERROR);
result.setComponent(r.errorReportReceiver);
result.putExtra(Intent.EXTRA_BUG_REPORT, report);
result.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return result;
}
private ApplicationErrorReport createAppErrorReportLocked(ProcessRecord r,
long timeMillis, ApplicationErrorReport.CrashInfo crashInfo) {
if (r.errorReportReceiver == null) {
return null;
}
if (!r.crashing && !r.notResponding && !r.forceCrashReport) {
return null;
}
ApplicationErrorReport report = new ApplicationErrorReport();
report.packageName = r.info.packageName;
report.installerPackageName = r.errorReportReceiver.getPackageName();
report.processName = r.processName;
report.time = timeMillis;
report.systemApp = (r.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
if (r.crashing || r.forceCrashReport) {
report.type = ApplicationErrorReport.TYPE_CRASH;
report.crashInfo = crashInfo;
} else if (r.notResponding) {
report.type = ApplicationErrorReport.TYPE_ANR;
report.anrInfo = new ApplicationErrorReport.AnrInfo();
report.anrInfo.activity = r.notRespondingReport.tag;
report.anrInfo.cause = r.notRespondingReport.shortMsg;
report.anrInfo.info = r.notRespondingReport.longMsg;
}
return report;
}
@Override
public void uncaughtException(Thread t, Throwable e) {
try {
ensureLogging(t, e);
// Don't re-enter -- avoid infinite loops if crash-reporting crashes.
if (mCrashing) return;
mCrashing = true;
// Try to end profiling. If a profiler is running at this point, and we kill the
// process (below), the in-memory buffer will be lost. So try to stop, which will
// flush the buffer. (This makes method trace profiling useful to debug crashes.)
if (ActivityThread.currentActivityThread() != null) {
ActivityThread.currentActivityThread().stopProfiling();
}
// Bring up crash dialog, wait for it to be dismissed
ActivityManager.getService().handleApplicationCrash(
mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
} catch (Throwable t2) {
if (t2 instanceof DeadObjectException) {
// System process is dead; ignore
} else {
try {
Clog_e(TAG, "Error reporting crash", t2);
} catch (Throwable t3) {
// Even Clog_e() fails! Oh well.
}
}
} finally {
// Try everything to make sure this process goes away.
Process.killProcess(Process.myPid());
System.exit(10);
}
}
public static void sendCrashReport(Throwable ex, final Context context) {
if (!isPlayStoreInstall(context) || Util.isDebuggable(context))
return;
try {
ApplicationErrorReport report = new ApplicationErrorReport();
report.packageName = report.processName = context.getPackageName();
report.time = System.currentTimeMillis();
report.type = ApplicationErrorReport.TYPE_CRASH;
report.systemApp = false;
ApplicationErrorReport.CrashInfo crash = new ApplicationErrorReport.CrashInfo();
crash.exceptionClassName = ex.getClass().getSimpleName();
crash.exceptionMessage = ex.getMessage();
StringWriter writer = new StringWriter();
PrintWriter printer = new PrintWriter(writer);
ex.printStackTrace(printer);
crash.stackTrace = writer.toString();
StackTraceElement stack = ex.getStackTrace()[0];
crash.throwClassName = stack.getClassName();
crash.throwFileName = stack.getFileName();
crash.throwLineNumber = stack.getLineNumber();
crash.throwMethodName = stack.getMethodName();
report.crashInfo = crash;
final Intent bug = new Intent(Intent.ACTION_APP_ERROR);
bug.putExtra(Intent.EXTRA_BUG_REPORT, report);
bug.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (bug.resolveActivity(context.getPackageManager()) != null)
context.startActivity(bug);
} catch (Throwable exex) {
Log.e(TAG, exex.toString() + "\n" + Log.getStackTraceString(exex));
}
}
/**
* Manually create an exception and open system error reporting window.
* Source: https://github.com/DmitryMalkovich/github-analytics/blob/master/app/src/main/java/com/dmitrymalkovich/android/githubanalytics/util/ActivityUtils.java#L64
*
* @param activity Current activity
*/
public static void openFeedback(Activity activity) {
try {
throw new Exception();
} catch (Exception e) {
ApplicationErrorReport report = new ApplicationErrorReport();
report.packageName = report.processName = activity.getApplication()
.getPackageName();
report.time = System.currentTimeMillis();
report.type = ApplicationErrorReport.TYPE_CRASH;
report.systemApp = false;
ApplicationErrorReport.CrashInfo crash = new ApplicationErrorReport.CrashInfo();
crash.exceptionClassName = e.getClass().getSimpleName();
crash.exceptionMessage = e.getMessage();
StringWriter writer = new StringWriter();
PrintWriter printer = new PrintWriter(writer);
e.printStackTrace(printer);
crash.stackTrace = writer.toString();
StackTraceElement stack = e.getStackTrace()[0];
crash.throwClassName = stack.getClassName();
crash.throwFileName = stack.getFileName();
crash.throwLineNumber = stack.getLineNumber();
crash.throwMethodName = stack.getMethodName();
report.crashInfo = crash;
Intent intent = new Intent(Intent.ACTION_APP_ERROR);
intent.putExtra(Intent.EXTRA_BUG_REPORT, report);
activity.startActivity(intent);
}
}
public static void openFeedback(Activity activity) {
try {
throw new IOException();
} catch (IOException e) {
ApplicationErrorReport report = new ApplicationErrorReport();
report.packageName = report.processName = activity.getApplication()
.getPackageName();
report.time = System.currentTimeMillis();
report.type = ApplicationErrorReport.TYPE_CRASH;
report.systemApp = false;
ApplicationErrorReport.CrashInfo crash = new ApplicationErrorReport.CrashInfo();
crash.exceptionClassName = e.getClass().getSimpleName();
crash.exceptionMessage = e.getMessage();
StringWriter writer = new StringWriter();
PrintWriter printer = new PrintWriter(writer);
e.printStackTrace(printer);
crash.stackTrace = writer.toString();
StackTraceElement stack = e.getStackTrace()[0];
crash.throwClassName = stack.getClassName();
crash.throwFileName = stack.getFileName();
crash.throwLineNumber = stack.getLineNumber();
crash.throwMethodName = stack.getMethodName();
report.crashInfo = crash;
Intent intent = new Intent(Intent.ACTION_APP_ERROR);
intent.putExtra(Intent.EXTRA_BUG_REPORT, report);
activity.startActivity(intent);
}
}
public static void sendCrashReport(Throwable ex, final Context context) {
if (!isPlayStoreInstall(context) || Util.isDebuggable(context))
return;
try {
ApplicationErrorReport report = new ApplicationErrorReport();
report.packageName = report.processName = context.getPackageName();
report.time = System.currentTimeMillis();
report.type = ApplicationErrorReport.TYPE_CRASH;
report.systemApp = false;
ApplicationErrorReport.CrashInfo crash = new ApplicationErrorReport.CrashInfo();
crash.exceptionClassName = ex.getClass().getSimpleName();
crash.exceptionMessage = ex.getMessage();
StringWriter writer = new StringWriter();
PrintWriter printer = new PrintWriter(writer);
ex.printStackTrace(printer);
crash.stackTrace = writer.toString();
StackTraceElement stack = ex.getStackTrace()[0];
crash.throwClassName = stack.getClassName();
crash.throwFileName = stack.getFileName();
crash.throwLineNumber = stack.getLineNumber();
crash.throwMethodName = stack.getMethodName();
report.crashInfo = crash;
final Intent bug = new Intent(Intent.ACTION_APP_ERROR);
bug.putExtra(Intent.EXTRA_BUG_REPORT, report);
bug.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (bug.resolveActivity(context.getPackageManager()) != null)
context.startActivity(bug);
} catch (Throwable exex) {
Log.e(TAG, exex.toString() + "\n" + Log.getStackTraceString(exex));
}
}
public static void sendCrashReport(Throwable ex, final Context context) {
if (!isPlayStoreInstall(context) || Util.isDebuggable(context))
return;
try {
ApplicationErrorReport report = new ApplicationErrorReport();
report.packageName = report.processName = context.getPackageName();
report.time = System.currentTimeMillis();
report.type = ApplicationErrorReport.TYPE_CRASH;
report.systemApp = false;
ApplicationErrorReport.CrashInfo crash = new ApplicationErrorReport.CrashInfo();
crash.exceptionClassName = ex.getClass().getSimpleName();
crash.exceptionMessage = ex.getMessage();
StringWriter writer = new StringWriter();
PrintWriter printer = new PrintWriter(writer);
ex.printStackTrace(printer);
crash.stackTrace = writer.toString();
StackTraceElement stack = ex.getStackTrace()[0];
crash.throwClassName = stack.getClassName();
crash.throwFileName = stack.getFileName();
crash.throwLineNumber = stack.getLineNumber();
crash.throwMethodName = stack.getMethodName();
report.crashInfo = crash;
final Intent bug = new Intent(Intent.ACTION_APP_ERROR);
bug.putExtra(Intent.EXTRA_BUG_REPORT, report);
bug.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (bug.resolveActivity(context.getPackageManager()) != null)
context.startActivity(bug);
} catch (Throwable exex) {
Log.e(TAG, exex.toString() + "\n" + Log.getStackTraceString(exex));
}
}
private boolean handleAppCrashInActivityController(ProcessRecord r,
ApplicationErrorReport.CrashInfo crashInfo,
String shortMsg, String longMsg,
String stackTrace, long timeMillis,
int callingPid, int callingUid) {
if (mService.mController == null) {
return false;
}
try {
String name = r != null ? r.processName : null;
int pid = r != null ? r.pid : callingPid;
int uid = r != null ? r.info.uid : callingUid;
if (!mService.mController.appCrashed(name, pid,
shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
&& "Native crash".equals(crashInfo.exceptionClassName)) {
Slog.w(TAG, "Skip killing native crashed app " + name
+ "(" + pid + ") during testing");
} else {
Slog.w(TAG, "Force-killing crashed app " + name
+ " at watcher's request");
if (r != null) {
if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null))
{
r.kill("crash", true);
}
} else {
// Huh.
Process.killProcess(pid);
ActivityManagerService.killProcessGroup(uid, pid);
}
}
return true;
}
} catch (RemoteException e) {
mService.mController = null;
Watchdog.getInstance().setActivityController(null);
}
return false;
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public void reportToPlayStore(Context c) {
if (currentCrashInfo == null || currentException == null) {
return;
}
ApplicationErrorReport applicationErrorReport = new ApplicationErrorReport();
applicationErrorReport.packageName = this.context.getPackageName();
applicationErrorReport.processName = this.context.getPackageName();
applicationErrorReport.time = System.currentTimeMillis();
applicationErrorReport.systemApp = false;
///////////
// CRASH //
///////////
applicationErrorReport.type = ApplicationErrorReport.TYPE_CRASH;
ApplicationErrorReport.CrashInfo crashInfo = new ApplicationErrorReport.CrashInfo();
crashInfo.exceptionClassName = currentException.getClass().getSimpleName();
crashInfo.exceptionMessage = currentException.getMessage();
crashInfo.stackTrace = currentCrashInfo.toString() + " - " +Utils.getStackTrace(currentException);
StackTraceElement stackTraceElement = currentException.getStackTrace()[0];
crashInfo.throwClassName = stackTraceElement.getClassName();
crashInfo.throwFileName = stackTraceElement.getFileName();
crashInfo.throwMethodName = stackTraceElement.getMethodName();
crashInfo.throwLineNumber = stackTraceElement.getLineNumber();
applicationErrorReport.crashInfo = crashInfo;
Intent i = new Intent(Intent.ACTION_APP_ERROR);
i.putExtra(Intent.EXTRA_BUG_REPORT, applicationErrorReport);
if (!(c instanceof Activity)) {
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
// Force "Send feedback choice", but still needs user acknowledgement
i.setClassName("com.google.android.feedback", "com.google.android.feedback.FeedbackActivity");
c.startActivity(i);
currentCrashInfo = null;
currentException = null;
}
/**
* Ask questions or submit bug report to the developer via Google feedback.
*
* <p><p>It will redirect to {@link #report(Context, String, String)} method if feedback
* package is not available on the device.
*
* @param context The context to retrieve the resources.
* @param appName The app name for the email subject.
* <p>{@code null} to get it from the supplied context.
* @param email The email id of the developer.
*
* @throws ActivityNotFoundException If no activity is found.
*
* @see ApplicationErrorReport
* @see ApplicationErrorReport#TYPE_NONE
*/
public static void feedback(@NonNull Context context,
@Nullable String appName, @NonNull String email) {
feedback(context, appName, email, ApplicationErrorReport.TYPE_NONE, null);
}