ฉันจะรับข้อมูลความขัดข้อง (อย่างน้อยมีร่องรอยสแต็ก) จากแอปพลิเคชัน Android ของฉันได้อย่างไร อย่างน้อยเมื่อทำงานบนอุปกรณ์ของฉันเองที่ถูกดึงด้วยสายเคเบิล แต่ควรนึกถึงแอปพลิเคชันของฉันที่ทำงานบนอุปกรณ์เพื่อให้ฉันสามารถปรับปรุงและทำให้มันแข็งแกร่งขึ้น
ฉันจะรับข้อมูลความขัดข้อง (อย่างน้อยมีร่องรอยสแต็ก) จากแอปพลิเคชัน Android ของฉันได้อย่างไร อย่างน้อยเมื่อทำงานบนอุปกรณ์ของฉันเองที่ถูกดึงด้วยสายเคเบิล แต่ควรนึกถึงแอปพลิเคชันของฉันที่ทำงานบนอุปกรณ์เพื่อให้ฉันสามารถปรับปรุงและทำให้มันแข็งแกร่งขึ้น
คำตอบ:
คุณอาจลองไลบรารีACRA (Application Crash Report สำหรับ Android) :
ACRA เป็นห้องสมุดที่เปิดใช้งานแอปพลิเคชัน Android เพื่อโพสต์รายงานข้อขัดข้องของพวกเขาไปยังแบบฟอร์ม GoogleDoc มีเป้าหมายสำหรับนักพัฒนาแอปพลิเคชัน Android เพื่อช่วยให้พวกเขาได้รับข้อมูลจากแอปพลิเคชันเมื่อเกิดข้อผิดพลาดหรือทำงานผิดพลาด
ง่ายต่อการติดตั้งในแอพกำหนดค่าได้สูงและไม่ต้องการให้คุณโฮสต์สคริปต์เซิร์ฟเวอร์ที่ใดก็ได้ ... รายงานจะถูกส่งไปยังสเปรดชีต Google เอกสาร!
สำหรับตัวอย่างแอพพลิเคชั่นและจุดประสงค์ในการดีบั๊กฉันใช้วิธีแก้ปัญหาง่ายๆที่อนุญาตให้ฉันเขียน stacktrace ไปยังการ์ด sd ของอุปกรณ์และ / หรืออัปโหลดไปยังเซิร์ฟเวอร์ โซลูชันนี้ได้รับแรงบันดาลใจจาก Project android-remote-stacktrace (โดยเฉพาะส่วนบันทึกไปยังอุปกรณ์และอัพโหลดไปยังเซิร์ฟเวอร์) และฉันคิดว่ามันแก้ปัญหาที่กล่าวถึงโดย Soonil มันไม่เหมาะสม แต่ใช้งานได้และคุณสามารถปรับปรุงได้หากคุณต้องการใช้ในแอปพลิเคชันที่ใช้งานจริง หากคุณตัดสินใจอัปโหลดสแต็คไปที่เซิร์ฟเวอร์คุณสามารถใช้ php script ( index.php
) เพื่อดู หากคุณสนใจคุณสามารถค้นหาแหล่งที่มาด้านล่างทั้งหมด - คลาส java หนึ่งแอปพลิเคชันของคุณและสอง php scrips เพิ่มเติมสำหรับเซิร์ฟเวอร์ที่โฮสต์สแต็คที่อัปโหลด
ในบริบท (เช่นกิจกรรมหลัก) ให้โทร
if(!(Thread.getDefaultUncaughtExceptionHandler() instanceof CustomExceptionHandler)) {
Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(
"/sdcard/<desired_local_path>", "http://<desired_url>/upload.php"));
}
CustomExceptionHandler
public class CustomExceptionHandler implements UncaughtExceptionHandler {
private UncaughtExceptionHandler defaultUEH;
private String localPath;
private String url;
/*
* if any of the parameters is null, the respective functionality
* will not be used
*/
public CustomExceptionHandler(String localPath, String url) {
this.localPath = localPath;
this.url = url;
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
}
public void uncaughtException(Thread t, Throwable e) {
String timestamp = TimestampFormatter.getInstance().getTimestamp();
final Writer result = new StringWriter();
final PrintWriter printWriter = new PrintWriter(result);
e.printStackTrace(printWriter);
String stacktrace = result.toString();
printWriter.close();
String filename = timestamp + ".stacktrace";
if (localPath != null) {
writeToFile(stacktrace, filename);
}
if (url != null) {
sendToServer(stacktrace, filename);
}
defaultUEH.uncaughtException(t, e);
}
private void writeToFile(String stacktrace, String filename) {
try {
BufferedWriter bos = new BufferedWriter(new FileWriter(
localPath + "/" + filename));
bos.write(stacktrace);
bos.flush();
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void sendToServer(String stacktrace, String filename) {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("filename", filename));
nvps.add(new BasicNameValuePair("stacktrace", stacktrace));
try {
httpPost.setEntity(
new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
httpClient.execute(httpPost);
} catch (IOException e) {
e.printStackTrace();
}
}
}
upload.php
<?php
$filename = isset($_POST['filename']) ? $_POST['filename'] : "";
$message = isset($_POST['stacktrace']) ? $_POST['stacktrace'] : "";
if (!ereg('^[-a-zA-Z0-9_. ]+$', $filename) || $message == ""){
die("This script is used to log debug data. Please send the "
. "logging message and a filename as POST variables.");
}
file_put_contents($filename, $message . "\n", FILE_APPEND);
?>
index.php
<?php
$myDirectory = opendir(".");
while($entryName = readdir($myDirectory)) {
$dirArray[] = $entryName;
}
closedir($myDirectory);
$indexCount = count($dirArray);
sort($dirArray);
print("<TABLE border=1 cellpadding=5 cellspacing=0 \n");
print("<TR><TH>Filename</TH><TH>Filetype</th><th>Filesize</TH></TR>\n");
for($index=0; $index < $indexCount; $index++) {
if ((substr("$dirArray[$index]", 0, 1) != ".")
&& (strrpos("$dirArray[$index]", ".stacktrace") != false)){
print("<TR><TD>");
print("<a href=\"$dirArray[$index]\">$dirArray[$index]</a>");
print("</TD><TD>");
print(filetype($dirArray[$index]));
print("</TD><TD>");
print(filesize($dirArray[$index]));
print("</TD></TR>\n");
}
}
print("</TABLE>\n");
?>
HttpPost httpPost = new HttpPost(url);
ต้องอยู่ในภารกิจ async (หรือตัวจัดการ ... เธรดแยกต่างหาก) ตอนนี้หากคุณกำหนดเป้าหมายไปที่ Honeycomb หรือใหม่กว่า
นอกจากนี้คุณยังสามารถลอง[BugSense] เหตุผล: สแปมเปลี่ยนเส้นทางไปยัง URL BugSense รวบรวมและวิเคราะห์รายงานข้อขัดข้องทั้งหมดและให้รายงานที่มีความหมายและเป็นภาพ ใช้งานได้ฟรีและมีโค้ดเพียง 1 บรรทัดเท่านั้นที่จะรวมเข้าด้วยกัน
ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้ร่วมก่อตั้ง
ใน Android 2.2 ตอนนี้เป็นไปได้ที่จะได้รับรายงาน Crash จากแอปพลิเคชัน Android Market โดยอัตโนมัติ:
คุณลักษณะการรายงานข้อผิดพลาดใหม่สำหรับแอพ Android Market ช่วยให้นักพัฒนาได้รับรายงานข้อผิดพลาดและหยุดการทำงานจากผู้ใช้ รายงานจะพร้อมใช้งานเมื่อพวกเขาลงชื่อเข้าใช้บัญชีผู้เผยแพร่
http://developer.android.com/sdk/android-2.2-highlights.html
เป็นไปได้ที่จะจัดการกับข้อยกเว้นเหล่านี้ด้วยThread.setDefaultUncaughtExceptionHandler()
อย่างไรก็ตามสิ่งนี้ดูเหมือนจะยุ่งกับวิธีการจัดการข้อยกเว้นของ Android ฉันพยายามใช้ตัวจัดการลักษณะนี้:
private class ExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread thread, Throwable ex){
Log.e(Constants.TAG, "uncaught_exception_handler: uncaught exception in thread " + thread.getName(), ex);
//hack to rethrow unchecked exceptions
if(ex instanceof RuntimeException)
throw (RuntimeException)ex;
if(ex instanceof Error)
throw (Error)ex;
//this should really never happen
Log.e(Constants.TAG, "uncaught_exception handler: unable to rethrow checked exception");
}
}
อย่างไรก็ตามถึงแม้จะมีการ rethrowing ข้อยกเว้นฉันไม่สามารถรับพฤติกรรมที่ต้องการได้เช่นการบันทึกข้อยกเว้นในขณะที่ยังคงอนุญาตให้ Android ปิดการทำงานขององค์ประกอบที่เกิดขึ้น
Constants.TAG
ส่วนหนึ่งของกรอบ Android หรือไม่? ครั้งแรกที่เห็นมัน ดูเหมือนจะไม่พบมัน
ฉันเห็นว่าคำถามนั้นเก่าเกินไปและหวังว่าคำตอบของฉันจะเป็นประโยชน์สำหรับผู้อื่นที่มีปัญหาเดียวกัน ...
ให้Crashlyticsลอง มันจะให้ข้อมูลเชิงลึกเกี่ยวกับความผิดพลาดทั้งหมดในอุปกรณ์ทั้งหมดที่มีแอปพลิเคชันของคุณและส่งการแจ้งเตือนถึงคุณผ่านทางอีเมลและส่วนที่ดีที่สุดคือการใช้งานได้อย่างสมบูรณ์ฟรี
ตกลงฉันดูตัวอย่างจาก rrainn และ Soonil แล้วและฉันพบวิธีแก้ปัญหาที่ไม่ทำให้เกิดข้อผิดพลาดในการจัดการ
ฉันแก้ไข CustomExceptionHandler ดังนั้นมันจะเก็บ UncaughtExceptionHandler ดั้งเดิมจากเธรดที่เราเชื่อมโยงใหม่ ในตอนท้ายของ "uncaughtException" ใหม่ - วิธีฉันเพิ่งเรียกฟังก์ชั่นเก่าโดยใช้ UncaughtExceptionHandler ที่เก็บไว้
ในคลาส DefaultExceptionHandler คุณต้องการ sth แบบนี้:
public class DefaultExceptionHandler implements UncaughtExceptionHandler{
private UncaughtExceptionHandler mDefaultExceptionHandler;
//constructor
public DefaultExceptionHandler(UncaughtExceptionHandler pDefaultExceptionHandler)
{
mDefaultExceptionHandler= pDefaultExceptionHandler;
}
public void uncaughtException(Thread t, Throwable e) {
//do some action like writing to file or upload somewhere
//call original handler
mStandardEH.uncaughtException(t, e);
// cleanup, don't know if really required
t.getThreadGroup().destroy();
}
}
ด้วยการแก้ไขในรหัสที่http://code.google.com/p/android-remote-stacktrace คุณมีฐานการทำงานที่ดีสำหรับการเข้าสู่ระบบในเขตข้อมูลไปยังเว็บเซิร์ฟเวอร์ของคุณหรือไปยัง sd-card
Google Developers Developers Console ให้การติดตามสแต็กจากแอพที่ล้มเหลวและส่งรายงานมาให้คุณจริงๆแล้วยังมีแผนภูมิที่ดีมากที่จะช่วยให้คุณเห็นข้อมูลดังตัวอย่างด้านล่าง:
ฉันใช้Crittercismสำหรับแอพ Android และ iOS ของฉันแล้วได้ยินเกี่ยวกับพวกเขาในการทดสอบเทคโนโลยี ค่อนข้างมีความสุขกับพวกเขาจนถึงตอนนี้!
ฉันสร้างเวอร์ชันของตัวเองที่นี่: http://androidblogger.blogspot.com/2009/12/how-to-improve-your-application-crash.html
โดยพื้นฐานแล้วมันเป็นสิ่งเดียวกัน แต่ฉันใช้อีเมลแทนการเชื่อมโยง http เพื่อส่งรายงานและที่สำคัญกว่านั้นฉันเพิ่มข้อมูลบางอย่างเช่นเวอร์ชันแอปพลิเคชันเวอร์ชัน OS รุ่นโทรศัพท์หรือหน่วยความจำ avalaible ไปยังรายงานของฉัน .. .
ใช้สิ่งนี้เพื่อตรวจสอบรายละเอียดข้อยกเว้น:
String stackTrace = Log.getStackTraceString(exception);
เก็บสิ่งนี้ในฐานข้อมูลและเก็บรักษาบันทึก
คุณสามารถใช้บริการทั้งหมด (อย่างง่าย) แทนการใช้ไลบรารีเท่านั้น บริษัท ของเราเพียงแค่เปิดตัวบริการเพียงว่าhttp://apphance.com
มีไลบรารี. jar แบบง่าย (สำหรับ Android) ที่คุณเพิ่มและรวมใน 5 นาทีจากนั้นไลบรารีจะรวบรวมไม่เพียง แต่ข้อมูลขัดข้อง แต่ยังล็อกจากแอปพลิเคชันที่ทำงานอยู่รวมถึงช่วยให้ผู้ทดสอบรายงานปัญหาโดยตรงจากอุปกรณ์ - บริบททั้งหมด (การหมุนอุปกรณ์ไม่ว่าจะเชื่อมต่อกับ WiFi หรือไม่และอื่น ๆ ) คุณสามารถดูบันทึกโดยใช้เว็บพาเนลที่ดีและมีประโยชน์ซึ่งคุณสามารถติดตามเซสชันด้วยแอปพลิเคชันของคุณเกิดปัญหาบันทึกสถิติและอื่น ๆ บริการอยู่ในช่วงทดสอบเบต้าปิด แต่คุณสามารถร้องขอการเข้าถึงและเราให้บริการคุณอย่างรวดเร็ว
ข้อจำกัดความรับผิดชอบ: ฉันเป็น CTO ของ Polidea และเป็นผู้ร่วมให้บริการ
ขอขอบคุณแหล่งข้อมูลที่มีอยู่Stackoverflow
ในการช่วยฉันค้นหาคำตอบนี้
คุณสามารถค้นหารายงานความผิดพลาดของคุณจากระยะไกล Android โดยตรงในอีเมลของคุณ remmember คุณต้องใส่อีเมลของคุณภายในระดับ CustomExceptionHandler
public static String sendErrorLogsTo = "tushar.pandey@virtualxcellence.com" ;
ขั้นตอนที่จำเป็น:
อันดับที่ 1) ใน onCreate กิจกรรมของคุณใช้ส่วนนี้ของรหัสของคุณ
if(!(Thread.getDefaultUncaughtExceptionHandler() instanceof CustomExceptionHandler)) {
Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(this));
}
2nd) ใช้คลาส CustomExceptionHandler รุ่นที่ถูกแทนที่นี้ของ (rrainn) ตาม phpscript ของฉัน
package com.vxmobilecomm.activity;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.AsyncTask;
import android.util.Log;
public class CustomExceptionHandler implements UncaughtExceptionHandler {
private UncaughtExceptionHandler defaultUEH;
public static String sendErrorLogsTo = "tushar.pandey@virtualxcellence.com" ;
Activity activity;
public CustomExceptionHandler(Activity activity) {
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
this.activity = activity;
}
public void uncaughtException(Thread t, Throwable e) {
final Writer result = new StringWriter();
final PrintWriter printWriter = new PrintWriter(result);
e.printStackTrace(printWriter);
String stacktrace = result.toString();
printWriter.close();
String filename = "error" + System.nanoTime() + ".stacktrace";
Log.e("Hi", "url != null");
sendToServer(stacktrace, filename);
StackTraceElement[] arr = e.getStackTrace();
String report = e.toString() + "\n\n";
report += "--------- Stack trace ---------\n\n";
for (int i = 0; i < arr.length; i++) {
report += " " + arr[i].toString() + "\n";
}
report += "-------------------------------\n\n";
report += "--------- Cause ---------\n\n";
Throwable cause = e.getCause();
if (cause != null) {
report += cause.toString() + "\n\n";
arr = cause.getStackTrace();
for (int i = 0; i < arr.length; i++) {
report += " " + arr[i].toString() + "\n";
}
}
report += "-------------------------------\n\n";
defaultUEH.uncaughtException(t, e);
}
private void sendToServer(String stacktrace, String filename) {
AsyncTaskClass async = new AsyncTaskClass(stacktrace, filename,
getAppLable(activity));
async.execute("");
}
public String getAppLable(Context pContext) {
PackageManager lPackageManager = pContext.getPackageManager();
ApplicationInfo lApplicationInfo = null;
try {
lApplicationInfo = lPackageManager.getApplicationInfo(
pContext.getApplicationInfo().packageName, 0);
} catch (final NameNotFoundException e) {
}
return (String) (lApplicationInfo != null ? lPackageManager
.getApplicationLabel(lApplicationInfo) : "Unknown");
}
public class AsyncTaskClass extends AsyncTask<String, String, InputStream> {
InputStream is = null;
String stacktrace;
final String filename;
String applicationName;
AsyncTaskClass(final String stacktrace, final String filename,
String applicationName) {
this.applicationName = applicationName;
this.stacktrace = stacktrace;
this.filename = filename;
}
@Override
protected InputStream doInBackground(String... params)
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(
"http://suo-yang.com/books/sendErrorLog/sendErrorLogs.php?");
Log.i("Error", stacktrace);
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(
6);
nameValuePairs.add(new BasicNameValuePair("data", stacktrace));
nameValuePairs.add(new BasicNameValuePair("to",sendErrorLogsTo));
nameValuePairs.add(new BasicNameValuePair("subject",applicationName));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity1 = response.getEntity();
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(
entity1);
is = bufHttpEntity.getContent();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return is;
}
@Override
protected void onPostExecute(InputStream result) {
super.onPostExecute(result);
Log.e("Stream Data", getStringFromInputStream(is));
}
}
// convert InputStream to String
private static String getStringFromInputStream(InputStream is) {
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
String line;
try {
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
}
ปัจจุบันรายงาน Firebase Crash หนึ่งวันได้รับความนิยมและใช้งานง่าย โปรดอ้างอิงลิงค์ต่อไปนี้สำหรับข้อมูลเพิ่มเติม: Firebase Crash Reporting
หวังว่ามันจะช่วยคุณ
นี่เป็นสัตว์เดรัจฉาน แต่มันเป็นไปได้ที่จะเรียกใช้ logcat ได้ทุกที่ดังนั้นแฮ็คที่รวดเร็วและสกปรกก็คือการเพิ่มเข้าไปในบล็อก catch ใด ๆ getRuntime().exec("logcat >> /sdcard/logcat.log");
มีเครื่องมือที่เรียกว่าแฟบริคซึ่งเป็นเครื่องมือวิเคราะห์ความผิดพลาดซึ่งจะช่วยให้คุณได้รับรายงานข้อผิดพลาดเมื่อแอปพลิเคชั่นใช้งานจริงและระหว่างการพัฒนา การเพิ่มเครื่องมือนี้ลงในแอปพลิเคชันของคุณนั้นง่ายมากเช่นกัน .. เมื่อแอปพลิเคชันของคุณพังซึ่งรายงานความผิดพลาดนั้นสามารถดูได้จากแดชบอร์ด fabric.io ของคุณ รายงาน thw ถูกจับโดยอัตโนมัติจะไม่ขออนุญาตจากผู้ใช้ ไม่ว่าเขา / เธอต้องการที่จะส่งรายงานข้อผิดพลาด / ความผิดพลาด และนี่คือฟรีโดยสมบูรณ์ ... https://get.fabric.io/
Google Firebaseเป็นวิธีล่าสุดของ Google (2016) ในการให้ข้อมูลความผิดพลาด / ข้อผิดพลาดในโทรศัพท์ของคุณ รวมไว้ในไฟล์ build.gradle ของคุณ:
compile 'com.google.firebase:firebase-crash:9.0.0'
ข้อผิดพลาดร้ายแรงจะถูกบันทึกโดยอัตโนมัติโดยไม่ต้องป้อนข้อมูลผู้ใช้และคุณสามารถบันทึกข้อผิดพลาดที่ไม่ร้ายแรงหรือเหตุการณ์อื่น ๆ เช่น:
try
{
}
catch(Exception ex)
{
FirebaseCrash.report(new Exception(ex.toString()));
}
มีห้องสมุดหุ่นยนต์ที่เรียกว่าเป็นเชอร์ล็อก มันให้รายงานความผิดพลาดเต็มรูปแบบพร้อมกับข้อมูลอุปกรณ์และแอปพลิเคชัน เมื่อใดก็ตามที่เกิดความผิดพลาดมันจะแสดงการแจ้งเตือนในแถบการแจ้งเตือนและเมื่อคลิกที่การแจ้งเตือนก็จะเปิดรายละเอียดความผิดพลาด คุณยังสามารถแชร์รายละเอียดข้อขัดข้องกับผู้อื่นผ่านทางอีเมลหรือตัวเลือกการแชร์อื่น ๆ
การติดตั้ง
android {
dataBinding {
enabled = true
}
}
compile('com.github.ajitsing:sherlock:1.0.0@aar') {
transitive = true
}
การสาธิต
แม้ว่าคำตอบหลายคำในหน้านี้จะมีประโยชน์ แต่ก็ง่ายสำหรับพวกเขาที่จะล้าสมัย สถิติการรวบรวมเว็บไซต์ AppBrain ซึ่งช่วยให้คุณค้นหาโซลูชันการรายงานข้อขัดข้องที่เป็นที่นิยมมากที่สุดที่เป็นปัจจุบัน:
ห้องสมุดรายงานความผิดพลาดของ Android
คุณจะเห็นว่าเมื่อโพสต์ภาพนี้ Crashlytics จะใช้ในแอพ 5.24% และ 12.38% ของการติดตั้ง
เราใช้ระบบที่ปลูกเองภายใน บริษัท และให้บริการเราได้เป็นอย่างดี มันเป็นห้องสมุด android ที่ส่งรายงานข้อขัดข้องไปยังเซิร์ฟเวอร์และเซิร์ฟเวอร์ที่รับรายงานและทำการวิเคราะห์ เซิร์ฟเวอร์ยกเว้นกลุ่มตามชื่อข้อยกเว้นสแต็คเทรซข้อความ ช่วยระบุปัญหาที่สำคัญที่สุดที่ต้องแก้ไข บริการของเราอยู่ในช่วงเบต้าสาธารณะดังนั้นทุกคนสามารถลองใช้ได้ คุณสามารถสร้างบัญชีที่http://watchcat.coหรือคุณก็สามารถมาดูวิธีการทำงานโดยใช้การเข้าถึงการสาธิตhttp://watchcat.co/reports/index.php?demo
หากคุณต้องการคำตอบทันทีคุณสามารถใช้logcat
$adb shell logcat -f /sdcard/logoutput.txt *:E
หากมีขยะมากเกินไปในบันทึกของคุณตอนนี้ให้ลองล้างมันเสียก่อน
$adb shell logcat -c
จากนั้นลองเรียกใช้แอปแล้ว logcat อีกครั้ง
ฉันพบเว็บแอปพลิเคชันที่ยอดเยี่ยมอีกหนึ่งรายการเพื่อติดตามรายงานข้อผิดพลาด
ขั้นตอนการกำหนดค่าจำนวนน้อย
Mint.initAndStartSession(YourActivity.this, "api_key");
android { ... repositories { maven { url "https://mint.splunk.com/gradle/"} } ... } dependencies { ... compile "com.splunk.mint:mint:4.4.0" ... }
Mint.initAndStartSession (YourActivity.this, "api_key");
แค่นั้นแหละ. คุณเข้าสู่ระบบและไปที่แดชบอร์ดแอปพลิเคชันคุณจะได้รับรายงานข้อผิดพลาดทั้งหมด
หวังว่าจะช่วยใครซักคน
สำหรับบริการรายงานข้อผิดพลาดสำรอง / ติดตามตรวจสอบRaygun.io - มันเป็นตรรกะที่ดีสำหรับการจัดการข้อขัดข้องของ Android รวมถึงประสบการณ์การใช้งานที่ดีเมื่อเสียบเข้ากับแอปของคุณ (โค้ดสองบรรทัดในกิจกรรมหลักของคุณ บรรทัดของ XML ที่วางลงใน AndroidManifest)
เมื่อแอปของคุณขัดข้องมันจะดึงการติดตามสแต็คข้อมูลสภาพแวดล้อมสำหรับฮาร์ด / ซอฟต์แวร์ข้อมูลการติดตามผู้ใช้ข้อมูลที่กำหนดเองใด ๆ ที่คุณระบุ ฯลฯ โดยอัตโนมัติและโพสต์ลงใน API แบบอะซิงโครนัส ไปยังดิสก์หากไม่มีเครือข่าย
ข้อจำกัดความรับผิดชอบ: ฉันสร้างผู้ให้บริการ Android :)
เพิ่งเริ่มใช้ ACRA https://github.com/ACRA/acraโดยใช้ Google Forms เป็นแบ็กเอนด์และเป็นเรื่องง่ายมากที่จะติดตั้งและใช้งานซึ่งเป็นค่าเริ่มต้น
แต่การส่งรายงานไปยัง Google Forms จะถูกคัดค้าน (ถูกลบออกแล้ว): https://plus.google.com/118444843928759726538/posts/GTTgsrEQdN6 https://github.com/ACRA/acra/acra/wiki/Notice-on-Google -Form-Spreadsheet การใช้งาน
อย่างไรก็ตามเป็นไปได้ที่จะกำหนดผู้ส่งของคุณเอง https://github.com/ACRA/acra/wiki/AdvancedUsage#wiki-Implementing_your_own_sender คุณสามารถลองส่งอีเมลถึงผู้ส่งได้
ด้วยความพยายามขั้นต่ำเป็นไปได้ที่จะส่งรายงานไปยัง bugsense: http://www.bugsense.com/docs/android#acra
NBบัญชีฟรีของ Bugsense จำกัด 500 รายงาน / เดือน
สายไปงานเลี้ยงฉันสนับสนุนและเชื่อว่า ACRA เป็นตัวเลือกที่ดีที่สุดในบรรดาทั้งหมด ง่ายต่อการติดตั้งและกำหนดค่า ฉันได้สร้างคำแนะนำโดยละเอียดพร้อมอินพุตจากทั่วเพื่อดึงรายงานข้อผิดพลาดโดยใช้ ACRA และส่งอีเมลเดียวกันกับที่อยู่อีเมลของฉันโดยใช้ MandrillAp
ลิงก์ไปที่โพสต์: https://androidician.wordpress.com/2015/03/29/sending-crash-reports-with-acra-over-email-using-mandrill/
เชื่อมโยงไปยังโครงการตัวอย่างบน github: https://github.com/ayushhgoyal/AcraSample
ฉันเป็นหนึ่งในผู้ก่อตั้งBugsnagที่เราออกแบบมาเพื่อจุดประสงค์นี้ Bugsnag จะรวบรวมข้อยกเว้นที่ไม่สามารถจัดการได้โดยอัตโนมัติในแอพ Android และส่งไปยังแดชบอร์ดของเราซึ่งคุณสามารถจัดลำดับความสำคัญของการแก้ไขและดำลงในข้อมูลการวินิจฉัย
ต่อไปนี้เป็นสิ่งสำคัญที่ต้องพิจารณาเมื่อเลือกหรือสร้างระบบรายงานข้อขัดข้องพร้อมกับตัวอย่างโค้ด:
หากคุณต้องการดูแนวทางปฏิบัติที่ดีที่สุดเกี่ยวกับการจัดการความผิดพลาด / การรายงานบน Android คุณสามารถตรวจสอบซอร์สโค้ดแบบเต็มสำหรับไลบรารีการรายงานข้อผิดพลาดของ Bugsnag ซึ่งเป็นโอเพ่นซอร์สแบบเต็มอย่าลังเลที่จะฉีกมันออกจากกัน
หากคนอื่นกำลังดาวน์โหลดแอปของคุณและหยุดทำงานบนอุปกรณ์ระยะไกลคุณอาจต้องการเข้าไปในห้องสมุดรายงานข้อผิดพลาดของ Android (อ้างอิงในโพสต์ SO นี้ ) หากเป็นเพียงอุปกรณ์ของคุณคุณสามารถใช้ LogCat แม้ว่าอุปกรณ์ไม่ได้เชื่อมต่อกับเครื่องโฮสต์เมื่อเกิดการขัดข้องให้เชื่อมต่ออุปกรณ์และการออกคำสั่ง adb logcat จะดาวน์โหลดประวัติ logcat ทั้งหมด (อย่างน้อยก็เท่าที่บัฟเฟอร์ซึ่งโดยปกติจะเป็น loooot ของข้อมูลบันทึก มันก็ไม่สิ้นสุด) ตัวเลือกเหล่านี้ตอบคำถามของคุณหรือไม่ หากคุณไม่สามารถพยายามชี้แจงสิ่งที่คุณกำลังมองหาอีกเล็กน้อย?
การวิเคราะห์ที่วุ่นวายช่วยให้คุณมีข้อมูลผิดพลาดรุ่นฮาร์ดแวร์รุ่น Android และสถิติการใช้งานแอปแบบสด ใน SDK ใหม่พวกเขาดูเหมือนจะให้ข้อมูลที่ผิดพลาดรายละเอียดเพิ่มเติมhttp://www.flurry.com/flurry-crash-analytics.html
Google เปลี่ยนจำนวนรายงานความผิดพลาดที่คุณได้รับจริง ก่อนหน้านี้คุณจะได้รับรายงานข้อผิดพลาดที่รายงานด้วยตนเองเท่านั้น
ตั้งแต่การประชุมนักพัฒนาครั้งล่าสุดและการแนะนำAndroid Vitalsคุณจะได้รับรายงานข้อขัดข้องจากผู้ใช้ที่เปิดใช้งานเพื่อแชร์ข้อมูลการวินิจฉัย
คุณจะเห็นข้อขัดข้องทั้งหมดที่รวบรวมจากอุปกรณ์ Android ที่ผู้ใช้เลือกใช้เพื่อแบ่งปันข้อมูลการใช้งานและการวินิจฉัยโดยอัตโนมัติ ข้อมูลพร้อมใช้งานสำหรับสองเดือนก่อนหน้า
คุณสามารถทำได้โดยตรงใน Android Studio เพียงเชื่อมต่อโทรศัพท์ของคุณรันแอพปล่อยให้มันพังและคุณสามารถดู stacktrace ได้โดยตรงใน Android Studio