ฉันจะรับข้อมูลความผิดพลาดจากแอปพลิเคชัน Android ของฉันได้อย่างไร


737

ฉันจะรับข้อมูลความขัดข้อง (อย่างน้อยมีร่องรอยสแต็ก) จากแอปพลิเคชัน Android ของฉันได้อย่างไร อย่างน้อยเมื่อทำงานบนอุปกรณ์ของฉันเองที่ถูกดึงด้วยสายเคเบิล แต่ควรนึกถึงแอปพลิเคชันของฉันที่ทำงานบนอุปกรณ์เพื่อให้ฉันสามารถปรับปรุงและทำให้มันแข็งแกร่งขึ้น



ฉันเห็นว่าสิ่งนี้ส่งรายงานไปยังเซิร์ฟเวอร์ระยะไกล มันสามารถบันทึกข้อยกเว้นไปยังไฟล์ในเครื่องได้หรือไม่?

1
Application Crash Report สำหรับ Android code.google.com/p/acra
gdonald

อันนี้ดูเหมือนจะมีประสิทธิภาพมากกว่าถ้ารายงานล้มเหลวในการอัพโหลดหลังจากลองใหม่ทั้งหมดจะสามารถบันทึกไฟล์หรือ sqlite db ได้หรือไม่
JPM

คำตอบ:


354

คุณอาจลองไลบรารีACRA (Application Crash Report สำหรับ Android) :

ACRA เป็นห้องสมุดที่เปิดใช้งานแอปพลิเคชัน Android เพื่อโพสต์รายงานข้อขัดข้องของพวกเขาไปยังแบบฟอร์ม GoogleDoc มีเป้าหมายสำหรับนักพัฒนาแอปพลิเคชัน Android เพื่อช่วยให้พวกเขาได้รับข้อมูลจากแอปพลิเคชันเมื่อเกิดข้อผิดพลาดหรือทำงานผิดพลาด

ง่ายต่อการติดตั้งในแอพกำหนดค่าได้สูงและไม่ต้องการให้คุณโฮสต์สคริปต์เซิร์ฟเวอร์ที่ใดก็ได้ ... รายงานจะถูกส่งไปยังสเปรดชีต Google เอกสาร!


8
ง่ายต่อการติดตั้งและใช้งาน แนะนำสำหรับการใช้งานในสถานที่ก่อนตลาดและแม้กระทั่งหลังจาก
mxcl

1
เริ่มใช้มันและมันก็ดีกว่าการรายงานข้อผิดพลาดใน Flurry ที่ฉันมีมาก่อนหรือโฮมเมดที่ฉันเริ่มด้วย จนถึงตอนนี้ฉัน stoked ที่ "acra"
Adrian Spinei

8
ข้อได้เปรียบที่ยิ่งใหญ่ของ acra คือความเป็นไปได้ที่จะใช้ Google API เพื่อวิเคราะห์และแสดงภาพข้อมูลได้อย่างง่ายดายดูjberkel.github.com/sms-backup-plus/acra-analysisเพื่อดูตัวอย่างในการทำเช่นนี้
Jan Berkel

3
ดูเหมือนจะไม่มั่นคงสำหรับฉัน ACRA ล้มเหลวและส่งรายงานข้อขัดข้องเกี่ยวกับตัวเองไม่ใช่ความผิดพลาดของแอพที่เกี่ยวข้อง -1
Sandor

19
Google เอกสารในฐานะแบ็กเอนด์ไม่รองรับอีกต่อไป
eliocs

305

สำหรับตัวอย่างแอพพลิเคชั่นและจุดประสงค์ในการดีบั๊กฉันใช้วิธีแก้ปัญหาง่ายๆที่อนุญาตให้ฉันเขียน 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");
?>

9
ฉันคิดว่านี่จะทำให้เกิดปัญหาทางกฎหมายในบางรัฐ / ประเทศ
setzamora

