Android: Как проверить электронную почту в определенное время с помощью AlarmManager?

Мне нужно распечатать все входящие письма в 9 утра каждое утро. Вот что я пробовал

Часть электронной почты работает нормально. Я могу подключиться к электронной почте и распечатать их все. Проблема возникает, когда я представляю Alarm Manager. Когда я запускаю его, ничего не происходит. Это просто зависает

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 (ОБНОВЛЕННЫЙ КЛАСС)

 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; } } 

Когда я запускаю его, ничего не происходит. Что я делаю не так?

Прежде всего, если вы хотите запустить какой-то код на устройстве Android, вы должны использовать это:

  1. AlarmManager который запускает BroadcastReceiver
  2. Используйте WakeupBroadcastReceiver чтобы разбудить устройство.
  3. Используйте режим пребывания в режиме ожидания Android-устройства во время выполнения кода.
  4. Не забудьте перезагрузить устройство после перезагрузки устройства.
  5. У ВАС ЕСТЬ ПРОБЛЕМА, ЗАПУСКАЮЩИЙСЯ АСТИНКТА !!!
  6. У вас неправильный alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1000 * 5, pi); реализация. Эта строка означает: «выполнить мой код каждые 5 секунд. Начните это сейчас!». Это не 9AM время;)

Итак, попробуйте следующее:

  1. Чтобы зарядить 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 (родительский класс для Activity и Service ). Например, в классе Activity это getContext() или getActivity() . nexttime раз – время, чтобы насладиться получателем. Например, long nexttime = System.getCurrentTimeMillis(); , AlarmManager am = (AlarmManager) ctx.getSystemService(Activity.ALARM_SERVICE); , intentalarm – это уникальный номер для обнаружения этого запуска в будущем. Это может быть любое число, которое вы хотите, но постоянное в своем приложении. Например, final int intentalarm = 22344;

  1. Для запуска службы 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)); } } 
  1. OWakeLocker – это мой собственный класс, который хранит все запущенные службы, чтобы сохранить их жизнь.
 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; } } 
  1. Используйте эту службу для выполнения кода:
 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(); } } 
  1. Чтобы рассчитать хорошее время 9AM, вы должны использовать этот код: время и дата этого календаря
  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. 
  1. Используйте setExactAndAllowWhileIdle вместо setRepeating... И AlarmManager в SService.onDestroy() используя тот же код, что и в Activity

  2. Изменить 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> 

Используйте Intent-Service с широковещательным приемником.

Ниже приведена ссылка с примером:

Справочная служба

  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); } } 

Прежде всего, измените свой код в 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 (убедитесь, что этот реестр уже зарегистрирован в манифесте с настраиваемым действием в теге 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 , то есть AsyncTaskActvity . Вам нужно найти разницу между Service и AsyncTask .