Android捕捉并收集未被程序处理的异常Exception

2014年11月19日 Android 13条评论 阅读8854次
Android捕捉并收集未被程序处理的异常Exception

在Android应用中,异常(Exception)/错误(Error)都是很常见的,为了让自己的android应用程序更加稳健、不至于很容易异常死掉,所以我们在程序中就要注意try-catch-final的使用。但无论如何,程序员总是对程序的所有异常错误都无法完全预知,这样就出现了程序极不友好的提示,给用户带来很不好的体验效果。而一旦发生了异常/错误的情况,只给程序员提供一个出错了的信息,相信诸程序员也只能无奈地摇头叹气。
基于上述问题,我们想要把未捕捉到的异常/错误信息及时保存到日志文件中,根据需要让用户提供日志文件或选择网络上传发送等。
其实,在java中jdk已经给我们提供了这样一个解决异常处理类。这就是java.lang.Thread.UncaughtExceptionHandler类。
自己只需写一个类来实现Thread.UncaughtExceptionHandler,具体未捕捉的异常处理就在uncaughtException里写就可以了。最后这个类只要在android应用的MainActivity或Application类中的onCreate中注册一次即可。
下面是一个写好的UncaughtExceptionHandler类,实现的功能就是程序遇到未知的异常时,通过Toast的形式向用户提示“很抱歉,程序出现异常,即将退出...”;同时向手机存储中制定文件夹的指定文件中保存出现异常时的设备信息(手机型号、手机生产厂商、OS版本、内核版本等)、时间、具体的StackTrace等信息;最后程序的结局肯定还是终止掉,或你可以根据自己的需求重新启动应用等。
得到出现异常的日志后,则可选择上传到网络服务器等操作了。
具体参照下面的代码。

package yourpackage;

import ......

public class CatchOtherExceptions implements Thread.UncaughtExceptionHandler {

    private static final String TAG = "CatchOtherExceptions";
    private static final String FOLDER = "Log";
    private static CatchOtherExceptions instance = null;
    private static Context mContext = null;

    // 系统默认的 UncaughtException 处理类
    private static Thread.UncaughtExceptionHandler mDefaultHandler;

    // 用来存储设备信息和异常信息
    private Map<String, String> infos = new HashMap<String, String>();

    // 用于格式化日期,作为日志文件名的一部分
    private DateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");

    private CatchOtherExceptions() {
    }

    public static CatchOtherExceptions getInstance(Context c) {
        mContext = c;
        if (instance == null) {
            instance = new CatchOtherExceptions();
        }

        // 获取系统默认的 UncaughtException 处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();

        return instance;
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (!handleException(ex) && mDefaultHandler != null) {
            // 如果用户没有处理则让系统默认的异常处理器来处理
            mDefaultHandler.uncaughtException(thread, ex);
        } else {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                Log.e(TAG, "error : ", e);
            }

            // 退出程序,注释下面的重启启动程序代码
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(1);

        }
    }

    /**
     * 自定义错误处理,收集错误信息,发送错误报告等操作均在此完成
     * 
     * @param ex
     * @return true:如果处理了该异常信息;否则返回 false
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }

        // 使用 Toast 来显示异常信息
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出...",
                        Toast.LENGTH_LONG).show();
                Looper.loop();
            }
        }.start();

        // 收集设备参数信息
        collectDeviceInfo(mContext);
        // 保存日志文件
        saveCrashInfo2File(ex);
        return true;
    }

    /**
     * 收集设备参数信息
     * 
     * @param ctx
     */
    public void collectDeviceInfo(Context ctx) {
        try {
            PackageManager pm = ctx.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),
                    PackageManager.GET_ACTIVITIES);

            if (pi != null) {
                String versionName = pi.versionName == null ? "null"
                        : pi.versionName;
                String versionCode = pi.versionCode + "";
                infos.put("versionName", versionName);
                infos.put("versionCode", versionCode);
            }
        } catch (NameNotFoundException e) {
            Log.e(TAG, "an error occured when collect package info", e);
        }

        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                infos.put(field.getName(), field.get(null).toString());
                Log.d(TAG, field.getName() + " : " + field.get(null));
            } catch (Exception e) {
                Log.e(TAG, "an error occured when collect crash info", e);
            }
        }
    }

    /**
     * 保存错误信息到文件中
     * 
     * @param ex
     * @return 返回文件名称,便于将文件传送到服务器
     */
    private String saveCrashInfo2File(Throwable ex) {
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String> entry : infos.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key + "=" + value + "\n");
        }

        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();

        String result = writer.toString();
        sb.append(result);
        try {
            long timestamp = System.currentTimeMillis();
            String time = formatter.format(new Date());
            String fileName = "crash-" + time + "-" + timestamp + ".log";

            if (Environment.getExternalStorageState().equals(
                    Environment.MEDIA_MOUNTED)) {
                String path = Environment.getExternalStorageDirectory()
                        .getPath() + File.separator + FOLDER;
                File dir = new File(path);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                FileOutputStream fos = new FileOutputStream(path
                        + File.separator + fileName);
                fos.write(sb.toString().getBytes());
                fos.close();
            }

            return fileName;
        } catch (Exception e) {
            Log.e(TAG, "an error occured while writing file...", e);
        }

        return null;
    }
}
在MainActivity或应用程序的Application类的onCreate方法中加入下面的代码