5
หมายเหตุ: HttpPost httpPost = new HttpPost(url);ต้องอยู่ในภารกิจ async (หรือตัวจัดการ ... เธรดแยกต่างหาก) ตอนนี้หากคุณกำหนดเป้าหมายไปที่ Honeycomb หรือใหม่กว่า
Bryan Denny

4
@Joset ปัญหาด้านกฎหมายประเภทใดและเพราะอะไร
varevarao

2
@varevarao ปัญหาด้านกฎหมาย (อาจ) เนื่องจากคุณกำลังส่งข้อมูลอุปกรณ์ที่ละเอียดอ่อนโดยไม่ได้รับความยินยอมจากผู้ใช้โดยใช้คุณลักษณะส่งไปยังเซิร์ฟเวอร์ของรหัสนี้
caw

2
DefaultExceptionHandler ดูเหมือนจะยังคงมีอยู่ในการทำกิจกรรม ฉันอัปเดตคำตอบเพื่อตั้งค่าเริ่มต้นเฉพาะเมื่อไม่ได้ตั้งค่าตัวจัดการแบบกำหนดเองไว้แล้ว หากไม่มีตัวจัดการแต่ละตัวจะถือและเรียกหมายเลขก่อนหน้าไปจนถึงตัวดั้งเดิม ซึ่งทำให้เกิดปัญหากับการบันทึกที่ซ้ำกันรวมทั้งปัญหาการรั่วไหลของหน่วยความจำ
Dave McClelland

57

นอกจากนี้คุณยังสามารถลอง[BugSense] เหตุผล: สแปมเปลี่ยนเส้นทางไปยัง URL BugSense รวบรวมและวิเคราะห์รายงานข้อขัดข้องทั้งหมดและให้รายงานที่มีความหมายและเป็นภาพ ใช้งานได้ฟรีและมีโค้ดเพียง 1 บรรทัดเท่านั้นที่จะรวมเข้าด้วยกัน

ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้ร่วมก่อตั้ง


4
ฉันได้ลอง BugSense แล้วมันเยี่ยมมาก UI ที่เรียบง่ายและสดใหม่อย่างรวดเร็วเช่นกัน ไม่มีการขยายคุณสมบัติที่โง่ ง่ายต่อการดูข้อผิดพลาดที่พบบ่อยที่สุดและยังขุดลงในกองซ้อน
vidstige

เมื่อเร็ว ๆ นี้เราทำอะไรมากไปกว่าการรายงานความผิดพลาดเพียง แต่นี้ไม่ได้เป็นสถานที่ที่เหมาะสมที่จะพูดคุยคุณสมบัติใหม่ ฯลฯ
PanosJee

พยายามมัน ข้อผิดพลาดทำงานได้แม้ว่าสแต็คเทรซไม่สมบูรณ์เกินไปข้อมูลความผิดพลาดตามเวลาจริงยังไม่ผ่าน โหมดแก้ไขข้อบกพร่องไม่ทำงาน ฉันลงเส้นทางเริ่มต้น - ครั้งเดียวจากคลาสแอปพลิเคชัน (ซึ่งเป็นสิ่งที่เหมาะสมสำหรับกรณีส่วนใหญ่) BugSense มีแดชบอร์ดที่น่าทึ่งความอับอายที่รายงานความผิดพลาดบางอย่างไม่ทำงานและสัญลักษณ์ไม่ได้อยู่ในระดับฟรี เอาฉันไป 5 นาทีเพื่อติดตั้ง GetSentry และมันเพิ่งทำงานนอกกรอบสำหรับ Android กับลูกค้าทั่วไปนี้: github.com/joshdholtz/Sentry-Android
albertpeiro

3
BugSense นั้นง่ายและง่ายต่อการรวมเข้าด้วยกัน แต่มันแพงเกินไป เราสามารถบรรลุฟังก์ชั่นการรับรู้ข้อผิดพลาดแบบเดียวกันโดยใช้การวิเคราะห์ความวุ่นวายและการแยกวิเคราะห์ ทั้งสองอย่างนั้นฟรีและง่ายต่อการรวมเข้าด้วยกัน
venkat

