I have a app that takes care of certain silence functions, but I can't make it work when the phone is sleeping and not connected to the computer. Everything works fine when the screen is on, but it stops working when the phone sleeps.
Any idea what I'm doing wrong? I have checked 100 other posts here, but I just can't identify my problem.
My Alarm manager that makes the intent:
Intent intent2 = new Intent(this, Silence.class);
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(this, 1000 + id, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am2 = (AlarmManager)getSystemService(Activity.ALARM_SERVICE);
am2.setRepeating(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), AlarmManager.INTERVAL_DAY * 7, pendingIntent2);
Broadcast Receiver:
public class MainSilenceCatcherVibrate extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent1) {
WakeLocker.acquire(context);
System.out.println("test");
WakeLocker.release();
}
}
Manifest usage:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<receiver android:name=".Silence"></receiver>
<activity android:name=".ContactActivity"></activity>
i just cant identify my problem
Your event will happen once immediately, then not again for a week (AlarmManager.INTERVAL_DAY * 7,). Perhaps you did not wait a week.
Note that you do not need WakeLocker here -- so long as all your work is in onReceive(), the system will hold a WakeLock for you. If you have work that will take more than a millisecond or so, you will not want to do that in onReceive(), but in that case I would recommend WakefulBroadcastReceiver or my WakefulIntentService over rolling your own WakeLock solution.
Related
I'd like to repeat an alarm every 20 minutes.
So I tried:
manifest:
<receiver android:name=".AlarmReceiver" />
AlarmReceiver.class
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent intent2 = new Intent(context, MainActivity.class);
showNotification(context, "text", "text", intent2);
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(context, notification);
r.play();
}
#TargetApi(Build.VERSION_CODES.N)
public void showNotification(Context context, String title, String body, Intent intent) {
...
}
}
and in my main activity:
AlarmManager alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
Calendar time = Calendar.getInstance();
time.setTimeInMillis(System.currentTimeMillis());
time.add(Calendar.SECOND, 1200);
alarmMgr.set(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(), pendingIntent);
It is working only the first time. I'd like to keep it repeating even when the app is not opening, any ideas?
Starting with KitKat (API 19), alarms are all inexact, meaning the system will batch alarms around similar times together. If you need exact timing, there are different APIs to call. Further complicating things, starting with Marshmallow, Android introduced the concept of Doze, which further restricts the when/how things can wake up the device. You can still use exact alarms, but need to use the API which allows it during idle (Doze) time: setAndAllowWhileIdle(). Bear in mind that when your alarm fires, you could be in a Doze window and your app will be restricted on what kinds of operations it can perform.
Try below for Repeating alarm on every 20 minutes interval
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(),1000 * 60 * 20, pendingIntent);
Try to use android worker manager since it is working with doze mode as well. https://developer.android.com/reference/androidx/work/PeriodicWorkRequest#min_periodic_interval_millis
https://developer.android.com/reference/androidx/work/PeriodicWorkRequest
I have some existing code that spawns a service intent which does a bunch of stuff in the background. This code does work...
Intent serviceIntent = new Intent(context, APMService.class);
serviceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startService(serviceIntent);
My question is: how to change this to use the AlarmManager.setInexactRepeating(...) methods?
I have changed the above code to this:
Intent serviceIntent = new Intent(context, APMService.class);
serviceIntent.putExtra("STARTED_BY", starter);
serviceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//Set up recurring alarm that restarts our service if
// it crashes or if it gets killed by the Android OS
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pi = PendingIntent.getService(context, 0, serviceIntent, 0);
//am.cancel(pi);
am.setInexactRepeating(
AlarmManager.ELAPSED_REALTIME_WAKEUP //wake up the phone if it's asleep
, cal.getTimeInMillis()
, 10000
, pi);
And I have added these permissions to AndroidManifest.xml...
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
<uses-permission android:name="com.android.alarm.permission.WAKE_LOCK"/>
My understanding is that this is supposed to start the service immediately and then try to restart it again every 10 seconds. But this code isn't working properly.
Using this new code, the service never starts at all and I cannot see why not. To complicate matters the debugger never seems to attach to the app in time to see what's going on.
Can anyone see what I'm doing wrong?
Put AlarmManager code under onDestroy() function of service to schedule start of service as below:
#Override
public void onDestroy() {
/**
* Flag to restart service if killed.
* This flag specify the time which is ued by
* alarm manager to fire action.
*/
final int TIME_TO_INVOKE = 5 * 1000; // try to re-start service in 5 seconds.
// get alarm manager
AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AutoStartServiceReceiver.class);
PendingIntent pendingIntent = PendingIntent
.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
// set repeating alarm.
alarms.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() +
TIME_TO_INVOKE, TIME_TO_INVOKE, pendingIntent);
}
And handle starting of your service in AutoStartServiceReceiver as below:
public class AutoStartServiceReceiver extends BroadcastReceiver {
private static final String TAG = AutoStartServiceReceiver.class.getSimpleName();
#Override
public void onReceive(Context context, Intent intent) {
// check broadcast action whether action was
// boot completed or it was alarm action.
if (intent.getAction().equals(AppConstants.ACTION_ALARM_INTENT)) {
context.startActivity(new Intent(context, YourActivity.class));
// handle service restart event
LockerServiceHelper.handleServiceRestart(context);
}
}
}
Kindly note that, your service will not restart if you stop it manually from settings-apps-running apps-your app.
Your service is not starting because of AlarmManager.ELAPSED_REALTIME_WAKEUP, while it should be using AlarmManager.RTC_WAKEUP
If you want to run every 10s keep in mind that above API 21 alarm intervals below 60s are rounded up to 60s.
Also, consider using WakefulIntentService
https://github.com/commonsguy/cwac-wakeful
I've been trying to use AlarmManager.RTC_WAKEUP to wake up my device to play some sounds.
Here's the alarm scheduling:
Intent intent = new Intent(Main.this, OneShotAlarm.class);
PendingIntent sender = PendingIntent.getBroadcast(Main.this, 0, intent, 0);
// I want the alarm to go off 60 seconds from now.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 60);
// Schedule the alarm!
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(), sender);
The OneShotAlarm BroadCastReceiver:
public class OneShotAlarm extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context, "OneShotAlarm Broadcast invoked", 1000).show();
intent = new Intent(context, ServiceClassToRun.class);
context.startService(intent);
}
}
The Service:
public class ServiceClassToRun extends Service {
protected static final int Rnd = 0;
public void onStart(Intent intent, int startId) {
//do some business here
}
And finally, my manifest:
<receiver android:name=".OneShotAlarm" android:process=":remote" />
<service android:name=".ServiceClassToRun "/>
My service works fine when device is in wake up state.
Any ideas are greatly appreciated. Has anyone else experienced this as
well? Thanks in advance.
PendingIntent sender = PendingIntent.getBroadcast(Main.this, 0, intent, 0);
change to
PendingIntent sender = PendingIntent.getBroadcast(Main.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
OR, If you miss the permission of alarm, than add these permission
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
Let me know, If it's work for you
I doubt that this is still relevant for the author, but maybe it will be useful for someone else.
Probably the reason for the issue is that you do not acquire any wakelocks. System holds a wakelock for you while OneShotAlarm.onReceive is called. You start a service by sending an intent. But after the OneShotAlarm.onReceive returns, there are no held wakelocks left and the device goes to sleep. Therefore your intent will be only delivered when you manually wake up the device.
You can see an example with a wakelock here https://github.com/yuriykulikov/AlarmClock/blob/develop/src/com/better/alarm/model/AlarmsService.java
Best regards,
Yuriy
Your Service - ServiceClassToRun will be called 1 minute after you have set the alarm..But you won't come to know it as you havn't done anything in onStart() method.Also override onBind and onCreate methods.
You may implement Notification or play sound when onStart method of Service is called
You can ask if you have any further queries.
I've been struggling with this for a couple of days. What I want to do is run a service periodically, about 2-3 minutes apart. I have an Activity that is responsible for the interface and setting up the first alarm.
The alarm is configured by a BroadcastReceiver which looks like this:
public class Receiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String message = "Alarm worked";
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
setAlarm(context);
}
public void setAlarm(Context context){
AlarmManager am = (AlarmManager) context.
getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, Receiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context,
0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Intent dailyUpdater = new Intent(context, DiscoveryService.class);
context.startService(dailyUpdater);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
+ (1000 * 30) , pi);
}
}
I've tried using setRepeating for AlarmManager, but it still has the same effect. What happens is that the AlarmManager works how it should, it fires an Intent which the receiver gets and executes onReceive periodically, as it should. However, it executes the service only the first time. After the first time, the alarms still go off, but the service is not executed.
I read some threads from people with similar problems, and one of them mentioned that PendingIntent lasts for only one send. Thus, I opted out to setting the alarm every time so I can set pendingIntent flag for updating every time.
I tried making my service an intentService, which is fine, but then my bluetooth scanner inside the service does not work because intentService thread terminates without waiting for my bluetooth discovery to finish.
Anyone have any idea what can help me?
Here is part of my service:
public class DiscoveryService extends Service {
public void onCreate() {
super.onCreate();
Toast.makeText(this, "MyAlarmService.onCreate()",
Toast.LENGTH_LONG).show();
findEverything();
}
}
EDIT: This is the code that I currently have.
public void onReceive(Context context, Intent intent) {
String message = "Alarm worked";
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
Intent dailyUpdater = new Intent(context, DiscoveryService.class);
context.startService(dailyUpdater);
}
public void setAlarm(Context context){
// get a Calendar object with current time
AlarmManager am=(AlarmManager)context.
getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, Receiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
(1000 * 30) , pi);
}
What happens is that the AlarmManager works how it should, it fires an Intent which the reciever gets and executes onReceive periodically, as it should. However, it executes the service only the first time. After the first time, the alarms still go off, but the service is not executed.
You are calling startService() once when you are scheduling the alarm. You are not calling startService() at all from your BroadcastReceiver. Yet you are scheduling the alarm via the BroadcastReceiver. Hence, when the alarm goes off, the service will not be sent a command, because you are not sending it a command.
I read some threads from people with similar problems, and one of them mentioned that PendingIntent lasts for only one send.
That is only if you use FLAG_ONE_SHOT.
Anyone have any idea what can help me?
Call startService() from your onReceive() method, instead of from your setAlarm() method. Also, add in all the WakeLock management logic, since you are using a _WAKEUP alarm and you are not able to use my WakefulIntentService.
I'm developing a live wallpaper for Android. To refresh the wallpaper at set times I use AlarmManager. Most of the times this works great, but occasionally my alarm isn't received. On top of that I can't replicate this behaviour, it just randomly happens. I've run into this using at least 3 ROMs.
Now for the code.
I use this PendingIntent:
mRefreshIntent = new Intent()
.setComponent(new ComponentName(mContext, RefreshBroadcastReceiver.class))
.setAction("my.package.name.REFRESH_WALLPAPER");
mPendingRefreshIntent = PendingIntent.getBroadcast(
mContext,
0,
mRefreshIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
This is my code to set the alarm:
mAlarmManager.set(AlarmManager.RTC_WAKEUP, time, mPendingRefreshIntent);
where time is the UTC time in milliseconds. I often verified if the alarm is set as intended using adb shell dumpsys alarm, which it is.
The receiving side:
public class RefreshBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("DayNight", "onReceive ; " + System.currentTimeMillis());
DayNightService.refresher.refresh();
Log.d("DayNight", "onReceive done; " + System.currentTimeMillis());
}
}
Associated manifest lines:
<application>
...
<receiver
android:name="RefreshBroadcastReceiver">
<intent-filter>
<action android:name="my.package.name.REFRESH_WALLPAPER" />
</intent-filter>
</receiver>
...
</application>
Alarms which are not fired always exist in the queue (dumpsys alarms) beforehand, and are not in the alarm log afterwards. Seems like they get 'lost' at T minus zero.
I will be very happy if one of you can solve this problem for me.
I use following code:
Intent intent = new Intent(ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_NO_CREATE);
Log.d(LOG_TAG, "pending intent: " + pendingIntent);
// if no intent there, schedule it ASAP
if (pendingIntent == null) {
pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
// schedule new alarm in 15 minutes
alarmService.setInexactRepeating(AlarmManager.RTC, System.currentTimeMillis(),300000, pendingIntent);
Log.d(LOG_TAG, "scheduled intent: " + pendingIntent);
}
Note, that I request inexact repeating alarm and RTC ( not RTC_WAKEUP ) - if phone is sleeping deep inside jeans pocket, user is not interested on changes of your live wallpaper - no need to waste battery juice and wake phone up
You may also need to register boot complete broadcast receiver to start update scheduling
on reboot.