AG环亚娱乐_AG直营网_环亚娱乐AG最佳线路_搜狐新闻
web技术

热门文章

当前位置:主页 > 热门文章 >

联系我们

CONTACT

地址:
电话:
传真:
邮箱:

Android程序崩溃异常收集框架

2019-01-26

最近在写Android程序崩溃异常处理,完成之后,稍加封装与大家分享。

我的思路是这样的,在程序崩溃之后,将异常信息保存到一个日志文件中,然后对该文件进行处理,比如发送到邮箱,或发送到服务器。

所以,第一步是先定义一个接口,用于在保存好日志之后的回调。代码如下:

//网易新闻uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 @(#)CrashListener.java		       Project: crash
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Date:2014-5-27
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Copyright (c) 2014 CFuture09, Institute of Software, 
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Guangdong Ocean University, Zhanjiang, GuangDong, China.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 All rights reserved.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Licensed under the Apache License, Version 2.0 (the "License");
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850  you may not use this file except in compliance with the License.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 You may obtain a copy of the License at
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850     http://www.apache.org/licenses/LICENSE-2.0
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Unless required by applicable law or agreed to in writing, software
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 distributed under the License is distributed on an "AS IS" BASIS,
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 See the License for the specific language governing permissions and
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 limitations under the License.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850/
package com.githang.android.crash;

import java.io.File;

//uploads/allimg/181014/20181014113040nhrgeegpyia1850/uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 @author Geek_Soledad 
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850/
public interface CrashListener {
    //uploads/allimg/181014/20181014113040nhrgeegpyia1850/uploads/allimg/181014/20181014113040nhrgeegpyia1850
     /uploads/allimg/181014/20181014113040nhrgeegpyia1850 保存异常的日志。
     /uploads/allimg/181014/20181014113040nhrgeegpyia1850 
     /uploads/allimg/181014/20181014113040nhrgeegpyia1850 @param file
     /uploads/allimg/181014/20181014113040nhrgeegpyia1850/
    public void afterSaveCrash(File file);
}

接下来是用于处理崩溃异常的类,它要实现UncaughtExceptionHandler接口。实现它之后,将它设为默认的线程异常的处理者,这样程序崩溃之后,就会调用它了。但是在调用它之前,还需要先获取保存之前默认的handler,用于在我们收集了异常之后对程序进行处理,比如默认的弹出“程序已停止运行”的对话框(当然你也可以自己实现一个),终止程序,打印LOG。

我的实现如下:

//uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 @(#)CrashHandler.java		       Project: crash
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Date:2014-5-26
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Copyright (c) 2014 CFuture09, Institute of Software, 
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Guangdong Ocean University, Zhanjiang, GuangDong, China.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 All rights reserved.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Licensed under the Apache License, Version 2.0 (the "License");
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850  you may not use this file except in compliance with the License.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 You may obtain a copy of the License at
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850     http://www.apache.org/licenses/LICENSE-2.0
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Unless required by applicable law or agreed to in writing, software
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 distributed under the License is distributed on an "AS IS" BASIS,
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 See the License for the specific language governing permissions and
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 limitations under the License.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850/
package com.githang.android.crash;

import java.io.File;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

//uploads/allimg/181014/20181014113040nhrgeegpyia1850/uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 @author Geek_Soledad 
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850/
public class CrashHandler implements UncaughtExceptionHandler {
    private static final CrashHandler sHandler = new CrashHandler();
    private static final UncaughtExceptionHandler sDefaultHandler = Thread
            .getDefaultUncaughtExceptionHandler();
    private static final ExecutorService THREAD_POOL = Executors.newSingleThreadExecutor();
    private Future future;
    private CrashListener mListener;
    private File mLogFile;