44

ใน Android 2.2 ตอนนี้เป็นไปได้ที่จะได้รับรายงาน Crash จากแอปพลิเคชัน Android Market โดยอัตโนมัติ:

คุณลักษณะการรายงานข้อผิดพลาดใหม่สำหรับแอพ Android Market ช่วยให้นักพัฒนาได้รับรายงานข้อผิดพลาดและหยุดการทำงานจากผู้ใช้ รายงานจะพร้อมใช้งานเมื่อพวกเขาลงชื่อเข้าใช้บัญชีผู้เผยแพร่

http://developer.android.com/sdk/android-2.2-highlights.html


ฉันคิดว่ามันไม่ใช่แค่ 2.2 แต่เป็นเพียงคุณสมบัติใหม่ของ Google ข้อเสนอ ฉันได้รับรายงานความผิดพลาดเมื่อหลายวันก่อนและไม่ควรมีอุปกรณ์ froyo อยู่ที่นั่นโดยใช้แอพของฉัน
Janusz

1
@ Janusz คุณแน่ใจหรือไม่ มีการเปิดตัว Froyo สำหรับ Nexus One แล้วโดยไม่นับ Googler ที่ใช้ Froyo มาระยะหนึ่งแล้ว
pupeno

อย่างน้อยต้องมีการอัปเดตในเวอร์ชั่นบนโทรศัพท์แม้จะเป็นเพียงการแก้ไขอีกครั้ง แต่วิธีนี้จะใช้งานได้อย่างไร
RoflcoptrException

ฉันไม่ทราบว่ารายงานได้ถูกส่งไปยัง Google มาก่อนหรือไม่ รายงานค่อนข้างแปลกเพราะ Google แสดง UI สำหรับการส่งวิดีโอและต้องมีการเปลี่ยนแปลงในระบบปฏิบัติการไม่ใช่เฉพาะตลาด แต่มันบอกว่า: แพลตฟอร์ม 1 รายงานรายงาน / สัปดาห์และหุ่นไม่ควรอยู่ใน froyo
Janusz

1
รหัสปุ่ม "รายงาน" อยู่ใน AOSP มาระยะหนึ่งแล้ว Romain Guy (ราง) ตอบคำถามเกี่ยวกับเรื่องนี้ที่นี่เมื่อสองสามเดือนที่ผ่านมา
Christopher Orr

30

เป็นไปได้ที่จะจัดการกับข้อยกเว้นเหล่านี้ด้วย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 ปิดการทำงานขององค์ประกอบที่เกิดขึ้น


ทำไมคุณเพียงโยนข้อยกเว้นที่ไม่ได้ตรวจสอบใหม่เท่านั้น? ดูเหมือนว่าคุณควรโยนข้อยกเว้นทั้งหมดอีกครั้ง
MatrixFrog

ดูเหมือนว่าบางคนประสบความสำเร็จกับวิธีการของคุณ: jyro.blogspot.com/2009/09/crash-report-for-android-app.html
MatrixFrog

1
เคล็ดลับคือการรับค่าเริ่มต้นก่อนหน้านี้ UncaughtExceptionHandler และจัดการข้อยกเว้นไปยังวัตถุนั้นหลังจากที่คุณรายงานข้อยกเว้นเสร็จแล้ว
Tom

เป็นConstants.TAGส่วนหนึ่งของกรอบ Android หรือไม่? ครั้งแรกที่เห็นมัน ดูเหมือนจะไม่พบมัน
Haroun Hajem

1
@HarounHajem เราจำเป็นต้องกำหนดของเราเอง
KYHSGeekCode

22

ฉันเห็นว่าคำถามนั้นเก่าเกินไปและหวังว่าคำตอบของฉันจะเป็นประโยชน์สำหรับผู้อื่นที่มีปัญหาเดียวกัน ...

