Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Hand-made Crash Report of Android Library

Hand-made Crash Report of Android Library

http://connpass.com/event/20240/
How to implement crash report of Android-Library

petitviolet

October 13, 2015
Tweet

More Decks by petitviolet

Other Decks in Technology

Transcript

  1. Hand-made CrashReport
    of
    Android Library
    potatotips #22
    @petitviolet

    View full-size slide

  2. About me
    • @petitviolet
    • Fringe81 Co., Ltd.
    • ޿ࠂSDKͷAndroid/iOS։ൃ
    • ࠷ۙ͸Scalaॻ͍ͯ·͢

    View full-size slide

  3. ΫϥογϡϨϙʔτ

    View full-size slide

  4. CrashReport
    • ΞϓϦέʔγϣϯ͕Ϋϥογϡͨ࣌͠ͷঢ়گ
    ΛϨϙʔτͱͯ͠ૹ৴
    • ୺຤ͷछྨ
    • OS
    • ελοΫτϨʔε
    • etc.

    View full-size slide

  5. crashlytics
    https://try.crashlytics.com/

    View full-size slide

  6. ACRA
    https://github.com/ACRA/acra

    View full-size slide

  7. Desire
    • ϥΠϒϥϦىҼͷΫϥογϡϩά΋ऩू͍ͨ͠
    • ΞϓϦͷΫϥογϡϩά͸ऩू͠ͳ͍
    • ͦΕ͸Crashlytics౳ʹ͓೚ͤ
    • ಠࣗͷσʔλ͕ཉ͍͠

    View full-size slide

  8. UncaughtException
    • (جຊతʹ)Ϋϥογϡ͢Δͱ͖ʹඈͿྫ֎
    • catch͞Εͳ͔ͬͨͷͰuncaught
    • ErrorͰ͸ͳ͘Exception

    View full-size slide

  9. UncaughtExceptionHandler
    • UncaughtExceptionΛͲ͏ѻ͏͔
    • σϑΥϧτͷಈ࡞͸
    getDefaultUncaughtExceptionHandler
    • Defaultͷಈ࡞Λյ͞ͳ͍ͨΊʹอଘ

    View full-size slide

  10. جຊ෦෼

    class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {

    private static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID;


    private final Thread.UncaughtExceptionHandler mDefaultHandler;

    private WeakReference mContext;

    volatile private static boolean sCrashing = false;


    public MyUncaughtExceptionHandler(Context context) {

    mContext = new WeakReference<>(context.getApplicationContext());

    mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();

    }

    }

    View full-size slide

  11. جຊ෦෼

    class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {

    private static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID;


    private final Thread.UncaughtExceptionHandler mDefaultHandler;

    private WeakReference mContext;

    volatile private static boolean sCrashing = false;


    public MyUncaughtExceptionHandler(Context context) {

    mContext = new WeakReference<>(context.getApplicationContext());

    mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();

    }

    }
    UncaughtExceptionHandlerΛܧঝ

    View full-size slide

  12. جຊ෦෼

    class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {

    private static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID;


    private final Thread.UncaughtExceptionHandler mDefaultHandler;

    private WeakReference mContext;

    volatile private static boolean sCrashing = false;


    public MyUncaughtExceptionHandler(Context context) {

    mContext = new WeakReference<>(context.getApplicationContext());

    mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();

    }

    }
    DefaultͷUncaughtExceptionHandlerΛอଘ
    UncaughtExceptionHandlerΛܧঝ

    View full-size slide

  13. جຊ෦෼
    @Override

    public void uncaughtException(final Thread thread, final Throwable ex) {

    if (sCrashing) {

    mDefaultHandler.uncaughtException(thread, ex);

    return;

    }

    sCrashing = true;

    StackTraceElement[] stackTraceElements = ex.getStackTrace();


    boolean inLibraryException = false;

    for (StackTraceElement stackTraceElement : stackTraceElements) {

    if (stackTraceElement.getClassName().contains(PACKAGE_NAME)) {

    inLibraryException = true;

    break;

    }

    }


    // ϥΠϒϥϦ಺ͰͷΫϥογϡͩͬͨ৔߹͸ϩάΛૹΔ

    if (inLibraryException) {

    try {

    sendCrashReport(ex);

    } catch (Exception e) {

    e.printStackTrace();

    }

    }


    // ϝΠϯεϨουͩͬͨ৔߹͸ࢮ͵͔͠ແ͍

    if (thread.getId() == Looper.getMainLooper().getThread().getId()
    || !inLibraryException) {

    mDefaultHandler.uncaughtException(thread, ex);

    }

    }

    View full-size slide

  14. @Override

    public void uncaughtException(final Thread thread, final Throwable ex) {

    if (sCrashing) {

    mDefaultHandler.uncaughtException(thread, ex);

    return;

    }

    sCrashing = true;

    StackTraceElement[] stackTraceElements = ex.getStackTrace();


    boolean inLibraryException = false;

    for (StackTraceElement stackTraceElement : stackTraceElements) {

    if (stackTraceElement.getClassName().contains(PACKAGE_NAME)) {

    inLibraryException = true;

    break;

    }

    }
    ͢ͰʹΫϥογϡͨ͠ޙͳΒࢮ͵

    View full-size slide

  15. @Override

    public void uncaughtException(final Thread thread, final Throwable ex) {

    if (sCrashing) {

    mDefaultHandler.uncaughtException(thread, ex);

    return;

    }

    sCrashing = true;

    StackTraceElement[] stackTraceElements = ex.getStackTrace();


    boolean inLibraryException = false;

    for (StackTraceElement stackTraceElement : stackTraceElements) {

    if (stackTraceElement.getClassName().contains(PACKAGE_NAME)) {

    inLibraryException = true;

    break;

    }

    }
    ͢ͰʹΫϥογϡͨ͠ޙͳΒࢮ͵
    Library಺ͷΫϥογϡ͔Ͳ͏͔൑ఆ

    View full-size slide

  16. // ϥΠϒϥϦ಺ͰͷΫϥογϡͩͬͨ৔߹͸ϩάΛૹΔ

    if (inLibraryException) {

    try {

    sendCrashReport(ex);

    } catch (Exception e) {

    e.printStackTrace();

    }

    }


    // ϝΠϯεϨουͩͬͨ৔߹͸ࢮ͵͔͠ແ͍

    if (thread.getId() == Looper.getMainLooper().getThread().getId()
    || !inLibraryException) {

    mDefaultHandler.uncaughtException(thread, ex);

    }

    }

    View full-size slide

  17. // ϥΠϒϥϦ಺ͰͷΫϥογϡͩͬͨ৔߹͸ϩάΛૹΔ

    if (inLibraryException) {

    try {

    sendCrashReport(ex);

    } catch (Exception e) {

    e.printStackTrace();

    }

    }


    // ϝΠϯεϨουͩͬͨ৔߹͸ࢮ͵͔͠ແ͍

    if (thread.getId() == Looper.getMainLooper().getThread().getId()
    || !inLibraryException) {

    mDefaultHandler.uncaughtException(thread, ex);

    }

    }
    Library಺ͷΫϥογϡͳΒϩάૹ৴

    View full-size slide

  18. // ϥΠϒϥϦ಺ͰͷΫϥογϡͩͬͨ৔߹͸ϩάΛૹΔ

    if (inLibraryException) {

    try {

    sendCrashReport(ex);

    } catch (Exception e) {

    e.printStackTrace();

    }

    }


    // ϝΠϯεϨουͩͬͨ৔߹͸ࢮ͵͔͠ແ͍

    if (thread.getId() == Looper.getMainLooper().getThread().getId()
    || !inLibraryException) {

    mDefaultHandler.uncaughtException(thread, ex);

    }

    }
    Library֎ͷΫϥογϡ͔UIεϨουͳΒࢮ͵
    Library಺ͷΫϥογϡͳΒϩάૹ৴

    View full-size slide

  19. جຊ෦෼
    @Override

    public void uncaughtException(final Thread thread, final Throwable ex) {

    if (sCrashing) {

    mDefaultHandler.uncaughtException(thread, ex);

    return;

    }

    sCrashing = true;

    StackTraceElement[] stackTraceElements = ex.getStackTrace();


    boolean inLibraryException = false;

    for (StackTraceElement stackTraceElement : stackTraceElements) {

    if (stackTraceElement.getClassName().contains(PACKAGE_NAME)) {

    inLibraryException = true;

    break;

    }

    }


    // ϥΠϒϥϦ಺ͰͷΫϥογϡͩͬͨ৔߹͸ϩάΛૹΔ

    if (inLibraryException) {

    try {

    sendCrashReport(ex);

    } catch (Exception e) {

    e.printStackTrace();

    }

    }


    // ϝΠϯεϨουͩͬͨ৔߹͸ࢮ͵͔͠ແ͍

    if (thread.getId() == Looper.getMainLooper().getThread().getId()
    || !inLibraryException) {

    mDefaultHandler.uncaughtException(thread, ex);

    }

    }
    Library಺ͷΫϥογϡ͔Ͳ͏͔൑ఆ
    Library಺ͷΫϥογϡͳΒϩάૹ৴
    Library֎ͷΫϥογϡ͔UIεϨουͳΒࢮ͵
    ͢ͰʹΫϥογϡͨ͠ޙͳΒࢮ͵

    View full-size slide

  20. େࣄͳ͜ͱ
    • ϥΠϒϥϦ΋ΫϥογϡϩάΈͯվળ
    • ΞϓϦͷअຐΛ͠ͳ͍
    • σϑΥϧτͷಈ࡞Λࡴ͞ͳ͍
    • ϑϦʔζͤ͞ͳ͍Α͏ʹ
    • ແݶΫϥογϡ͠ͳ͍Α͏ʹ؅ཧ
    • ໘౗Ͱ΋ϑϥά؅ཧ

    View full-size slide