Thread.setDefaultUncaughtExceptionHandler(CatchOtherExceptions.getInstance((this)));


各位在使用的时候,可能需要修改的就是要保存的路径,上面的例子是直接存到了存储的Log文件夹中。

文末,有问题欢迎提出。

分享本文至:

WRITTEN BY

avatar
本文标签:exception
看了本文是不是觉得很赞,那就赶紧点击下面按钮分享给身边的朋友吧!

13 条评论

  1. <a href="http://www.hkyahao.com/salomon-s-lab-fellcross-gr%C3%A5-rosa-skoe">salomon s lab fellcross gr氓 rosa</a> <a href="http://www.innordicau.com/carmelo-anthony-kids-jersey-nflh">carmelo anthony kids jersey</a> <a href="http://www.rahdanesh.com/giannis-antetokounmpo-all-star-jersey-nfli">giannis antetokounmpo all star jersey</a> <a href="http://www.myprontocard.com/chicago-bulls-jersey-dress-23-nflh">chicago bulls jersey dress 23</a> <a href="http://www.eldiadeitalia.com/nike-mercurial-vapor-9-gul-oransje-shoese">nike mercurial vapor 9 gul oransje</a> <a href="http://www.lapakhoki.com/wimbledon-umpire-pima-sweater-polo-tennis-v-neck-ralphlaurenmen-shorts-poloh">wimbledon umpire pima sweater polo tennis v neck ralphlaurenmen shorts</a>
    valethelp http://www.valethelp.com/

  2. <a href="http://www.retailnav.com/men-adidas-springblade-drive-2.0-black-sliver-shoesk">men adidas springblade drive 2.0 black sliver</a> <a href="http://www.merleflugge.com/ray-ban-round-metal-blue-polarized-sunglassesh">ray ban round metal blue polarized</a> <a href="http://www.airfarelinks.com/adidas-zx-flux-or-gris-chaussuresl">adidas zx flux or gris</a> <a href="http://www.vidiyow.com/james-harden-tout-blanc-adidas-chaussuresl">james harden tout blanc adidas</a> <a href="http://www.quiveutdescds.com/billignike-mercurial-superfly-fg-blau-lagoon-wei%C3%9F-volt-schwarz-schuhej">billignike mercurial superfly fg blau lagoon wei脽 volt schwarz</a> <a href="http://www.wapkaa.com/adidas-originals-samba-schwarz-schuhei">adidas originals samba schwarz</a>
    zeuslazer http://www.zeuslazer.com/

  3. avatar nowaitnails

    <a href="http://www.laketreepress.com/nike-flyknit-lunar-3-dam%C3%A4nner-rot-lila-schuhei">nike flyknit lunar 3 dam盲nner rot lila</a> <a href="http://www.prohaarklinik.com/air-jordan-retro-1-silber-rot-schuheh">air jordan retro 1 silber rot</a> <a href="http://www.bonfanticare.com/nike-roshe-run-hyperfuse-r%C3%B8d-rosa-obuvj">nike roshe run hyperfuse r酶d rosa</a> <a href="http://www.antoniopagni.com/femminile-nike-roshe-run-triangle-nero-grigio-scarpep">femminile nike roshe run triangle nero grigio</a> <a href="http://www.wcshosting.com/air-jordan-eclipse-bleu-ciel-blanc-chaussuresh">air jordan eclipse bleu ciel blanc</a> <a href="http://www.biddingstream.com/prada-gold-wallet-pradah">prada gold wallet</a>
    nowaitnails http://www.nowaitnails.com/

  4. avatar pngoilgas

    <a href="http://www.lvnailbar.com/nike-mercurial-rosa-and-s%C3%B8lv-obuvk">nike mercurial rosa and s酶lv</a> <a href="http://www.eisenhards.com/femminile-asics-gel-kinsei-5-grigio-argento-scarpei">femminile asics gel kinsei 5 grigio argento</a> <a href="http://www.martinmakeup.com/adidas-rose-7-naranja-zapatosh">adidas rose 7 naranja</a> <a href="http://www.dgrabovsky.com/herre-under-armour-curry-4-gul-skok">herre under armour curry 4 gul</a> <a href="http://www.madeinmyindia.com/nike-air-force-1-duckboot-2013-brun-gr%C3%B8nn-obuvi">nike air force 1 duckboot 2013 brun gr酶nn</a> <a href="http://www.manglammovers.com/adidas-originals-tubular-radial-zapatillas-in-blanco-zapatosl">adidas originals tubular radial zapatillas in blanco</a>
    pngoilgas http://www.pngoilgas.com/

  5. avatar flushandhunt

    <a href="http://www.flushnhunt.com/lacoste-classic-long-sleeve-polo-poloh">lacoste classic long sleeve polo</a> <a href="http://www.evelpa.com/womens-asics-gel-noosa-tri-10-pink-silver-shoesi">womens asics gel noosa tri 10 pink silver</a> <a href="http://www.taaliminfos.com/adidas-tubular-runner-silver-red-shoesk">adidas tubular runner silver red</a> <a href="http://www.cacikvideo.com/nike-air-yeezy-2-bl%C3%A5-gull-obuvq">nike air yeezy 2 bl氓 gull</a> <a href="http://www.grossavind.com/nike-air-force-1-bl%C3%A5-tick-skoj">nike air force 1 bl氓 tick</a> <a href="http://www.boltsfans.com/nike-air-max-90-essential-arancia-scarpeq">nike air max 90 essential arancia</a>
    flushandhunt http://www.flushandhunt.com/

  6. avatar lemodemo

    <a href="http://www.poppiesdelray.com/south-carolina-gamecocks-new-era-ncaa-tonal-tint-39thirty-cap-hatj">south carolina gamecocks new era ncaa tonal tint 39thirty cap</a> <a href="http://www.soundsofbuzz.com/maschio-nike-air-max-invigor-print-grigio-scarpej">maschio nike air max invigor print grigio</a> <a href="http://www.hozloli.com/m%C3%A4nner-mizuno-neo-ii-fg-gelb-schwarz-schuhei">m盲nner mizuno neo ii fg gelb schwarz</a> <a href="http://www.privetaustria.com/nike-air-max-neon-gul-2013-skoh">nike air max neon gul 2013</a> <a href="http://www.goodnnasty.com/cam-newton-jersey-for-girls-nfli">cam newton jersey for girls</a> <a href="http://www.ankarasanal.com/nike-air-max-tn-gull-svart-obuvk">nike air max tn gull svart</a>
    lemodemo http://www.lemodemo.com/

  7. avatar ayakkabiyeri

    <a href="http://www.hutchinsmedia.com/adidas-ultra-boost-gris-off-blanco-zapatosl">adidas ultra boost gris off blanco</a> <a href="http://www.datesfordate.com/oakley-radarlock-path-matte-black-yellow-frame-and-grey-iridium-lens-sunglassesh">oakley radarlock path matte black yellow frame and grey iridium lens</a> <a href="http://www.spchemtech.com/orlando-magic-new-era-nba-team-metallic-9fifty-snapback-cap-hatj">orlando magic new era nba team metallic 9fifty snapback cap</a> <a href="http://www.eadamattia.com/maschio-nike-air-force-1-mid-bianca-scarpej">maschio nike air force 1 mid bianca</a> <a href="http://www.citypixxel.com/nike-huarache-utility-blau-schuhei">nike huarache utility blau</a> <a href="http://www.megasatinc.com/m%C3%A6nd-nike-air-max-2016-gr%C3%B8n-sort-bl%C3%A5-skoh">m忙nd nike air max 2016 gr酶n sort bl氓</a>
    ayakkabiyeri http://www.ayakkabiyeri.com/

  8. avatar dexterbowl

    <a href="http://www.katieirene.com/nike-lunar-eclipse-4-femminile-in-esecuzione-scarpe-kurpesa">nike lunar eclipse 4 femminile in esecuzione scarpe</a> <a href="http://www.klimafeuer.com/nike-roshe-run-premium-wei%C3%9F-schwarz-edition-schuhed">nike roshe run premium wei脽 schwarz edition</a> <a href="http://www.kennethmarrin.com/nike-zoom-vomero-mujeres-amarillo-blanco-kurpesb">nike zoom vomero mujeres amarillo blanco</a> <a href="http://www.akashkataria.com/vibram-fivefingers-komodo-oro-nero-kurpesa">vibram fivefingers komodo oro nero</a> <a href="http://www.fariselmasu.com/new-blance-ni%C3%B1os-zapatos-negro-naranja-obuvb">new blance ni帽os zapatos negro naranja</a> <a href="http://www.cleanopoly.com/nike-zoom-structure-19-kvinders-guld-hvid-kurpesa">nike zoom structure 19 kvinders guld hvid</a>
    [url=http://www.dexterbowl.com/]dexterbowl[/url]

  9. avatar cksholdings

    <a href="http://www.taiwanmeinet.com/all-r%C3%B8d-kvinners-nike-air-max-obuvj">all r酶d kvinners nike air max</a> <a href="http://www.talkwithgirl.com/nike-free-run-2-femminile-rosa-scarpel">nike free run 2 femminile rosa</a> <a href="http://www.mamatale.com/kd-8-femmes-vert-violet-chaussuresh">kd 8 femmes vert violet</a> <a href="http://www.strongtale.com/nike-air-max-1-dark-ash-dark-grigio-light-blu-scarpeh">nike air max 1 dark ash dark grigio light blu</a> <a href="http://www.iranpayamco.com/youth-anaheim-ducks-ryan-getzlaf-reebok-orange-alternate-replica-jersey-2-nfli">youth anaheim ducks ryan getzlaf reebok orange alternate replica jersey 2</a> <a href="http://www.hapeid.com/nike-air-max-90-ultra-essential-todas-negro-zapatosh">nike air max 90 ultra essential todas negro</a>
    cksholdings http://www.cksholdings.com/

  10. avatar Essay Yulan

    有一个你可以连接到mysql的Mysql包,可以学习如何连接这个阶段。享受更好的时间安装这个最佳区域的时间。你也可以在这里享受美好的环境。

  11. avatar 鞍山妇科医院

    感谢楼主分享,收藏了慢慢看,慢慢学

  12. avatar LED display

    博主是专门开发android的吗,好厉害哇。

  13. avatar 琉璃瓦

    博主高手啊。来看看博主。加油

欢迎留言




用户登录

sitemap