ให้Crashlyticsลอง มันจะให้ข้อมูลเชิงลึกเกี่ยวกับความผิดพลาดทั้งหมดในอุปกรณ์ทั้งหมดที่มีแอปพลิเคชันของคุณและส่งการแจ้งเตือนถึงคุณผ่านทางอีเมลและส่วนที่ดีที่สุดคือการใช้งานได้อย่างสมบูรณ์ฟรี


21

ตกลงฉันดูตัวอย่างจาก 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


19

Google Developers Developers Console ให้การติดตามสแต็กจากแอพที่ล้มเหลวและส่งรายงานมาให้คุณจริงๆแล้วยังมีแผนภูมิที่ดีมากที่จะช่วยให้คุณเห็นข้อมูลดังตัวอย่างด้านล่าง:

ป้อนคำอธิบายรูปภาพที่นี่


2
คุณมีวิธีให้ผู้ใช้ส่งรายงานหรือทำงานอย่างไรถ้าแอพของคุณไม่ได้อยู่ใน play store คุณสามารถทำเพื่อการทดสอบได้หรือไม่?
Lion789

คุณรู้หรือไม่ว่ามีโครงการโอเพ่นซอร์ส Android ใดที่เปิดเผยรายงานข้อผิดพลาดของตน
Justin Civi

1
โปรดทราบว่านี่จะแสดงเฉพาะข้อขัดข้อง ANR ที่ผู้ใช้เลือกที่จะรายงาน
sojin

ใช่แล้วเมื่อคุณมีฐานผู้ใช้จำนวนมากคุณมีความเป็นไปได้มากมายที่จะรายงานข้อขัดข้องทั้งหมดและยังเกิดปัญหาและรายงาน ANR ที่นี่จะเป็นสิ่งที่สำคัญที่สุดเพราะผู้คนจะรายงานพวกเขาอีกครั้ง กรองและแก้ไขในลำดับความสำคัญนั้น (รายงานเพิ่มเติม = ข้อผิดพลาดที่สำคัญมากขึ้น) ในขณะที่ (ไม่มีรายงาน = ไม่ใช่ข้อบกพร่องที่สำคัญ)
Eefret

18

ฉันใช้Crittercismสำหรับแอพ Android และ iOS ของฉันแล้วได้ยินเกี่ยวกับพวกเขาในการทดสอบเทคโนโลยี ค่อนข้างมีความสุขกับพวกเขาจนถึงตอนนี้!


FYI: รายงานข้อขัดข้องจากด้าน NDK ไม่ได้เป็นส่วนหนึ่งของแผนพื้นฐานและอยู่ภายใต้ "การรายงานข้อขัดข้องเพิ่มเติม" ดูที่: crittercism.com/pricing
ahash

