Vibration triggered by alarm when device is asleep doesn't stop - android

I'm rather wondering if this is specific to my device (Nexus 4, Android 4.3, stock ROM), but I have an alarm, registered once via the AlarmManager. When triggered, the device is set to vibrate for two seconds. If the alarm is triggered while the device is on, then it correctly vibrates for the two seconds. However, if the alarm is triggered when the device is off (and unplugged), the vibration starts, but doesn't stop until the power button is pressed (to wake up the device). Here is the code to register the alarm:
public static void registerAlarm(Context context, int uniqueId, long triggerAlarmAt)
{
Intent intent = new Intent(context, AlarmReceiver.class);
intent.setAction("com.myapp.ALARM_EVENT");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), uniqueId, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, triggerAlarmAt, pendingIntent);
}
And the receiver code:
public class AlarmReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent arg1)
{
Toast.makeText(context, "Test of alarm", Toast.LENGTH_LONG).show();
Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(2000);
}
}
Any ideas on why this is happening or how to prevent it?

Finally figured this one out. My innocuous 'Toast' which gets triggered before the vibration was causing the vibrator to hang until the toast was complete. The Toast wasn't showing until the screen was turned on and this somehow blocked the completion of the vibration. Removing the Toast solved my issue and the vibration ceased after two seconds as expected even with the screen off.

Related

Android notifications not always delivered

I'm writing my android application, which should always show a notification every day at 10:00 AM, no matter what. I use an alarm service to fire notifications at a specific time.
I set notifications to fire in two cases:
when I open the app, I set the alarm service to fire at the nearest 10:00 AM
when I receive notifications, I set the alarm service to fire the next day at 10:00 AM
The problem is: When the interval between the moment when I set alarm service and the actual alarm is greater than approx 12 hours, I just don't receive that notification. If the interval is smaller - I do. But I checked the logs, the alarm service is scheduled properly and for the correct time no matter how I set notifications.
I expect the problem is in the battery optimizer, but I don't know how to verify (and fix) that.
What I tried
In Android I've added my app to exceptions, allowing it to run in the background.
Tested on Huawei P30 Pro, Android 10.
Attaching the code how notifications are scheduled
public class AlarmBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// display notification
NotificationController.scheduleNextNotification(context);
}
}
public class NotificationController {
public static void scheduleNextNotification(Context context) {
Intent myIntent = new Intent(context, AlarmBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
long notificationTime = getNotificationTime(new Date());
int alarmType = AlarmManager.RTC_WAKEUP;
alarmManager.setExactAndAllowWhileIdle(alarmType, notificationTime, pendingIntent);
}
}

BroadcastReceiver not firing when phone is sleeping

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.

AlarmManager only lets one Service through when used with setRepeating in Android

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.

Wakeful IntentService work incomplete thith Notification in sleep mode

I have set up AlarmManager for 1 minute for test mode. It sends broadcast to OnAlarmReceiver.
OnAlarmReceiver start sendWakefulWork(context, TaskService); and in TaskService in doWakefulWork() method i sendOrderedBroadcast which fire Notification.
This works well^ notification with sound and vibration appear. But only when phone in active mode. When phone in sleep mode (screen is switched off) only vibration and flash work during notification. No sounds from notification in sleep mode, only vibration. Sometimes it make sounds, but only sometimes , for example make 1 sound in hour, but it should make sound every minute. Also it make sounds every minute in sleep mode when phone connected to the computer but when I unplug phone from computer it starts only vibrate. When I turn on screen everything becomes normal: notification plays sound + vibration.
So I have no idea if it problem with my code or with my phone (HTC Desire Android 2.2)
I have tried a lot of things to fix it:
default and custom sounds
notification.audioStreamType = AudioManager.STREAM_SYSTEM and others
with flash and without flash
with vibration and without vibration
Nothing. Only sounds disappear in sleep mode, vibration worked perfect.
public class OnBootReceiver extends BroadcastReceiver {
public static void setAlarm(Context ctxt) {
AlarmManager mgr = (AlarmManager) ctxt.getSystemService(Context.ALARM_SERVICE);
mgr.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis()+1000,
1*60*1000,
getPendingIntent(ctxt));
}
public static void cancelAlarm(Context ctxt) {
AlarmManager mgr = (AlarmManager) ctxt.getSystemService(Context.ALARM_SERVICE);
mgr.cancel(getPendingIntent(ctxt));
}
private static PendingIntent getPendingIntent(Context ctxt) {
Intent i=new Intent(ctxt, OnAlarmReceiver.class);
return PendingIntent.getBroadcast(ctxt, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
}
#Override
public void onReceive(Context ctxt, Intent intent) {
setAlarm(ctxt);
}
}
My doWakefulWork method in TaskService class:
protected void doWakefulWork(Intent intent) {
Intent mIntent = new Intent(EXERCISE_EVENT);
mIntent.putExtra(StringUtils.PARAM_NEXT_TASK_TIME, nextStringTime);
mIntent.putExtra(StringUtils.PARAM_TASK_NUMBER, taskNumber);
sendOrderedBroadcast(mIntent, null);
}
And this is my NotificationBrodcastReceiver :
public class NotificationBrodcastReceiver extends android.content.BroadcastReceiver {
public void onReceive(Context ctx, Intent intent) {
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) ctx.getSystemService(ns);
int icon = R.drawable.notif_icon;
CharSequence tickerText = ctx.getResources().getString(R.string.notification_ticker);
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.defaults |= Notification.DEFAULT_SOUND;
notification.defaults |= Notification.DEFAULT_VIBRATE;
Intent notificationIntent = new Intent(ctx, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0, notificationIntent, 0);
notification.setLatestEventInfo(ctx, "contentTitle", "contentText", contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, notification);
}
}
You are using an ordered broadcast to raise your Notification. Presumably, you are doing this because you want an activity to handle the request if the activity is in the foreground and has a higher-priority BroadcastReceiver for this broadcast.
That pattern is fine for non-wakeful situations. However, once doWakefulWork() ends, nothing is going to keep the device awake, and so the device will fall back asleep. Your ordered Broadcast happens asynchronously, so the its work will happen after doWakefulWork() ends, and so your Notification may not happen at all. If the Notification is partially happening, as you describe, I would personally consider this behavior to be a bug in Android (it should hold its own WakeLock for the purposes of playing back the ringtone), but it is entirely possible that your BroadcastReceiver simply does not get control at all, because the device falls asleep before the broadcast is delivered.
Your hold-a-WakeLock-for-two-seconds workaround will increase the odds of success, but that too is not guaranteed. The only guaranteed ways to ensure that you will get a chance to raise the Notification is to either:
do that work inside of doWakefulWork(), or
hold a WakeLock until the broadcast is completed and the Notification is raised.
I will look to add additional features to the WakefulIntentService framework in the future to handle your scenario better, as what you appear to want to do is reasonable, and it would be nice to have a common implementation of the pattern. However, what you are trying to do is definitely outside the current scope of what WakefulIntentService does.

