I need to print all my incoming email at 9AM every morning. Here is what I tried
The email part works fine. I am able to connect to email and print them all. The problem comes when I introduce the Alarm Manager. When I run it, nothing happens. It just hangs
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 (UPDATED 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", "[email protected]", "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;
}
}
When I run it, nothing happens. What am I doing wrong?
AlarmManager is a bridge between application and Android system alarm service. It can send a broadcast to your app (which can be completely terminated by user) at a scheduled time and your app can then perform any task accordingly.
What is this permission? The new exact alarm permission ( SCHEDULE_EXACT_ALARM ) was created to save system resources. Alarms that must be executed in an exact time may be triggered when the phone is on power-saving mode or Doze, making the app consumes more battery than it should.
Navigate to the app > res > layout > activity_main. xml and add the below code to that file. In this file, we have added two items 'TimePicker' and 'ToggleButton'. TimePicker is used to capture the alarm time and ToggleButton is added to set the alarm on or off.
First of all, if you want to launch some code inside Android device you have to use this:
AlarmManager
which launches BroadcastReceiver
WakeupBroadcastReceiver
to wake up your device.alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1000 * 5, pi);
implementation. this string mean:"execute my code each 5 seconds. Start it is now!". This is not 9AM time;)So, try this:
AlarmManager
at specific time: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); } }
where ctx
- current Context
class (parent Class for Activity
and Service
). For example, in Activity
class this is getContext()
or getActivity()
. nexttime
- time to lauch the receiver. For example, long nexttime = System.getCurrentTimeMillis();
, AlarmManager am = (AlarmManager) ctx.getSystemService(Activity.ALARM_SERVICE);
, intentalarm
- is a some unique number to detect this launch event in future. It may be any number your want but the constant in your app. For example, 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
is my own class which stores all launched services to save their lifes.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(); } }
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.
Use setExactAndAllowWhileIdle
instead of setRepeating...
. And recharge AlarmManager
at SService.onDestroy()
method using the same code as in the Activity
Edit 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>
Use Intent-Service with Broadcast Receiver.
Follow below link with example :
Background 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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With