1
ฉันเพิ่งทดสอบการรายงาน NDK บน Crashlytics ของ Fabric.io ของ Twitter ... ยอดเยี่ยมมาก (ในวันที่ 1 ของการใช้งาน) มันต้องมีขั้นตอนเพิ่มเติมเมื่อฉันปล่อยวางการแมปลงในระบบของพวกเขาเพื่อให้ร่องรอยสแต็คดูดี ข้อผิดพลาด NDK ผมใช้ในการทดสอบ (ทำ "ยกเลิก ();" การเรียกร้องกลยุทธ์ทั่วค ++ และให้กองติดตามสำหรับการทดสอบ.
เธ่ Orionnoir

14

ฉันสร้างเวอร์ชันของตัวเองที่นี่: http://androidblogger.blogspot.com/2009/12/how-to-improve-your-application-crash.html

โดยพื้นฐานแล้วมันเป็นสิ่งเดียวกัน แต่ฉันใช้อีเมลแทนการเชื่อมโยง http เพื่อส่งรายงานและที่สำคัญกว่านั้นฉันเพิ่มข้อมูลบางอย่างเช่นเวอร์ชันแอปพลิเคชันเวอร์ชัน OS รุ่นโทรศัพท์หรือหน่วยความจำ avalaible ไปยังรายงานของฉัน .. .


11

ใช้สิ่งนี้เพื่อตรวจสอบรายละเอียดข้อยกเว้น:

String stackTrace = Log.getStackTraceString(exception); 

เก็บสิ่งนี้ในฐานข้อมูลและเก็บรักษาบันทึก


วิธีเข้าถึงฐานข้อมูลนั้นคุณจะยกตัวอย่างให้ฉัน กรุณาถ้าคุณสามารถ ขอบคุณใน advacne
Rajendra Verma

8

คุณสามารถใช้บริการทั้งหมด (อย่างง่าย) แทนการใช้ไลบรารีเท่านั้น บริษัท ของเราเพียงแค่เปิดตัวบริการเพียงว่าhttp://apphance.com

มีไลบรารี. jar แบบง่าย (สำหรับ Android) ที่คุณเพิ่มและรวมใน 5 นาทีจากนั้นไลบรารีจะรวบรวมไม่เพียง แต่ข้อมูลขัดข้อง แต่ยังล็อกจากแอปพลิเคชันที่ทำงานอยู่รวมถึงช่วยให้ผู้ทดสอบรายงานปัญหาโดยตรงจากอุปกรณ์ - บริบททั้งหมด (การหมุนอุปกรณ์ไม่ว่าจะเชื่อมต่อกับ WiFi หรือไม่และอื่น ๆ ) คุณสามารถดูบันทึกโดยใช้เว็บพาเนลที่ดีและมีประโยชน์ซึ่งคุณสามารถติดตามเซสชันด้วยแอปพลิเคชันของคุณเกิดปัญหาบันทึกสถิติและอื่น ๆ บริการอยู่ในช่วงทดสอบเบต้าปิด แต่คุณสามารถร้องขอการเข้าถึงและเราให้บริการคุณอย่างรวดเร็ว

ข้อจำกัดความรับผิดชอบ: ฉันเป็น CTO ของ Polidea และเป็นผู้ร่วมให้บริการ


7

ขอขอบคุณแหล่งข้อมูลที่มีอยู่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();

    }
}

6

ปัจจุบันรายงาน Firebase Crash หนึ่งวันได้รับความนิยมและใช้งานง่าย โปรดอ้างอิงลิงค์ต่อไปนี้สำหรับข้อมูลเพิ่มเติม: Firebase Crash Reporting

หวังว่ามันจะช่วยคุณ


5

นี่เป็นสัตว์เดรัจฉาน แต่มันเป็นไปได้ที่จะเรียกใช้ logcat ได้ทุกที่ดังนั้นแฮ็คที่รวดเร็วและสกปรกก็คือการเพิ่มเข้าไปในบล็อก catch ใด ๆ getRuntime().exec("logcat >> /sdcard/logcat.log");


นี่จะให้เอาท์พุทบันทึกของแอพทั้งหมด การกรองโดยชื่อแท็กของแอปอาจไม่เป็นไร แต่อย่าคิดว่านี่จะเป็นวิธีที่ดีในการไปเพราะรายการอาจมีความหลากหลาย การล้างเอาต์พุต logcat หลังจากการเขียนแต่ละครั้งอาจช่วยแก้ปัญหานั้นได้
bschandramohan

5

มีเครื่องมือที่เรียกว่าแฟบริคซึ่งเป็นเครื่องมือวิเคราะห์ความผิดพลาดซึ่งจะช่วยให้คุณได้รับรายงานข้อผิดพลาดเมื่อแอปพลิเคชั่นใช้งานจริงและระหว่างการพัฒนา การเพิ่มเครื่องมือนี้ลงในแอปพลิเคชันของคุณนั้นง่ายมากเช่นกัน .. เมื่อแอปพลิเคชันของคุณพังซึ่งรายงานความผิดพลาดนั้นสามารถดูได้จากแดชบอร์ด fabric.io ของคุณ รายงาน thw ถูกจับโดยอัตโนมัติจะไม่ขออนุญาตจากผู้ใช้ ไม่ว่าเขา / เธอต้องการที่จะส่งรายงานข้อผิดพลาด / ความผิดพลาด และนี่คือฟรีโดยสมบูรณ์ ... https://get.fabric.io/


5

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()));
}

5

มีห้องสมุดหุ่นยนต์ที่เรียกว่าเป็นเชอร์ล็อก มันให้รายงานความผิดพลาดเต็มรูปแบบพร้อมกับข้อมูลอุปกรณ์และแอปพลิเคชัน เมื่อใดก็ตามที่เกิดความผิดพลาดมันจะแสดงการแจ้งเตือนในแถบการแจ้งเตือนและเมื่อคลิกที่การแจ้งเตือนก็จะเปิดรายละเอียดความผิดพลาด คุณยังสามารถแชร์รายละเอียดข้อขัดข้องกับผู้อื่นผ่านทางอีเมลหรือตัวเลือกการแชร์อื่น ๆ

การติดตั้ง

android {
    dataBinding {
      enabled = true
    }
}

compile('com.github.ajitsing:sherlock:1.0.0@aar') {
    transitive = true
}

การสาธิต

ป้อนคำอธิบายรูปภาพที่นี่


5

แม้ว่าคำตอบหลายคำในหน้านี้จะมีประโยชน์ แต่ก็ง่ายสำหรับพวกเขาที่จะล้าสมัย สถิติการรวบรวมเว็บไซต์ AppBrain ซึ่งช่วยให้คุณค้นหาโซลูชันการรายงานข้อขัดข้องที่เป็นที่นิยมมากที่สุดที่เป็นปัจจุบัน:

ห้องสมุดรายงานความผิดพลาดของ Android

เว็บไซต์สมองแอป

คุณจะเห็นว่าเมื่อโพสต์ภาพนี้ Crashlytics จะใช้ในแอพ 5.24% และ 12.38% ของการติดตั้ง


4

เราใช้ระบบที่ปลูกเองภายใน บริษัท และให้บริการเราได้เป็นอย่างดี มันเป็นห้องสมุด android ที่ส่งรายงานข้อขัดข้องไปยังเซิร์ฟเวอร์และเซิร์ฟเวอร์ที่รับรายงานและทำการวิเคราะห์ เซิร์ฟเวอร์ยกเว้นกลุ่มตามชื่อข้อยกเว้นสแต็คเทรซข้อความ ช่วยระบุปัญหาที่สำคัญที่สุดที่ต้องแก้ไข บริการของเราอยู่ในช่วงเบต้าสาธารณะดังนั้นทุกคนสามารถลองใช้ได้ คุณสามารถสร้างบัญชีที่http://watchcat.coหรือคุณก็สามารถมาดูวิธีการทำงานโดยใช้การเข้าถึงการสาธิตhttp://watchcat.co/reports/index.php?demo


3

หากคุณต้องการคำตอบทันทีคุณสามารถใช้logcat

$adb shell logcat -f /sdcard/logoutput.txt *:E

หากมีขยะมากเกินไปในบันทึกของคุณตอนนี้ให้ลองล้างมันเสียก่อน

$adb shell logcat -c

จากนั้นลองเรียกใช้แอปแล้ว logcat อีกครั้ง


สิ่งนี้ยังไม่ต้องการหรือไม่ที่คุณต้องต่ออุปกรณ์เข้ากับพีซี (เช่นด้วยสายเคเบิล)?
เจอราร์ด

3

ฉันพบเว็บแอปพลิเคชันที่ยอดเยี่ยมอีกหนึ่งรายการเพื่อติดตามรายงานข้อผิดพลาด