    public static CrashHandler getInstance() {
        return sHandler;
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        CrashLogUtil.writeLog(mLogFile, "CrashHandler", ex.getMessage(), ex);
        future = THREAD_POOL.submit(new Runnable() {
            public void run() {
                if (mListener != null) {
                    mListener.afterSaveCrash(mLogFile);
                }
            };
        });
        if (!future.isDone()) {
            try {
                future.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        sDefaultHandler.uncaughtException(thread, ex);
    }

    public void init(File logFile, CrashListener listener) {
        mLogFile = logFile;
        mListener = listener;
    }

}

这个类很简单,就是在发生未能捕获的异常之后,保存LOG到文件,然后 调用前面定义的接口,对日志文件进行处理。其中CrashLogUtil是我实现的保存LOG到文件的类。代码如下:
//uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 @(#)LogUtil.java		       Project: crash
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Date:2014-5-27
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Copyright (c) 2014 CFuture09, Institute of Software, 
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Guangdong Ocean University, Zhanjiang, GuangDong, China.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 All rights reserved.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Licensed under the Apache License, Version 2.0 (the "License");
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850  you may not use this file except in compliance with the License.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 You may obtain a copy of the License at
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850     http://www.apache.org/licenses/LICENSE-2.0
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Unless required by applicable law or agreed to in writing, software
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 distributed under the License is distributed on an "AS IS" BASIS,
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 See the License for the specific language governing permissions and
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 limitations under the License.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850/
package com.githang.android.crash;

import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;

//uploads/allimg/181014/20181014113040nhrgeegpyia1850/uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 @author Geek_Soledad 
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850/
public class CrashLogUtil {
    private static final SimpleDateFormat timeFormat = new SimpleDateFormat("MM-dd HH:mm:ss.SSS",
            Locale.getDefault());

    //uploads/allimg/181014/20181014113040nhrgeegpyia1850/uploads/allimg/181014/20181014113040nhrgeegpyia1850
     /uploads/allimg/181014/20181014113040nhrgeegpyia1850 将日志写入文件。
     /uploads/allimg/181014/20181014113040nhrgeegpyia1850 
     /uploads/allimg/181014/20181014113040nhrgeegpyia1850 @param tag
     /uploads/allimg/181014/20181014113040nhrgeegpyia1850 @param message
     /uploads/allimg/181014/20181014113040nhrgeegpyia1850 @param tr
     /uploads/allimg/181014/20181014113040nhrgeegpyia1850/
    public static synchronized void writeLog(File logFile, String tag, String message, Throwable tr) {
        logFile.getParentFile().mkdirs();
        if (!logFile.exists()) {
            try {
                logFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        String time = timeFormat.format(Calendar.getInstance().getTime());
        synchronized (logFile) {
            FileWriter fileWriter = null;
            BufferedWriter bufdWriter = null;
            PrintWriter printWriter = null;
            try {
                fileWriter = new FileWriter(logFile, true);
                bufdWriter = new BufferedWriter(fileWriter);
                printWriter = new PrintWriter(fileWriter);
                bufdWriter.append(time).append(" ").append("E").append('/').append(tag).append(" ")
                        .append(message).append('
');
                bufdWriter.flush();
                tr.printStackTrace(printWriter);
                printWriter.flush();
                fileWriter.flush();
            } catch (IOException e) {
                closeQuietly(fileWriter);
                closeQuietly(bufdWriter);
                closeQuietly(printWriter);
            }
        }
    }

    public static void closeQuietly(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException ioe) {
                // ignore
            }
        }
    }
}

在日志保存之后,我们还需要生成一个报告,并发送给服务器。报告的方法,可以是发送到邮箱,或者http请求发送给服务器。所以这里写了一个抽象类,实现了生成标题和内容,设置日志路径等。代码如下:

//uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 @(#)AbstractReportHandler.java		       Project: crash
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Date:2014-5-27
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Copyright (c) 2014 CFuture09, Institute of Software, 
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Guangdong Ocean University, Zhanjiang, GuangDong, China.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 All rights reserved.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Licensed under the Apache License, Version 2.0 (the "License");
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850  you may not use this file except in compliance with the License.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 You may obtain a copy of the License at
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850     http://www.apache.org/licenses/LICENSE-2.0
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Unless required by applicable law or agreed to in writing, software
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 distributed under the License is distributed on an "AS IS" BASIS,
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 See the License for the specific language governing permissions and
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 limitations under the License.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850/
package com.githang.android.crash;

import java.io.File;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;

//uploads/allimg/181014/20181014113040nhrgeegpyia1850/uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 @author Geek_Soledad 
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850/
public abstract class AbstractCrashReportHandler implements CrashListener {
    private Context mContext;

    public AbstractCrashReportHandler(Context context) {
        mContext = context;
        CrashHandler handler = CrashHandler.getInstance();
        handler.init(getLogDir(context), this);
        Thread.setDefaultUncaughtExceptionHandler(handler);
    }

    protected File getLogDir(Context context) {
        return new File(context.getFilesDir(), "crash.log");
    }

    protected abstract void sendReport(String title, String body, File file);

    @Override
    public void afterSaveCrash(File file) {
        sendReport(buildTitle(mContext), buildBody(mContext), file);
    }

    public String buildTitle(Context context) {
        return "Crash Log: "
                + context.getPackageManager().getApplicationLabel(context.getApplicationInfo());
    }

    public String buildBody(Context context) {
        StringBuilder sb = new StringBuilder();

        sb.append("APPLICATION INFORMATION").append('
');
        PackageManager pm = context.getPackageManager();
        ApplicationInfo ai = context.getApplicationInfo();
        sb.append("Application : ").append(pm.getApplicationLabel(ai)).append('
');

        try {
            PackageInfo pi = pm.getPackageInfo(ai.packageName, 0);
            sb.append("Version Code: ").append(pi.versionCode).append('
');
            sb.append("Version Name: ").append(pi.versionName).append('
');
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        sb.append('
').append("DEVICE INFORMATION").append('
');
        sb.append("Board: ").append(Build.BOARD).append('
');
        sb.append("BOOTLOADER: ").append(Build.BOOTLOADER).append('
');
        sb.append("BRAND: ").append(Build.BRAND).append('
');
        sb.append("CPU_ABI: ").append(Build.CPU_ABI).append('
');
        sb.append("CPU_ABI2: ").append(Build.CPU_ABI2).append('
');
        sb.append("DEVICE: ").append(Build.DEVICE).append('
');
        sb.append("DISPLAY: ").append(Build.DISPLAY).append('
');
        sb.append("FINGERPRINT: ").append(Build.FINGERPRINT).append('
');
        sb.append("HARDWARE: ").append(Build.HARDWARE).append('
');
        sb.append("HOST: ").append(Build.HOST).append('
');
        sb.append("ID: ").append(Build.ID).append('
');
        sb.append("MANUFACTURER: ").append(Build.MANUFACTURER).append('
');
        sb.append("PRODUCT: ").append(Build.PRODUCT).append('
');
        sb.append("TAGS: ").append(Build.TAGS).append('
');
        sb.append("TYPE: ").append(Build.TYPE).append('
');
        sb.append("USER: ").append(Build.USER).append('
');

        return sb.toString();
    }
}

这样一个框架就算基本完成了。

当然,下面我还给出了报告的一种实现,发送邮件。

如何发送邮箱,网上已有不少资料,这里不再简而言之。

首先需要用到三个jar包: activation.jar, additionnal.jar, mail.jar。

然后 写一个类,继承自Authenticator。代码如下:

//uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 @(#)Snippet.java		       Project: CrashHandler
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Date: 2014-5-27
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Copyright (c) 2014 CFuture09, Institute of Software, 
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Guangdong Ocean University, Zhanjiang, GuangDong, China.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 All rights reserved.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Licensed under the Apache License, Version 2.0 (the "License");
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850  you may not use this file except in compliance with the License.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 You may obtain a copy of the License at
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850     http://www.apache.org/licenses/LICENSE-2.0
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Unless required by applicable law or agreed to in writing, software
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 distributed under the License is distributed on an "AS IS" BASIS,
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 See the License for the specific language governing permissions and
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 limitations under the License.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850/
package com.githang.android.crash;

import android.util.Log;

import java.util.Date;
import java.util.Properties;

import javax.activation.CommandMap;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.activation.MailcapCommandMap;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

//uploads/allimg/181014/20181014113040nhrgeegpyia1850/uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Author: msdx ([email protected]) Time: 14-5-27 上午9:07
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850/
public class LogMail extends Authenticator {
    private String host;
    private String port;
    private String user;
    private String pass;
    private String from;
    private String to;
    private String subject;
    private String body;

    private Multipart multipart;
    private Properties props;

    public LogMail() {
    }

    public LogMail(String user, String pass, String from, String to, String host, String port,
            String subject, String body) {
        this.host = host;
        this.port = port;
        this.user = user;
        this.pass = pass;
        this.from = from;
        this.to = to;
        this.subject = subject;
        this.body = body;
    }

    public LogMail setHost(String host) {
        this.host = host;
        return this;
    }

    public LogMail setPort(String port) {
        this.port = port;
        return this;
    }

    public LogMail setUser(String user) {
        this.user = user;
        return this;
    }

    public LogMail setPass(String pass) {
        this.pass = pass;
        return this;
    }

    public LogMail setFrom(String from) {
        this.from = from;
        return this;
    }

    public LogMail setTo(String to) {
        this.to = to;
        return this;
    }

    public LogMail setSubject(String subject) {
        this.subject = subject;
        return this;
    }

    public LogMail setBody(String body) {
        this.body = body;
        return this;
    }

    public void init() {
        multipart = new MimeMultipart();
        // There is something wrong with MailCap, javamail can not find a
        // handler for the multipart/mixed part, so this bit needs to be added.
        MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
        mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
        mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
        mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
        mc.addMailcap("multipart//uploads/allimg/181014/20181014113040nhrgeegpyia1850;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
        mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
        CommandMap.setDefaultCommandMap(mc);

        props = new Properties();

        props.put("mail.smtp.host", host);
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.port", port);
        props.put("mail.smtp.socketFactory.port", port);
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        props.put("mail.smtp.socketFactory.fallback", "false");
    }

    public boolean send() throws MessagingException {
        if (!user.equals("") && !pass.equals("") && !to.equals("") && !from.equals("")) {
            Session session = Session.getDefaultInstance(props, this);
            Log.d("SendUtil", host + "..." + port + ".." + user + "..." + pass);

            MimeMessage msg = new MimeMessage(session);

            msg.setFrom(new InternetAddress(from));

            InternetAddress addressTo = new InternetAddress(to);
            msg.setRecipient(MimeMessage.RecipientType.TO, addressTo);

            msg.setSubject(subject);
            msg.setSentDate(new Date());

            // setup message body
            BodyPart messageBodyPart = new MimeBodyPart();
            messageBodyPart.setText(body);
            multipart.addBodyPart(messageBodyPart);

            // Put parts in message
            msg.setContent(multipart);

            // send email
            Transport.send(msg);

            return true;
        } else {
            return false;
        }
    }

    public void addAttachment(String filePath, String fileName) throws Exception {
        BodyPart messageBodyPart = new MimeBodyPart();
        DataSource source = new FileDataSource(filePath);
        messageBodyPart.setDataHandler(new DataHandler(source));
        messageBodyPart.setFileName(fileName);
        multipart.addBodyPart(messageBodyPart);
    }

    @Override
    public PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(user, pass);
    }
}
然后是发送报告邮件的类了,它继承自前面所写的AbstractCrashReportHandler,实现如下:

//uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 @(#)CrashEmailReport.java		       Project: CrashHandler
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Date: 2014-5-27
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Copyright (c) 2014 CFuture09, Institute of Software, 
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Guangdong Ocean University, Zhanjiang, GuangDong, China.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 All rights reserved.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Licensed under the Apache License, Version 2.0 (the "License");
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850  you may not use this file except in compliance with the License.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 You may obtain a copy of the License at
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850     http://www.apache.org/licenses/LICENSE-2.0
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 Unless required by applicable law or agreed to in writing, software
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 distributed under the License is distributed on an "AS IS" BASIS,
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 See the License for the specific language governing permissions and
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 limitations under the License.
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850/
package com.githang.android.crash;

import java.io.File;

import android.content.Context;

//uploads/allimg/181014/20181014113040nhrgeegpyia1850/uploads/allimg/181014/20181014113040nhrgeegpyia1850
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850 @author Geek_Soledad 
 /uploads/allimg/181014/20181014113040nhrgeegpyia1850/
public class CrashEmailReport extends AbstractCrashReportHandler {
    private String mReceiveEmail;

    public CrashEmailReport(Context context) {
        super(context);
    }

    public void setReceiver(String receiveEmail) {
        mReceiveEmail = receiveEmail;
    }
    
    @Override
    protected void sendReport(String title, String body, File file) {
        LogMail sender = new LogMail().setUser("[email protected]").setPass("xxxxxxxx")
                .setFrom("[email protected]").setTo(mReceiveEmail).setHost("smtp.163.com")
                .setPort("465").setSubject(title).setBody(body);
        sender.init();
        try {
            sender.addAttachment(file.getPath(), file.getName());
            sender.send();
            file.delete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这样,一个完整的程序崩溃异常框架就完成了。对于日志报告,可自己继承AbstractCrashReportHandler来扩展实现。

使用的时候,需要写一个继承自Application的类,在onCreate方法中加上如下代码,即设置接收邮箱。

  new CrashEmailReport(this).setReceiver("[email protected]");
然后在AndroidManifest.xml中配置这个类。

http://www.bkjia.com/Androidjc/777963.htmlwww.bkjia.comtruehttp://www.bkjia.com/Androidjc/777963.htmlTechArticle最近在写Android程序崩溃异常处理,完成之后,稍加封装与大家分享。 我的思路是这样的,在程序崩溃之后,将异常信息保存到一个日志文...

本文源自: AG环亚娱乐

Copyright © 2005-2017 http://www.turingvr.com AG环亚娱乐_AG直营网_环亚娱乐AG最佳线路_搜狐新闻版权所有

友情链接: