最近在考虑为已经有的一个应用程序增加一个用户反馈的功能,用户可以通过反馈功能将用户的意见和建议、程序出现的问题以一种更符合用户习惯的方式反馈回来。网上也有一些实现好的反馈程序的服务,包括bug的提交、程序的建议、程序使用中的问题,但是这样的服务基本上不是完全开源和免费的,并且我对程序反馈的定位还是用户可以把他的想法通过写文字的方法发送回来就可以(不需要记录崩溃时的系统状况),所以还是决定在完全了解实现机制的基础上来实现反馈功能。
采用发送邮件的方式不需要自己构建服务器,同时也符合我对反馈的管理习惯,因此决定采用在通过在应用程序内发送邮件的方式来实现反馈功能。
*上的回答http://*.com/a/2033124/1767800基本给出了在Android中实现在应用程序内部发送邮件的方法,在阅读该代码的时候我一直在找smtp是如何认证的。后来发现该实现方法中GmailSender直接继承了javax.mail.Authenticator类,实现了getPasswordAuthentication方法,并且通过Session.getDefaultInstance(props, this)(getDefaultInstance(Properties props, Authenticator authenticator)
)语句在建立session的同时将authenticator属性写入。
为了实现在Android的应用程序内部发送邮件,其中有两点可能的修改需要注意:
1.该回答使用的是Gmail账户作为发送邮件的账户,如果采用其它的账户需要对发送邮件服务器和端口号进行单独的设置。
对于126或者163邮箱而言,只需要将properties设置的部分修改为:
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.host", mailhost);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "25");
参考:http://www.cnblogs.com/peakzheng/archive/2012/02/04/2338671.html
2.需要将UI线程(主线程)中的发送邮件操作转移到单独的线程进行处理
Google在honeycomb的发布版之后就对主线程中的操作进行了更加严格的要求。为了保证用户体验,在主线程中不能网络数据传输操作,因为在主线程中进行网络数据传输可能会带来主界面的长时间不响应用户的点击操作,从而带来不好的用户体验(参考)。对于轻量级的网络操作,Android系统中,通常通过AsyncTask类来实现。
按说Android在高版本的系统中对应用程序在主界面访问网络的操作都会提示android.os.NetworkOnMainThreadException错误,但是在使用Java Mail API进行应用程序内的邮件发送时,我遇到的情况是在2.3版本的模拟器上运行程序,接收方可以收到发送的邮件。同样的代码在在4.2.2版本的手机上却无法成功发送邮件,在Eclipse下的logcat界面中没有任何错误提示。*上的回答http://*.com/a/2033124/1767800后也有人给出了类似的评论。
但是,在将sender.sendMail()函数转移到asyncTask类中之后,在4.2.2的手机中也可以成功发送邮件了。具体实现是:
1)新建一个继承自AsyncTask的类
class SendMailTask extends AsyncTask<URL, Integer, Long> {
MailSender sender;
public SendMailTask(MailSender sender) {
// TODO Auto-generated constructor stub
this.sender=sender;
}
protected Long doInBackground(URL... urls) { long totalSize = 0;
try {
this.sender.sendMail("This is Subject",
"This is Body",
"senderAddress",
"receiverAddress");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return totalSize;
} protected void onProgressUpdate(Integer... progress) {
} protected void onPostExecute(Long result) {
}
}
2)通过如下语句发送邮件
new SendMailTask(sender).execute();
通过gmail接收的邮件如下图所示