https://mint.splunk.com/

ขั้นตอนการกำหนดค่าจำนวนน้อย

  1. เข้าสู่ระบบหรือลงทะเบียนและกำหนดค่าโดยใช้ลิงก์ด้านบน เมื่อคุณสร้างแอปพลิเคชันเสร็จแล้วพวกเขาจะให้บรรทัดสำหรับการกำหนดค่าด้านล่าง
Mint.initAndStartSession(YourActivity.this, "api_key");
  1. เพิ่มสิ่งต่อไปนี้ใน build.gradl ของแอปพลิเคชัน
android {
...
    repositories {
        maven { url "https://mint.splunk.com/gradle/"}
    }
...
}

dependencies {
...
    compile "com.splunk.mint:mint:4.4.0"
...
}
  1. เพิ่มรหัสที่เราคัดลอกด้านบนและเพิ่มลงในทุกกิจกรรม

    Mint.initAndStartSession (YourActivity.this, "api_key");

แค่นั้นแหละ. คุณเข้าสู่ระบบและไปที่แดชบอร์ดแอปพลิเคชันคุณจะได้รับรายงานข้อผิดพลาดทั้งหมด

หวังว่าจะช่วยใครซักคน


ราคาเท่าไร?
user2966445

2

สำหรับบริการรายงานข้อผิดพลาดสำรอง / ติดตามตรวจสอบRaygun.io - มันเป็นตรรกะที่ดีสำหรับการจัดการข้อขัดข้องของ Android รวมถึงประสบการณ์การใช้งานที่ดีเมื่อเสียบเข้ากับแอปของคุณ (โค้ดสองบรรทัดในกิจกรรมหลักของคุณ บรรทัดของ XML ที่วางลงใน AndroidManifest)

เมื่อแอปของคุณขัดข้องมันจะดึงการติดตามสแต็คข้อมูลสภาพแวดล้อมสำหรับฮาร์ด / ซอฟต์แวร์ข้อมูลการติดตามผู้ใช้ข้อมูลที่กำหนดเองใด ๆ ที่คุณระบุ ฯลฯ โดยอัตโนมัติและโพสต์ลงใน API แบบอะซิงโครนัส ไปยังดิสก์หากไม่มีเครือข่าย

ข้อจำกัดความรับผิดชอบ: ฉันสร้างผู้ให้บริการ Android :)


1

เพิ่งเริ่มใช้ 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 รายงาน / เดือน


1

สายไปงานเลี้ยงฉันสนับสนุนและเชื่อว่า 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


1

ฉันเป็นหนึ่งในผู้ก่อตั้งBugsnagที่เราออกแบบมาเพื่อจุดประสงค์นี้ Bugsnag จะรวบรวมข้อยกเว้นที่ไม่สามารถจัดการได้โดยอัตโนมัติในแอพ Android และส่งไปยังแดชบอร์ดของเราซึ่งคุณสามารถจัดลำดับความสำคัญของการแก้ไขและดำลงในข้อมูลการวินิจฉัย

ต่อไปนี้เป็นสิ่งสำคัญที่ต้องพิจารณาเมื่อเลือกหรือสร้างระบบรายงานข้อขัดข้องพร้อมกับตัวอย่างโค้ด:

  • ตรวจจับข้อยกเว้นที่ไม่สามารถจัดการได้โดยอัตโนมัติ ( โค้ดตัวอย่าง )
  • รวบรวมข้อมูลการวินิจฉัยเช่นการใช้หน่วยความจำข้อมูลอุปกรณ์ ฯลฯ ( ตัวอย่างรหัส )
  • กลุ่มล้มเหลวอย่างมีประสิทธิภาพด้วยกันโดยสาเหตุที่แท้จริง
  • ช่วยให้คุณติดตามการกระทำที่ผู้ใช้ทำก่อนเกิดความผิดพลาดแต่ละครั้งเพื่อช่วยในการทำซ้ำ ( โค้ดตัวอย่าง )

