Android: 如何使用AlarmManager 定时查看邮件?
Android: How to check email at a specific time with AlarmManager?
我需要在每天早上 9 点打印所有收到的电子邮件。这是我试过的
电子邮件部分工作正常。我能够连接到电子邮件并将它们全部打印出来。当我介绍警报管理器时,问题就来了。当我 运行 它时,什么也没有发生。它只是挂起
MainActivity.java
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Properties;
import javax.mail.*;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void checkEmail(View view) {
Log.d("test", "accessing gmail");
Calendar cur_cal = new GregorianCalendar();
cur_cal.setTimeInMillis(System.currentTimeMillis());//set the current time and date for this calendar
Calendar cal = new GregorianCalendar();
cal.add(Calendar.DAY_OF_YEAR, cur_cal.get(Calendar.DAY_OF_YEAR));
cal.set(Calendar.HOUR_OF_DAY, 9);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, cur_cal.get(Calendar.SECOND));
cal.set(Calendar.MILLISECOND, cur_cal.get(Calendar.MILLISECOND));
cal.set(Calendar.DATE, cur_cal.get(Calendar.DATE));
cal.set(Calendar.MONTH, cur_cal.get(Calendar.MONTH));
// create an Intent
Intent intentAlarm = new Intent(this, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getService(this, 0, intentAlarm, 0);
// create the object
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
//set the alarm for 9 AM
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1000 * 5, pi);
Toast.makeText(this, "Alarm Scheduled for 9 AM", Toast.LENGTH_LONG).show();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
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.admin.myapplication.MainActivity">
<TextView
android:layout_width="wrap_content"
android:textSize="24sp"
android:layout_height="wrap_content"
android:text="Email Checker"
android:id="@+id/textView2" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="@+id/button"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="152dp"
android:onClick="checkEmail"/>
</RelativeLayout>
AlarmReceiver.java(已更新 CLASS)
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.SmsManager;
import android.util.Log;
import android.widget.Toast;
public class AlarmReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Intent i = new Intent(context, AsyncTaskActvity.class);
i.putExtra("foo", "bar");
context.startService(i);
Log.d("test", "async");
Toast.makeText(context, "Alarm Triggered", Toast.LENGTH_LONG).show();
}
}
AsyncTaskActvity.java
package com.example.admin.myapplication;
import android.os.AsyncTask;
import android.util.Log;
import java.util.Properties;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Store;
public class AsyncTaskActvity extends AsyncTask {
@Override
protected Object doInBackground(Object[] params) {
computerUp();
return null;
}
protected boolean computerUp () {
try {
Properties props = java.lang.System.getProperties();
props.setProperty("mail.store.protocol", "imaps");
Session session = Session.getDefaultInstance(props, null);
Store store = session.getStore("imaps");
store.connect("imap.gmail.com", "myemail@gmail.com", "mypassword");
Session s = Session.getInstance(props);
Message[] msgs;
Folder inbox = store.getFolder("Inbox");
inbox.open(Folder.READ_ONLY);
msgs = inbox.getMessages();
for (int i = 0; i < msgs.length; i++) {
msgs[i].getSubject();
Log.d("test", msgs[i].getSubject());
}
} catch (Exception e) {
Log.e(e.getClass().getName(), e.getMessage(), e);
}
return true;
}
}
当我运行它时,没有任何反应。我究竟做错了什么?
将 Intent-Service 与广播接收器一起使用。
按照以下 link 举例:
public class MyAlarmReceiver extends BroadcastReceiver {
public static final int REQUEST_CODE = 12345;
public static final String ACTION = "com.codepath.example.servicesdemo.alarm";
// Triggered by the Alarm periodically (starts the service to run task)
@Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, MyTestService.class);
i.putExtra("foo", "bar");
context.startService(i);
}
}
首先,如果你想在 Android 设备中启动一些代码,你必须使用这个:
AlarmManager
启动 BroadcastReceiver
- 使用
WakeupBroadcastReceiver
唤醒您的设备。
- 在执行代码时使用 Android 设备的保持唤醒状态。
- 重启设备后不要忘记充电。
- 您在启动 ASYNCTASK 时遇到问题 !!!
- 您的
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1000 * 5, pi);
实施不正确。这个字符串的意思是:"execute my code each 5 seconds. Start it is now!"。现在不是上午 9 点;)
所以,试试这个:
- 在特定时间充电
AlarmManager
:
Intent intent = new Intent(BRWakeup.INTENT_FILTER) ;
PendingIntent pi = PendingIntent.getBroadcast(ctx, intentalarm, intent, PendingIntent.FLAG_CANCEL_CURRENT);
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion < android.os.Build.VERSION_CODES.KITKAT){
am.set(wakeup?AlarmManager.RTC_WAKEUP:AlarmManager.RTC, nexttime, pi);
} else if (currentapiVersion >= android.os.Build.VERSION_CODES.LOLLIPOP)
if (currentapiVersion < android.os.Build.VERSION_CODES.M) {
am.setExact(AlarmManager.RTC_WAKEUP, nexttime, pi);
} else {
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nexttime, pi);
}
}
其中 ctx
- 当前 Context
class(Activity
和 Service
的父级 Class)。例如,在 Activity
class 中,这是 getContext()
或 getActivity()
。 nexttime
- 是时候启动接收器了。例如,long nexttime = System.getCurrentTimeMillis();
、AlarmManager am = (AlarmManager) ctx.getSystemService(Activity.ALARM_SERVICE);
、intentalarm
- 是一些唯一的数字,用于在将来检测此启动事件。它可以是您想要的任何数字,但在您的应用程序中是常量。例如,final int intentalarm = 22344;
- 要从
BroadcastReceiver
启动服务:
public class BRWakeup extends WakefulBroadcastReceiver {
public static final String INTENT_FILTER = "com.example.BRWakeup";
@Override
public void onReceive(Context ctx, Intent intent) {
// TODO Auto-generated method stub
OWakeLocker.acquire(ctx, 0);
ComponentName comp = new ComponentName(ctx.getPackageName(),
SService.class.getName());
startWakefulService(ctx, intent.setComponent(comp));
}
}
OWakeLocker
是我自己的 class 存储所有已启动的服务以挽救他们的生命。
public class OWakeLocker {
private static PowerManager.WakeLock[] wakeLocks = new PowerManager.WakeLock[1];//Services count
@SuppressWarnings("deprecation")
public static void acquire(Context ctx, int index) {
WakeLock wakeLock = wakeLocks[index];
if (wakeLock != null) wakeLock.release();
PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.ON_AFTER_RELEASE, _.APPNAME + Integer.toString(index));
if (wakeLock != null && wakeLock.isHeld()){
wakeLock.acquire();
}
}
public static void release(int index) {
WakeLock wakeLock = wakeLocks[index];
if (wakeLock != null)
wakeLock.release();
wakeLock = null;
}
}
- 使用此服务执行您的代码:
public class SService extends Service {
@Override
public void onCreate() {
OWakeLocker.acquire(this, 0);
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
OWakeLocker.release(_.indexNOTS_TAT);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//your code to start AsyncTask
AsyncTaskActvity atask = new AsyncTaskActvity();
atsk.execute();
}
}
- 要计算正确的上午 9 点时间,您必须使用以下代码:
此日历的时间和日期
Calendar cal = Calendar.getInstance();
boolean iftoday = cal.get(Calendar.HOUR_OF_DAY) < 9;
//to set the time as exact
cal.set(Calendar.HOUR_OF_DAY, 9);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
if (!iftoday) {
cal.add(Calendar.DATE, 1);
}
long nexttime = cal.getTimeInMillis();//this is the correct next time.
使用 setExactAndAllowWhileIdle
而不是 setRepeating...
。并使用与 Activity
相同的代码在 SService.onDestroy()
充值 AlarmManager
编辑AndroidManifest.xml
<receiver android:name="com.example.BRWakeup"
android:exported="false">
<intent-filter>
<action android:name="com.example.BRWakeup"/>
</intent-filter>
</receiver>
<service android:name="com.example.SService"></service>
首先,将 checkEmail()
方法中的代码更改为:
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void checkEmail(View view) {
Log.d("test", "accessing gmail");
//set the current time and date for this calendar
Calendar cal = new GregorianCalendar();
cal.add(Calendar.DAY_OF_YEAR, 1);
cal.set(Calendar.HOUR_OF_DAY, 9);
cal.set(Calendar.MINUTE, 0);
// create an Intent
Intent intentAlarm = new Intent(this, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intentAlarm, 0);
// create the object
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
//set the alarm for 9 AM
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
Toast.makeText(this, "Alarm Scheduled for 9 AM", Toast.LENGTH_LONG).show();
}
在 AlarmReceiver.java
class 中(确保此接收器已在清单中注册并在 intent-filter
标签中使用自定义操作):
@Override
public void onReceive(Context context, Intent intent) {
new AsyncTaskActvity().execute();
Log.d("test", "async");
Toast.makeText(context, "Alarm Triggered", Toast.LENGTH_LONG).show();
}
出现错误的主要问题是,您将 startService()
调用到未扩展 Service
的 class,即 AsyncTaskActvity
。你需要找到 Service and AsyncTask.
之间的区别
我需要在每天早上 9 点打印所有收到的电子邮件。这是我试过的
电子邮件部分工作正常。我能够连接到电子邮件并将它们全部打印出来。当我介绍警报管理器时,问题就来了。当我 运行 它时,什么也没有发生。它只是挂起
MainActivity.java
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Properties;
import javax.mail.*;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void checkEmail(View view) {
Log.d("test", "accessing gmail");
Calendar cur_cal = new GregorianCalendar();
cur_cal.setTimeInMillis(System.currentTimeMillis());//set the current time and date for this calendar
Calendar cal = new GregorianCalendar();
cal.add(Calendar.DAY_OF_YEAR, cur_cal.get(Calendar.DAY_OF_YEAR));
cal.set(Calendar.HOUR_OF_DAY, 9);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, cur_cal.get(Calendar.SECOND));
cal.set(Calendar.MILLISECOND, cur_cal.get(Calendar.MILLISECOND));
cal.set(Calendar.DATE, cur_cal.get(Calendar.DATE));
cal.set(Calendar.MONTH, cur_cal.get(Calendar.MONTH));
// create an Intent
Intent intentAlarm = new Intent(this, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getService(this, 0, intentAlarm, 0);
// create the object
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
//set the alarm for 9 AM
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1000 * 5, pi);
Toast.makeText(this, "Alarm Scheduled for 9 AM", Toast.LENGTH_LONG).show();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
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.admin.myapplication.MainActivity">
<TextView
android:layout_width="wrap_content"
android:textSize="24sp"
android:layout_height="wrap_content"
android:text="Email Checker"
android:id="@+id/textView2" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="@+id/button"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="152dp"
android:onClick="checkEmail"/>
</RelativeLayout>
AlarmReceiver.java(已更新 CLASS)
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.SmsManager;
import android.util.Log;
import android.widget.Toast;
public class AlarmReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Intent i = new Intent(context, AsyncTaskActvity.class);
i.putExtra("foo", "bar");
context.startService(i);
Log.d("test", "async");
Toast.makeText(context, "Alarm Triggered", Toast.LENGTH_LONG).show();
}
}
AsyncTaskActvity.java
package com.example.admin.myapplication;
import android.os.AsyncTask;
import android.util.Log;
import java.util.Properties;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Store;
public class AsyncTaskActvity extends AsyncTask {
@Override
protected Object doInBackground(Object[] params) {
computerUp();
return null;
}
protected boolean computerUp () {
try {
Properties props = java.lang.System.getProperties();
props.setProperty("mail.store.protocol", "imaps");
Session session = Session.getDefaultInstance(props, null);
Store store = session.getStore("imaps");
store.connect("imap.gmail.com", "myemail@gmail.com", "mypassword");
Session s = Session.getInstance(props);
Message[] msgs;
Folder inbox = store.getFolder("Inbox");
inbox.open(Folder.READ_ONLY);
msgs = inbox.getMessages();
for (int i = 0; i < msgs.length; i++) {
msgs[i].getSubject();
Log.d("test", msgs[i].getSubject());
}
} catch (Exception e) {
Log.e(e.getClass().getName(), e.getMessage(), e);
}
return true;
}
}
当我运行它时,没有任何反应。我究竟做错了什么?
将 Intent-Service 与广播接收器一起使用。
按照以下 link 举例:
public class MyAlarmReceiver extends BroadcastReceiver {
public static final int REQUEST_CODE = 12345;
public static final String ACTION = "com.codepath.example.servicesdemo.alarm";
// Triggered by the Alarm periodically (starts the service to run task)
@Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, MyTestService.class);
i.putExtra("foo", "bar");
context.startService(i);
}
}
首先,如果你想在 Android 设备中启动一些代码,你必须使用这个:
AlarmManager
启动BroadcastReceiver
- 使用
WakeupBroadcastReceiver
唤醒您的设备。 - 在执行代码时使用 Android 设备的保持唤醒状态。
- 重启设备后不要忘记充电。
- 您在启动 ASYNCTASK 时遇到问题 !!!
- 您的
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1000 * 5, pi);
实施不正确。这个字符串的意思是:"execute my code each 5 seconds. Start it is now!"。现在不是上午 9 点;)
所以,试试这个:
- 在特定时间充电
AlarmManager
:
Intent intent = new Intent(BRWakeup.INTENT_FILTER) ; PendingIntent pi = PendingIntent.getBroadcast(ctx, intentalarm, intent, PendingIntent.FLAG_CANCEL_CURRENT); int currentapiVersion = android.os.Build.VERSION.SDK_INT; if (currentapiVersion < android.os.Build.VERSION_CODES.KITKAT){ am.set(wakeup?AlarmManager.RTC_WAKEUP:AlarmManager.RTC, nexttime, pi); } else if (currentapiVersion >= android.os.Build.VERSION_CODES.LOLLIPOP) if (currentapiVersion < android.os.Build.VERSION_CODES.M) { am.setExact(AlarmManager.RTC_WAKEUP, nexttime, pi); } else { am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nexttime, pi); } }
其中 ctx
- 当前 Context
class(Activity
和 Service
的父级 Class)。例如,在 Activity
class 中,这是 getContext()
或 getActivity()
。 nexttime
- 是时候启动接收器了。例如,long nexttime = System.getCurrentTimeMillis();
、AlarmManager am = (AlarmManager) ctx.getSystemService(Activity.ALARM_SERVICE);
、intentalarm
- 是一些唯一的数字,用于在将来检测此启动事件。它可以是您想要的任何数字,但在您的应用程序中是常量。例如,final int intentalarm = 22344;
- 要从
BroadcastReceiver
启动服务:
public class BRWakeup extends WakefulBroadcastReceiver { public static final String INTENT_FILTER = "com.example.BRWakeup"; @Override public void onReceive(Context ctx, Intent intent) { // TODO Auto-generated method stub OWakeLocker.acquire(ctx, 0); ComponentName comp = new ComponentName(ctx.getPackageName(), SService.class.getName()); startWakefulService(ctx, intent.setComponent(comp)); } }
OWakeLocker
是我自己的 class 存储所有已启动的服务以挽救他们的生命。
public class OWakeLocker { private static PowerManager.WakeLock[] wakeLocks = new PowerManager.WakeLock[1];//Services count @SuppressWarnings("deprecation") public static void acquire(Context ctx, int index) { WakeLock wakeLock = wakeLocks[index]; if (wakeLock != null) wakeLock.release(); PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE); wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, _.APPNAME + Integer.toString(index)); if (wakeLock != null && wakeLock.isHeld()){ wakeLock.acquire(); } } public static void release(int index) { WakeLock wakeLock = wakeLocks[index]; if (wakeLock != null) wakeLock.release(); wakeLock = null; } }
- 使用此服务执行您的代码:
public class SService extends Service { @Override public void onCreate() { OWakeLocker.acquire(this, 0); super.onCreate(); } @Override public void onDestroy() { super.onDestroy(); OWakeLocker.release(_.indexNOTS_TAT); } @Override public int onStartCommand(Intent intent, int flags, int startId) { //your code to start AsyncTask AsyncTaskActvity atask = new AsyncTaskActvity(); atsk.execute(); } }
- 要计算正确的上午 9 点时间,您必须使用以下代码: 此日历的时间和日期
Calendar cal = Calendar.getInstance(); boolean iftoday = cal.get(Calendar.HOUR_OF_DAY) < 9; //to set the time as exact cal.set(Calendar.HOUR_OF_DAY, 9); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); if (!iftoday) { cal.add(Calendar.DATE, 1); } long nexttime = cal.getTimeInMillis();//this is the correct next time.
使用
setExactAndAllowWhileIdle
而不是setRepeating...
。并使用与Activity
相同的代码在 编辑
AndroidManifest.xml
SService.onDestroy()
充值 AlarmManager
<receiver android:name="com.example.BRWakeup" android:exported="false"> <intent-filter> <action android:name="com.example.BRWakeup"/> </intent-filter> </receiver> <service android:name="com.example.SService"></service>
首先,将 checkEmail()
方法中的代码更改为:
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void checkEmail(View view) {
Log.d("test", "accessing gmail");
//set the current time and date for this calendar
Calendar cal = new GregorianCalendar();
cal.add(Calendar.DAY_OF_YEAR, 1);
cal.set(Calendar.HOUR_OF_DAY, 9);
cal.set(Calendar.MINUTE, 0);
// create an Intent
Intent intentAlarm = new Intent(this, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intentAlarm, 0);
// create the object
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
//set the alarm for 9 AM
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
Toast.makeText(this, "Alarm Scheduled for 9 AM", Toast.LENGTH_LONG).show();
}
在 AlarmReceiver.java
class 中(确保此接收器已在清单中注册并在 intent-filter
标签中使用自定义操作):
@Override
public void onReceive(Context context, Intent intent) {
new AsyncTaskActvity().execute();
Log.d("test", "async");
Toast.makeText(context, "Alarm Triggered", Toast.LENGTH_LONG).show();
}
出现错误的主要问题是,您将 startService()
调用到未扩展 Service
的 class,即 AsyncTaskActvity
。你需要找到 Service and AsyncTask.