I have an android setInexactRepeating placed inside of my onCreate that never fires. I have a log inside of it to make sure that it's actually executing, and that doesn't seem to fire, as well as the events that I have planned for it. I want it to go off every 10 seconds, but it doesn't even seem to go off even the first time.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("Restart", "First");
Intent toRun = new Intent(this, AlarmRestart.class);
PendingIntent pendingToRun = PendingIntent.getBroadcast(this, 0, toRun, 0);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.cancel(pendingToRun);
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, System.currentTimeMillis(), 10000L, pendingToRun);
Log.d("Restart", "Second");
}
This is in the other file:
public class AlarmRestart extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Log.d("Restart", "Third");
}
}
This is what "adb shell dumpsys alarm" says
com.packageName.restart
5715ms running, 64 wakeups
3 alarms: flg=0x14 cmp=com.packageName.restart/.AlarmRestart
61 alarms: flg=0x14 cmp=com.packageName.restart/.reciever.AlarmRestart
AlarmRestart is a BroadcastReceiver. It is not a Service. Yet you are trying to use a getService() PendingIntent. That will not work. Change getService() to getBroadcast(), and you should have better luck.
I found the problem :/
<reciever android:name="com.appName.restart.AlarmRestart" android:enabled="true" />
It's spelled receiver....not reciever. Seriously, XML needs an error checker. I'm still marking CommonWares answer as the accepted one, because he solved several other issues that I would have run into later.
You may use SystemClock.elapsedRealtime() in an ELAPSED_REALTIME_WAKEUP alarm, instead of System.currentTimeMillis()
Related
According to these examples: here and here, I was trying to create Service which starts periodically.
First I created Service:
public class MonitorService extends IntentService {
private static final String TAG = "MonitorService";
public MonitorService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
Log.d("TAG", "Service method was fired.");
}
}
Next I created Receiver:
public class MyReceiver extends BroadcastReceiver {
private static final String TAG = "MyReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "MyReceiver on receive");
Intent i = new Intent(context, MonitorService.class);
context.startService(i);
}
}
I added starting method for this in MainActivity:
public void scheduleAlarm() {
Intent intent = new Intent(getApplicationContext(), MyReceiver.class);
final PendingIntent pIntent = PendingIntent.getBroadcast(this, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
long firstMillis = System.currentTimeMillis();
AlarmManager alarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
// 1s is only for testing
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis, 1000, pIntent);
}
which is calling of course in onCreate method.
And I didn't forget to change AndroidManifest:
<receiver
android:name=".MyReceiver"
android:process=":remote" >
</receiver>
<service
android:name=".MonitorService"
android:exported="false" />
And unfortunately the result is that nothing happens in my logs.
So I have two questions.
QUESTION
How to solve issue with not starting service?
If I add scheduleAlarm method to onCreate it will be calling every time I start my application, what is the best way to start this method only for the first time application is started?
EDIT
According to #Lasse hints, I started debugging, and realized that Log.d is not working, when I changed it to Log.i, information from MonitorService was logged.
But... debugging is not stoping on breaking point in MyReceiver, and changing Log.d to Log.i there didn't help. Of course MonitorService is firing, weird thing.
Also time with 1000 ms results in firing service every minute, maybe it's minimum time, and changing to AlarmManager.INTERVAL now doesn't matter.
EDIT 2
Finally I'm getting logs from both service and receiver. I had tried many times and after that it is working, but I don't know why.
But with that another problem has appeared - I'm getting warning when my Service is running
W/art: Suspending all threads took: 21.787ms
I thought that Service is running background so it doesn't matter how long it is, should I concern about this warning?
Edited
Regarding the first question :
See this from the developer website
setInexactRepeating(), you have to use one of the AlarmManager interval constants--in this case, AlarmManager.INTERVAL_DAY.
So change your 1000 to use of of the constans
Regarding your other question you could override the application object and start it there. This way it is only called when launching the app.
I want to send my app to sleep and then wake it up at set times. I have it going to sleep but not waking up.
This sets the wakelock:
private void setWakeLock(){
System.out.println("wakelock");
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP
| PowerManager.ON_AFTER_RELEASE, "DoNotDimScreen");
wl.acquire();
}
This sets alarms for wake/sleep times:
private void setWakeSleep(){
java.util.Calendar c = java.util.Calendar.getInstance();
c.set(java.util.Calendar.HOUR_OF_DAY, 17);
c.set(java.util.Calendar.MINUTE, 53);
c.set(java.util.Calendar.MILLISECOND, 0);
Intent sleepIntent = new Intent("SLEEP_INTENT");
PendingIntent sleepPendingIntent = PendingIntent.getBroadcast(this, 0, sleepIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), sleepPendingIntent);
c.set(java.util.Calendar.HOUR_OF_DAY, 18);
c.set(java.util.Calendar.MINUTE, 14);
c.set(java.util.Calendar.MILLISECOND, 0);
Intent wakeIntent = new Intent("WAKE_INTENT");
PendingIntent wakePendingIntent = PendingIntent.getBroadcast(this, 0, wakeIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager2 = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager2.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), wakePendingIntent);
}
And this is the broadcast receiver:
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Time updateHour = new Time();
updateHour.set(System.currentTimeMillis());
if (intent.getAction().equals("SLEEP_INTENT")) {
System.out.println("sleep");
wl.release();
}
if (intent.getAction().equals("WAKE_INTENT")) {
wl.acquire();
System.out.println("wake");
//initialise();
}
}
};
Any help greatly appreciated!
First, you don't want a wakelock; those are for keeping the device from going to sleep, which is highly anti-social unless your app really requires it (it kills the battery).
Second, your code to set the wakeup time will fail if you call it after 18:14 since you'll now be defining a time in the past. Let's ignore that for now.
Next, your intent action should be something like "org.user1797190.WAKE_INTENT" rather than simply "WAKE_INTENT" which could cause collisions. If you anticipate making this intent public, consider registering it at http://openintents.org. That's not your problem either, though.
You don't need alarmManager2 -- there's only one alarm manager in the system, so just re-use the first one.
I've never heard of making an app go to "sleep" per se. Do you mean you want the app to go away, and then come back later?
Here is what I would do. Forget about the "SLEEP_INTENT" completely. Just schedule a "WAKE_INTENT" and then call finish(). Your app will simply leave the screen.
I would forget about the broadcast receiver entirely. Instead, I would use getActivity() instead of getBroadcast() to get a pending intent that will restart the activity. Modify your manifest so that your WAKE_INTENT will go to the activity. Also, you should set the "android:launchMode" property to "singleTask" so multiple instances of your activity aren't created. You'll also need to implement onNewIntent() to handle the wakeup intent if your activity is already running when it arrives.
Finally, if your activity is part of the same application that will be creating the intent, you don't need a named intent at all; you can create them by class. You'll need another way to let the receiver know that this is a wakeup intent though.
So, putting it all together:
Your manifest should contain:
<activity android:name=".TestActivity" android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Your code should contain:
/**
* Arrange for the activity to return at a specific time.
* Call finish() after calling this method().
* This function can be called from anywhere that has a valid Context.
*/
public static void scheduleWakeup(Context ctx, long timeMillis) {
if (DEBUG) Log.d(TAG, "Scheduling wakeup for " + timeMillis);
Intent intent = new Intent(ctx, TestActivity.class);
intent.putExtra("wakeup", true);
PendingIntent pi = PendingIntent.getActivity(ctx, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager mgr = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
mgr.cancel(pi); // Cancel any previously-scheduled wakeups
mgr.set(AlarmManager.RTC_WAKEUP, timeMillis, pi);
}
...
protected void onCreate(Bundle state) {
Intent intent = getIntent();
if (intent.getBooleanExtra("wakeup", false)) {
// We were woken up by the alarm manager
}
...
}
protected void onNewIntent(Intent intent) {
if (intent.getBooleanExtra("wakeup", false)) {
// We were woken up by the alarm manager, but were already running
}
}
This is pretty close to what I'm doing in my own apps, and it works pretty well for me.
You'll have to test this yourself, of course. Log.d() is your friend.
as above. The problem was that I was using a broadcast receiver within the calling activity.
I want to make a service which fire alarm manager in every 1 min interval..But
my Alarm run once(first time only).
I follow Lalit Answer
private class Receiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(getBaseContext(), "Alarm", Toast.LENGTH_LONG).show();
NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
AlarmManager mgr=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i=new Intent(context, ConnectionReceiver.class);
PendingIntent pi=PendingIntent.getBroadcast(context, 0, i, 0);
mgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1*60*1000, pi);
}
}
Juts register broadcast receiver for:
http://developer.android.com/reference/android/content/Intent.html#ACTION_TIME_TICK
Try this code in Your broadcast receiver's onReceive method
AlarmManager mgr=(AlarmManager)ctxt.getSystemService(Context.ALARM_SERVICE);
mgr.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
60000+System.currentTimeMillis(),
getPendingIntent(ctxt));
and you can get pending intent
private static PendingIntent getPendingIntent(Context ctxt) {
Intent i=new Intent(ctxt, AReceiver.class);
return(PendingIntent.getBroadcast(ctxt, 0, i, 0));
}
where AReceiver class is for start service like Notification
it is working fine in my app so i hope it helps you
I know this question already has an answer, but for others who have had the same issue but need to use AlarmManager. The reason why it only runs once is because the new PendingIntent you create does not get recreated, but rather is reusing the one before it. So in other words, the reason why your alarm only ran once was because it kept reusing it. Using the flags to refresh the intent extras if there are any should be doing the trick, but that also does not work.
A trick to use to make sure it does not reuse the PendingIntent and ultimately the Intent you provide is to use setAction() and give it some unique "Action". I did it like this:
intent.setAction("com.yourname."+System.currentTimeMillis());
As you see this makes sure its unique. Though, the above accepted answer it the best approach, if someone does not want that, they need to understand why and how to remedy that issue. Hope it helps anyone else.
In my app I have SQLite database that has one table with date rows in milliseconds. I would like to have a notification shown every day IF 30 days has passed since the last date value stored in my database. A service seems to be a good way to accomplish this check up.
I ran into Commonsware's WakefulIntentService and thought it could be the answer but I really don't know how should I implement it. In the demo it starts a service after 5 minutes since boot is complete which is just fine but what do I need to add to get it also start at every noon. (... but only to show one notification / day, not both, as from boot and regular daily check up)
I know this could be solved using AlarmManager but really don't know how. So, the help I need is to give me some samples / key points to get the service start on every boot and/or every day without app running.
thanks
Android alarmmanager is your answer. use it with a broadcast receiver which also resets the alarms on phone wake.
Now with code example:
Setting alarm inside a method:
Intent intent = new Intent(context, AlarmReceiver.class);
intent.setAction("packagename.ACTION");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pendingIntent);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
Receiver for your interval:
public class AlarmReceiver extends BroadcastReceiver {
private final String SOMEACTION = "packagename.ACTION"; //packagename is com.whatever.www
#Override
public void onReceive(Context context, Intent intent) {
Time now = new Time();
now.setToNow();
String time = FileHandler.timeFormat(now);
String action = intent.getAction();
if(SOMEACTION.equals(action)) {
// here you call a service etc.
}
Receiver for resetting alarms whenever phone has been shut down.
public class AlarmSetter extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// get preferences
SharedPreferences preferences = context.getSharedPreferences("name_of_your_pref", 0);
Map<String, ?> scheduleData = preferences.getAll();
// set the schedule time
if(scheduleData.containsKey("fromHour") && scheduleData.containsKey("toHour")) {
int fromHour = (Integer) scheduleData.get("fromHour");
int fromMinute = (Integer) scheduleData.get("fromMinute");
int toHour = (Integer) scheduleData.get("toHour");
int toMinute = (Integer) scheduleData.get("toMinute");
//Do some action
}
}
}
Manifest very important, this is added under application:
<receiver android:name="AlarmReceiver">
<intent-filter>
<action android:name="packagename.ACTION"/>
<action android:name="packagename.ACTION2"/>
</intent-filter>
</receiver>
<receiver android:name="AlarmSetter" >
<intent-filter>
<action
android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Also in order for this to work you need to add permission to receive the boot Broadcast in the manifest with following line:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Hope this cleared things up, if any errors plz tell.
Edit (added alarmsetter example):
public class AlarmSetter extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Do your stuff
}
}
This answer seems pretty old.
Now, I would totally recommend people to check out SyncAdapter framework provided by Google.
It is custom made for such things.
Here's the link: https://developer.android.com/training/sync-adapters/index.html
In the demo it starts a service after 5 minutes since boot is complete which is just fine but what do I need to add to get it also start at every noon.
Change the initial time of the setRepeating() call. The example shows one minute from now -- you would need to do the calculations to determine when the next noon is.
You can see an example of that sort of calculation in this OnBootReceiver from a different sample project. Here, I am setting up the alarm to go off every day at a user-specified time.
I've poured through a dozen tutorials and forum answers about this problem, but still haven't been able to get some working code together. I'll try to keep the question straightforward:
How do you use AlarmManager (in the Android API) to start an Activity at a given time? Any solution to this problem will do.
My latest attempt to achieve this is below.
(Imports omitted. I expect MyActivity to start 3 seconds after the program is opened, which it doesn't. There are no error messages to speak of.)
public class AndroidTest2Activity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Context context = this;//.getApplicationContext();
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); // CORRECT
Intent intent = new Intent(context, myReceiver.class); // CORRECT
PendingIntent pending = PendingIntent.getBroadcast( context, 0, intent, 0 ); // CORRECT
manager.set( AlarmManager.RTC, System.currentTimeMillis() + 3000, pending ); // CORRECT
setContentView(R.layout.main);
}
}
public class myReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Intent i=new Intent(context, myActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
public class myActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("", "Elusive success");
setContentView(R.layout.main);
}
}
Any advice would be appreciated.
Please note: I've got myReceiver in the manifest already
In case someone else stumbles upon this - here's some working code (Tested on 2.3.3 emulator):
public final void setAlarm(int seconds) {
// create the pending intent
Intent intent = new Intent(MainActivity.this, AlarmReceiver.class);
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0,
intent, 0);
// get the alarm manager, and scedule an alarm that calls the receiver
((AlarmManager) getSystemService(ALARM_SERVICE)).set(
AlarmManager.RTC, System.currentTimeMillis() + seconds
* 1000, pendingIntent);
Toast.makeText(MainActivity.this, "Timer set to " + seconds + " seconds.",
Toast.LENGTH_SHORT).show();
}
public static class AlarmReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Log.d("-", "Receiver3");
}
}
AndroidManifest.xml:
<receiver android:name="com.example.test.MainActivity$AlarmReceiver" >
</receiver>
Issues with BenLambell's code :
EITHER:
Move the receiver to it's own .java file or
make the inner class static - so it can be accessed from outside
Receiver is not declared correctly in the manifest:
if it's an inner class in MainActivity use:
<receiver android:name="package.name.MainActivity$AlarmReceiver" ></receiver>
if it's in a separate file:
<receiver android:name="package.name.AlarmReceiver" ></receiver>
If your intention is to display a dialog in the receiver's onReceive (like me): that's not allowed - only activities can start dialogs. This can be achieved with a dialog activity.
You can directly call an activity with the AlarmManager:
Intent intent = new Intent(MainActivity.this, TriggeredActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
((AlarmManager) getSystemService(ALARM_SERVICE)).set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + seconds * 1000, pendingIntent);
How do you use AlarmManager (in the Android API) to start an Activity at a given time?
Supply a PendingIntent to the set() call that identifies the activity to start up. Or, do what you're doing, which should work just fine.
This sample project is a bit elaborate, because it's 19 tutorials deep into one of my books, but if you look at classes like EditPreferences, OnBootReceiver, and OnAlarmReceiver, you will see the same basic recipe that you're using above. In this case, I could have just used a getActivity() PendingIntent, but the tutorial after this one gives the user a choice of launching an activity or displaying a Notification, so a BroadcastReceiver makes more sense.
Look for warnings in addition to errors in LogCat. Most likely, your receiver or activity is not in your manifest.
Note that popping up an activity out of the middle of nowhere is generally not a good idea. Quoting myself from the book in question:
Displaying the lunchtime alarm via a full-screen activity certainly works,
and if the user is looking at the screen, it will get their attention. However,
it is also rather disruptive if they happen to be using the phone right that
instant. For example, if they are typing a text message while driving, your
alarm activity popping up out of nowhere might distract them enough to
cause an accident. So, in the interest of public safety, we should give the user an option to
have a more subtle way to remind them to have lunch.
add this in your android mainifest file and it will hopefully work
<activity android:name=".MyReceiver" />
<receiver android:name=".MyReceiver"> </receiver>
In my experience you can achieve this without broadcast receiver, just use PendingIntent.getActivity() instead of getbroadcast()
private void setReminder(){
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar startTime = Calendar.getInstance();
startTime.add(Calendar.MINUTE, 1);
Intent intent = new Intent(ReminderActivity.this, ReminderActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(ReminderActivity.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC, startTime.getTimeInMillis(), pendingIntent);
}
I've tested this code on android O but I'm not sure about other android versions please inform me if this doesn't work on any other android version.
Main Problem : if you close completely you're app and expect to start you're activity after 3 seconds, you wrong. because when you close you're app , you're app cant receive broadcast, for solve this problem use services instead of broadcasts.
Point: when you're service would ran ,you cant start your activity if your app wouldn't in foreground.
Solution: I think when your service started you can again set Alarmmanager to start your activity with PendingIntent for just now.
Remember :
When you create your intent for pass it to pendingIntent add the FLAG_ACTIVITY_NEW_TASK to it.
For this PendingIntent use PendingIntent.getActivity() method and for the first PendingIntent use PendingIntent.getService() method.
I hope this help you.
I had this problem too long ago to know which answer is correct, but thank you to everyone for their responses. I'm self-answering so the question isn't still open.
According to Java convention class name begin with Capital letter.So change your
"myReceiver" to "MyReceiver" and "myActivity" to "MyActivity".
Then add your receiver in the manifest file like the below.
<application
------------
<receiver android:name="MyReceiver"></receiver>
---------------------
</application>
you are not sending any broadcast for the receiver to receiver and further more it lokks like u want a splash screen or something like that for that purpose u can start a new thread wait for some sec then start ur activity in that and for that time period u can do what ever u want on the UI thread ...