หากคุณต้องการดูแนวทางปฏิบัติที่ดีที่สุดเกี่ยวกับการจัดการความผิดพลาด / การรายงานบน Android คุณสามารถตรวจสอบซอร์สโค้ดแบบเต็มสำหรับไลบรารีการรายงานข้อผิดพลาดของ Bugsnag ซึ่งเป็นโอเพ่นซอร์สแบบเต็มอย่าลังเลที่จะฉีกมันออกจากกัน


0

หากคนอื่นกำลังดาวน์โหลดแอปของคุณและหยุดทำงานบนอุปกรณ์ระยะไกลคุณอาจต้องการเข้าไปในห้องสมุดรายงานข้อผิดพลาดของ Android (อ้างอิงในโพสต์ SO นี้ ) หากเป็นเพียงอุปกรณ์ของคุณคุณสามารถใช้ LogCat แม้ว่าอุปกรณ์ไม่ได้เชื่อมต่อกับเครื่องโฮสต์เมื่อเกิดการขัดข้องให้เชื่อมต่ออุปกรณ์และการออกคำสั่ง adb logcat จะดาวน์โหลดประวัติ logcat ทั้งหมด (อย่างน้อยก็เท่าที่บัฟเฟอร์ซึ่งโดยปกติจะเป็น loooot ของข้อมูลบันทึก มันก็ไม่สิ้นสุด) ตัวเลือกเหล่านี้ตอบคำถามของคุณหรือไม่ หากคุณไม่สามารถพยายามชี้แจงสิ่งที่คุณกำลังมองหาอีกเล็กน้อย?


0

การวิเคราะห์ที่วุ่นวายช่วยให้คุณมีข้อมูลผิดพลาดรุ่นฮาร์ดแวร์รุ่น Android และสถิติการใช้งานแอปแบบสด ใน SDK ใหม่พวกเขาดูเหมือนจะให้ข้อมูลที่ผิดพลาดรายละเอียดเพิ่มเติมhttp://www.flurry.com/flurry-crash-analytics.html


8
ความวุ่นวาย จำกัด อยู่ที่ตัวละครจำนวนมากเท่านั้นและทำให้คุณไม่มีหมายเลขบรรทัดหรือคล้ายกัน
ไบรอันนี่นี่

0

Google เปลี่ยนจำนวนรายงานความผิดพลาดที่คุณได้รับจริง ก่อนหน้านี้คุณจะได้รับรายงานข้อผิดพลาดที่รายงานด้วยตนเองเท่านั้น

ตั้งแต่การประชุมนักพัฒนาครั้งล่าสุดและการแนะนำAndroid Vitalsคุณจะได้รับรายงานข้อขัดข้องจากผู้ใช้ที่เปิดใช้งานเพื่อแชร์ข้อมูลการวินิจฉัย

คุณจะเห็นข้อขัดข้องทั้งหมดที่รวบรวมจากอุปกรณ์ Android ที่ผู้ใช้เลือกใช้เพื่อแบ่งปันข้อมูลการใช้งานและการวินิจฉัยโดยอัตโนมัติ ข้อมูลพร้อมใช้งานสำหรับสองเดือนก่อนหน้า

ดูข้อผิดพลาดและแอปพลิเคชันไม่ตอบสนองข้อผิดพลาด (ANR)


logcat บอกว่ามีไฟล์ dump crash dump ใน /data/user/0/com.<myappname>/cache/WebView/Crash Report / <GUUID> .dmp แต่อุปกรณ์ไม่รูทและฉันไม่สามารถคิดได้ ดูวิธีการเข้าถึงไฟล์นี้!
Michael

0

คุณสามารถทำได้โดยตรงใน Android Studio เพียงเชื่อมต่อโทรศัพท์ของคุณรันแอพปล่อยให้มันพังและคุณสามารถดู stacktrace ได้โดยตรงใน Android Studio

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.