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

Hand-made Crash Report of Android Library

petitviolet
October 13, 2015

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 Slide

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

    View Slide

  3. ΫϥογϡϨϙʔτ

    View Slide

  4. View Slide

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

    View Slide

  6. crashlytics
    https://try.crashlytics.com/

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

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

    }

    }

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

    }

    }
    UncaughtExceptionHandlerΛܧঝ

    View Slide

  13. جຊ෦෼

    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 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;

    }

    }


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

    if (inLibraryException) {

    try {

    sendCrashReport(ex);

    } catch (Exception e) {

    e.printStackTrace();

    }

    }


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

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

    mDefaultHandler.uncaughtException(thread, ex);

    }

    }

    View 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;

    }

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

    View Slide

  16. @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 Slide

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

    if (inLibraryException) {

    try {

    sendCrashReport(ex);

    } catch (Exception e) {

    e.printStackTrace();

    }

    }


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

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

    mDefaultHandler.uncaughtException(thread, ex);

    }

    }

    View 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಺ͷΫϥογϡͳΒϩάૹ৴

    View Slide

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

    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 Slide

  20. جຊ෦෼
    @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 Slide

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

    View Slide