本文实现了在好友生日前自动发送提醒邮件的功能。
android.util.Patterns自带的正则表达式实现邮箱验证。 Calender获取日历。 DatePickerDialog实现选择日期。 AlarmManager定时器实现系统后台提醒功能。 Java mail系统自动发送邮件,使用Java mail发送文件需要网络权限。邮件,生日用SharedPreference保存。所有代码如下。
github https://github.com/tashaerxing/SendMail
* AlarmManager定时器 四步
* AlarmManager是Android中的一种系统级别的提醒服务,它会为我们在特定的时刻广播一个指定的Intent。
* 相对时间:SystemClock.elapsedRealtime();
* 绝对时间:System.currentTimeMillis();
* 1.实例化 AlarmManager。
* AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
* 2.确认意图。Intent intent = new Intent(this,SendEmailIntentService.class);
* 3.延迟意图,get方法。PendingIntent pi = PendingIntent.getService(this,0,intent,0);
* 4.设置周期。set方法。//定时器:四个参数(绝对时间,当前系统时间,每天INTERVAL_DAY,pendingIntent)
* alarmManager.setRepeating(AlarmManager.RTC,System.currentTimeMillis(),
* AlarmManager.INTERVAL_DAY,pi);
package com.example.sendemail;
import android.Manifest;
import android.app.DatePickerDialog;
import java.util.Calendar;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
import android.util.Patterns;
import android.app.AlarmManager;
public class MainActivity extends AppCompatActivity implements
View.OnClickListener{
private EditText mail;
private TextView date;
private Button ack;
private int preyear;//初始化的年月日
private int premonth;
private int preday;
private int themeResId;//日历格式
private SharedPreferences sharedPreferences;
private SharedPreferences.Editor editor;
private AlarmManager alarmManager;
private RadioGroup radioGroup;
private boolean send;//判断是否开启生日提醒
private RadioButton yesSend;
private RadioButton noSend;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// requestWindowFeature(Window.FEATURE_NO_TITLE);加了这句话后程序崩溃,未解决日历样式
init();
date.setOnClickListener(this);
ack.setOnClickListener(this);
radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId){
case R.id.yesSend:
editor.putBoolean("send",true);
editor.apply();
//发送邮件需要获取网络权限
if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.
INTERNET)!= PackageManager.PERMISSION_GRANTED){
//如果没有权限,向用户申请权限
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest
.permission.INTERNET},1);
}else {
StartEmailService();
}
break;
case R.id.noSend:
editor.putBoolean("send",false);
editor.apply();
//如果开启生日提醒,在这里关闭生日提醒
CancelEmailService();
break;
default:break;
}
}
});
}
private void init(){
mail = (EditText)findViewById(R.id.mail);
date = (TextView) findViewById(R.id.date);
ack = (Button)findViewById(R.id.ack);
radioGroup = (RadioGroup)findViewById(R.id.pickMail);
yesSend = (RadioButton)findViewById(R.id.yesSend);
noSend = (RadioButton)findViewById(R.id.noSend);
//获取系统时间
Calendar calendar = Calendar.getInstance();
//从sheredPerference中获取数据,没有数据显示当前时间
sharedPreferences = getSharedPreferences("data",0);
editor = sharedPreferences.edit();
//初始化日期和邮箱
preyear = sharedPreferences.getInt("year",calendar.get(Calendar.YEAR));
premonth = sharedPreferences.getInt("month",calendar.get(Calendar.MONTH)+1);
preday = sharedPreferences.getInt("day",calendar.get(Calendar.DAY_OF_MONTH));
String Email = sharedPreferences.getString("email",null);//邮箱值
send = sharedPreferences.getBoolean("send",false);
date.setText(preyear+"年"+premonth +"月"+ preday+"日");
mail.setText(Email);
if(send){
// radioGroup.check(yesSend.getId());
yesSend.setChecked(true);
}else {
// radioGroup.check(noSend.getId());
noSend.setChecked(true);
}
// Log.d("send 的值",String.valueOf(send));
// themeResId = DatePickerDialog.THEME_HOLO_LIGHT;
themeResId = 3;
}
public void StartEmailService(){
//如果选中生日邮箱提醒,开启周期性系统服务
alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent intent = new Intent(MainActivity.this,SendEmailIntentService.class);
PendingIntent pi = PendingIntent.getService(MainActivity.this,0,intent,0);
//定时器:四个参数(绝对时间,当前系统时间,每天INTERVAL_DAY,pendingIntent)
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),
AlarmManager.INTERVAL_DAY,pi);
}
public void CancelEmailService(){
alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent intent = new Intent(MainActivity.this,SendEmailIntentService.class);
PendingIntent pi = PendingIntent.getService(MainActivity.this,0,intent,0);
//定时器:四个参数(绝对时间,当前系统时间,每天INTERVAL_DAY,pendingIntent)
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),
AlarmManager.INTERVAL_DAY,pi);
if(pi!=null){
alarmManager.cancel(pi);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode){
case 1:
if(grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
//如果有网络,可以发送邮件
StartEmailService();
}else {
//没有网络
Toast.makeText(this,"邮箱提醒开启失败,请开启网络权限",Toast.LENGTH_LONG).show();
noSend.setChecked(true);
}
}
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.date:
new DatePickerDialog(MainActivity.this, themeResId,new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
//日期改变后,用sheredperfreference保存
month++;
preyear = year;
premonth = month;
preday = dayOfMonth;
editor.putInt("year",year);
editor.putInt("month",month);
editor.putInt("day",dayOfMonth);
editor.apply();
date.setText(year+"年"+month +"月"+ dayOfMonth+"日");
}
},preyear,premonth-1,preday).show();
case R.id.ack://在这里判断邮箱是否正确
//首先获取输入的邮箱
String email = mail.getText().toString();
if("".equals(email)){
//email == null这里==并没有起作用,==比较的是两个对象的地址,equals比较的是两个对象的内容
//如果邮箱为空
Toast.makeText(MainActivity.this,"请输入邮箱"+email,Toast.LENGTH_SHORT).show();
}else {
//如果邮箱不为空,判断邮箱格式是否正确
if(!isEmail(email)){
//如果邮箱格式不正确
Toast.makeText(MainActivity.this,"请输入正确的邮箱地址",Toast.LENGTH_SHORT).show();
}else {
//将真确的邮箱保存
editor.putString("email",email);
editor.apply();
Toast.makeText((MainActivity.this),"邮箱地址正确",Toast.LENGTH_SHORT).show();
//邮箱地址正确,记录下邮箱,和生日,在生日前三天发送邮件提醒。
}
}
default:break;
}
}
public boolean isEmail(String email){
//邮箱的正则表达式
return Patterns.EMAIL_ADDRESS.matcher(email).matches();
}
}
Intent不能实现后台自动发送邮件的功能,改为Java mail
* javamail 实现发送邮件,首先需要依赖 additional.jar 、 mail.jar 和 activation.jar 这 3 个 jar 包。 * Properties 属性文件以 key value 存储值 * Authenticator 访问受保护的服务器资源 * Session 客户端与服务器端的会话。 Session 对象需要知道用来处理邮件的 SMTP 服务器。 * MimeMessage 存储我们实际发送的电子邮件信息, * InternetAddress 源地址和目标地址 * Transport 发送信息
链接失败:
properties.setProperty("mail.smtp.starttls.enable","true");//错误530。要打开tls安全传输层协议(TLS)用于在两个通信应用程序之间提供保密性和数据完整性。
package com.example.sendemail;
import android.app.IntentService;
import android.content.Intent;
import android.content.Context;
import android.content.SharedPreferences;
import java.util.Calendar;
import java.text.SimpleDateFormat;
import javax.mail.MessagingException;
/**
* An {@link IntentService} subclass for handling asynchronous task requests in
* a service on a separate handler thread.
* <p>
* TODO: Customize class - update intent actions, extra parameters and static
* helper methods.
*/
public class SendEmailIntentService extends IntentService {
// TODO: Rename actions, choose action names that describe tasks that this
// IntentService can perform, e.g. ACTION_FETCH_NEW_ITEMS
private static final String ACTION_FOO = "com.example.sendemail.action.FOO";
private static final String ACTION_BAZ = "com.example.sendemail.action.BAZ";
// TODO: Rename parameters
private static final String EXTRA_PARAM1 = "com.example.sendemail.extra.PARAM1";
private static final String EXTRA_PARAM2 = "com.example.sendemail.extra.PARAM2";
public SendEmailIntentService() {
super("SendEmailIntentService");
}
/**
* Starts this service to perform action Foo with the given parameters. If
* the service is already performing a task this action will be queued.
*
* @see IntentService
*/
// TODO: Customize helper method
public static void startActionFoo(Context context, String param1, String param2) {
Intent intent = new Intent(context, SendEmailIntentService.class);
intent.setAction(ACTION_FOO);
intent.putExtra(EXTRA_PARAM1, param1);
intent.putExtra(EXTRA_PARAM2, param2);
context.startService(intent);
}
/**
* Starts this service to perform action Baz with the given parameters. If
* the service is already performing a task this action will be queued.
*
* @see IntentService
*/
// TODO: Customize helper method
public static void startActionBaz(Context context, String param1, String param2) {
Intent intent = new Intent(context, SendEmailIntentService.class);
intent.setAction(ACTION_BAZ);
intent.putExtra(EXTRA_PARAM1, param1);
intent.putExtra(EXTRA_PARAM2, param2);
context.startService(intent);
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_FOO.equals(action)) {
final String param1 = intent.getStringExtra(EXTRA_PARAM1);
final String param2 = intent.getStringExtra(EXTRA_PARAM2);
handleActionFoo(param1, param2);
} else if (ACTION_BAZ.equals(action)) {
final String param1 = intent.getStringExtra(EXTRA_PARAM1);
final String param2 = intent.getStringExtra(EXTRA_PARAM2);
handleActionBaz(param1, param2);
}
}
// Log.d("SendEmailIntentService","在这里发送邮件");
SharedPreferences preferences = getSharedPreferences("data",0);
String email = preferences.getString("email",null);
if(!"".equals(email) && email!=null) {
// //如果邮箱不为空,发送提醒邮件
//使用intent发送邮件,不能自动发送
// Intent sendEmail = new Intent(Intent.ACTION_SENDTO);//纯文本,不用附件
// sendEmail.setData(Uri.parse("mailto:"+email));//目标地址
// sendEmail.putExtra(Intent.EXTRA_SUBJECT,"生日提醒");//设置标题
// sendEmail.putExtra(Intent.EXTRA_TEXT,"又有人过生日啦,礼物买好了吗?");//内容
// startActivity(sendEmail);
try {
//判断日期,在生日前三天发送邮件
SimpleDateFormat format = new SimpleDateFormat("MM-dd");
//内存中的生日
Calendar calendar1 = Calendar.getInstance();
int biryear = preferences.getInt("year",0);
int birmonth = preferences.getInt("month",0)-1;
int birday = preferences.getInt("day",0);
calendar1.set(biryear,birmonth,birday);
String date1 = format.format(calendar1.getTime());
// Log.d("data1",date1);
//当前日期的三天前
Calendar calendar2 = Calendar.getInstance();
calendar2.set(Calendar.DATE,calendar2.get(Calendar.DATE)-3);
String date2 = format.format(calendar2.getTime());
// Log.d("date2",date2);
if(date1.equals(date2)){
new SendMail(email).send();
}
//使用Javamail发送邮件,能自动发送
}catch (MessagingException e){
e.printStackTrace();
}
}else {
// Toast.makeText(this,"请输入邮箱地址",Toast.LENGTH_SHORT);
stopSelf();
}
}
/**
* Handle action Foo in the provided background thread with the provided
* parameters.
*/
private void handleActionFoo(String param1, String param2) {
// TODO: Handle action Foo
throw new UnsupportedOperationException("Not yet implemented");
}
/**
* Handle action Baz in the provided background thread with the provided
* parameters.
*/
private void handleActionBaz(String param1, String param2) {
// TODO: Handle action Baz
throw new UnsupportedOperationException("Not yet implemented");
}
}
package com.example.sendemail;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class SendMail {
private String target;
public SendMail(String target){
//目标邮箱地址
this.target = target;
}
public void send()throws AddressException,MessagingException {
Properties properties = new Properties();
//设置验证setProperty的参数只能是String,更安全
properties.setProperty("mail.smtp.host","smtp.qq.com");
properties.setProperty("mail.smtp.auth","true");
properties.setProperty("mail.smtp.starttls.enable","true");//错误530
// properties.setProperty("mail,smtp.port","465");
//访问受保护的服务器资源
MyAuthenticator authenticator = new MyAuthenticator("851059665","itochdvtspfmbcca");
//Session 客户端与服务器端的会话.Session对象需要知道用来处理邮件的SMTP服务器。
Session session = Session.getInstance(properties,authenticator);
// session.setDebug(true);//代表启用debug模式,可以在控制台输出smtp协议应答的过程
// Message对象将存储我们实际发送的电子邮件信息,
// Message需要知道应当选择哪一个JavaMail session。
MimeMessage message = new MimeMessage(session);
//源地址和目标地址
InternetAddress soureceAddress = new InternetAddress("851059665@qq.com");
InternetAddress targetAddress = new InternetAddress(target);
//设置要发送的邮件信息
message.setFrom(soureceAddress);
message.addRecipient(Message.RecipientType.TO,targetAddress);
message.setSubject("生日提醒");
message.setText("又有人过生日啦,礼物准备好了吗?");
message.saveChanges();
//设置发送协议
Transport transport = session.getTransport("smtp");
transport.connect("smtp.qq.com","851059665@qq.com","itochdvtspfmbcca");
transport.sendMessage(message,message.getAllRecipients());
transport.close();
}
}
package com.example.sendemail;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
/**
* Created by lenovo on 2018/5/28.
*/
public class MyAuthenticator extends Authenticator {
String userName = null;
String password = null;
public MyAuthenticator(String userName,String password){
this.userName = userName;
this.password = password;
}
public MyAuthenticator() {
super();
}
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(userName,password);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.sendemail.MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:gravity="center_vertical|left"
android:textSize="18sp"
android:text="请输入正确的邮箱地址" />
<EditText
android:id="@+id/mail"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:textSize="18sp"
android:lines="1"
android:inputType="textEmailAddress"
android:gravity="center_vertical|left"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:textSize="18sp"
android:gravity="center_vertical|left"
android:text="请输入好友生日"/>
<TextView
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:gravity="center_vertical|left"
android:clickable="true"
android:textSize="18sp"
/>
<Button
android:id="@+id/ack"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:textSize="18sp"
android:gravity="center"
android:text="确定"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:orientation="horizontal"
android:textSize="18sp"
android:gravity="center_vertical|left"
android:layout_weight="2">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:gravity="center_vertical|left"
android:text="是否开启生日提醒"/>
<RadioGroup
android:id="@+id/pickMail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/yesSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:gravity="center_vertical|left"
android:text="是"
/>
<RadioButton
android:id="@+id/noSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:gravity="center_vertical|left"
android:text="否"
android:checked="true"
/>
</RadioGroup>
</LinearLayout>
</LinearLayout>