How to develop Android Alarm application

I tried to develop a sample Alarm Application. I searched Google and SC, most of their examples confused. How can I create an alarm application with the following requirements,
In My Home screen i have a button, like "START ALARM", when i click the button a time picker must enable.
I select the time as I wish, once I pick the time, the alarm icon will enabled on widget. (For example if we set the alarm in default mobile Alarm application, the icon will be enabled, that indicates the alarm is set).
When the set time is reached (the time which is set form the TimePicker app), the alarm will beep.
These are my requirements, I finished the first two points, but I'm still struggling on setting the alarm.
Take a look at AlarmManager. And, If you want to use alarm simultaneously you must use Service class for that. And, see below sample code -
public class OnBootReceiver extends BroadcastReceiver {
private static final int PERIOD=300000; // 5 minutes
#Override
public void onReceive(Context context, Intent intent) {
AlarmManager mgr =
(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i=new Intent(context, OnAlarmReceiver.class);
PendingIntent pi=PendingIntent.getBroadcast(context, 0, i, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime()+60000, PERIOD, pi);
}
This will repeat the alarm with every 6 Mins. See Scheduling Repeating Alarms document.
when you enable the alarm you have to call inbuilt alarm manager and use the alarmmanager.set to set the alarm time in the manager.
Once the alarm time (in milliseconds) is given to the alarm manager it will send message and you can retrive the message through reciever class
//creating and assigning value to alarm manager class
Intent AlarmIntent = new Intent(MainActivity.this, AlarmReciever.class);
AlarmManager AlmMgr = (AlarmManager)getSystemService(ALARM_SERVICE);
PendingIntent Sender = PendingIntent.getBroadcast(MainActivity.this, 0, AlarmIntent, 0);
AlmMgr.set(AlarmManager.RTC_WAKEUP, Alarm.getTimeInMillis(), Sender);
For recieving the alarm you have to make a new class which extends reciever where in onrecieve you can set the intent to the activity u want to call on alarm time , you can also provide notification.
public class AlarmReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{ //Build pending intent from calling information to display Notification
PendingIntent Sender = PendingIntent.getBroadcast(context, 0, intent, 0);
NotificationManager manager = (NotificationManager)context.getSystemService(android.content.Context.NOTIFICATION_SERVICE);
Notification noti = new Notification(android.R.drawable.stat_notify_more, "Wake up alarm", System.currentTimeMillis());
noti.setLatestEventInfo(context, "My Alarm", "WAKE UP...!!!", Sender);
noti.flags = Notification.FLAG_AUTO_CANCEL;
manager.notify(R.string.app_name, noti);
//intent to call the activity which shows on ringing
Intent myIntent = new Intent(context, Alarmring.class);
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
//display that alarm is ringing
Toast.makeText(context, "Alarm Ringing...!!!", Toast.LENGTH_LONG).show();
}}
If you still get any problem ask again..:)
If you want to make things interesting, you can try to create one without a possibility of dismissing/snoozing. I made this a while ago, you can read about it in this tutorial:
Alarm Application in Android (Tutorial using AlarmManager)
And test the app functionality by downloading this app:
Oversleeper on Google Play
To finish your last point you need to do Date Comparision and use AlaramManager Alaram Doc and again you need to use Service
to compare next date and time. Hope it will helpful for you.
You need to use RingtoneManageror the NotificationManager(to show any text or image to the user for notification at the top of screen), Or you can use MediaPlayerto set to play sound when alarm time is reached. You have to set <receiver> tag in manifest file, that must include a class extending BroadCastReceiver. In the receiver class you can write your code to wake your device up.

Categories

Resources