public void runSound(){
Intent it = new Intent(Values.TAG_EXECUTE_ALARM);
PendingIntent pendIntent = PendingIntent.getBroadcast(this, 0, it, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND,0);
AlarmManager alarm = (AlarmManager) getSystemService(ALARM_SERVICE);
long time = calendar.getTimeInMillis();
alarm.set(AlarmManager.RTC_WAKEUP,time,pendIntent);
}
This method is called from a service. My service is supposed to play a sound to notify the user even if the device is on sleep mode.
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1) {
MediaPlayer player = MediaPlayer.create(arg0, R.raw.order_alarm);
player.setAudioStreamType(AudioManager.STREAM_ALARM);
player.start();
}
This is the class that will actually play the sound. Unfortunately the devices doesn't wake up and the sound is not played. When runSound is called before the device enters in sleep mode the sound works perfecly... Any ideas?
Edit:
-> Removed static references (yes, they were dumb, since runSound is inside a service).
-> Yes, the tag value is defined in receiver intent-filter
-> Improved the question.
Well, I cant test now, but looking at your code I can see some problems.
At getBroadcast(), the last parameter has to be a flag, like "FLAG_CANCEL_CURRENT", and I am not sure if 0 is a valid flag.
And at "long time = calendar.getTimeInMillis();" it looks like you are putting a time in the past, well if it is in the past, it will not run, try add 5000 (5s).
All others things looks fine to me.
Related
In my app, I use the AlarmManager class to set an alarm. To trigger the alarm after the mobile is rebooted I have used BroadcastReceiver. All works fine and my alarm is triggered at regular intervals. Now the problem arises in this case :
Suppose my current time is 2:30 pm and I set my alarm at 2:35 pm. After that, I switch off the mobile. After an hour when I switch on my mobile, no alarm is pop-up as the time on which the alarm is set. This is happening because the current time exceeds the time on which I set the alarm. To solve this issue what should I do. I have posted my code for setting alarm in the AlarmManager class. Please help me to solve this out
public class AlarmReceiver extends BroadcastReceiver {
#SuppressWarnings("static-access")
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
Intent myIntent = new Intent(context, MyAlarmService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, i, myIntent, i);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.MILLISECOND, (int) Utilities.diff(NoteManager.getSingletonObject().getAlarmTime(i)));
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
}
}
public static long diff(Date date) {
long difference = 0;
try {
// set current time
Calendar c = Calendar.getInstance();
difference = date.getTime() - c.getTimeInMillis();
if (difference < 0) {
// if difference is -1 - means alarm time is of previous time then current
// then firstly change it to +positive and subtract form 86400000 to get exact new time to play alarm
// 86400000-Total no of milliseconds of 24hr Day
difference = difference * -1;
difference = 86400000 - difference;
}
}
catch (Exception e) {
e.printStackTrace();
}
return difference;
}
In The Manifest File
<receiver android:name=".AlarmReciever">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
better way is to store that alarm details in database and retrieve it on boot via broadcast receiver as you are saying you implemented one. once notified remove the details from the database. this way u can track all your alarms. even you can start a Service on startup and do this operation
The Alarm app in the Android does the same, if your phone is switched off and there is Alarm to ring up, It will make your phone switch On , ring the alarm and go to sleep again.
Here is the link of source of Alarm app Git_Alarm app you can download it and see how it is doing this.
and if you are doing something else in your alarm reciever then to ring Alarm up. you can basically set alarmreciever again in the phone Boot up, here is the one answer which may help you Alarm problem if phone is switched off
Edit :- one link was broken, replaced it
In my app, I need to add a row to a database and simultaniously set up an Alarm event to repeat every day at the time specified in one of the database columns. I already have some code, but it doesent trigger the alarm event at the specified time. Here is my code:
public class Add_reminder extends Activity {
AlarmManager am;
int hours, minutes;
REMIND_DB db;
Calendar calendar;
Cursor cursor;
Button button;
public void onCreate(Bundle savedInstanceState) {
//The usual code in the beginning of onCreate
//I load db from extended Application class as global since i use it in more
//Activities. Ints hours and minutes is set by user interaction
calendar = Calendar.getInstance();
am = (AlarmManager) getSystemService(ALARM_SERVICE);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
db.open();
db.insertReminder( -- parameters for database --);
cursor = db.getAllReminders();
cursor.moveToLast();
calendar.set(Calendar.HOUR, hours);
calendar.set(Calendar.MINUTE, minutes);
Intent intent = new Intent(Add_reminder.this, ReminderAlarm.class);
intent.putExtra("id_of_db_row", cursor.getInt(0));
PendingIntent pi = PendingIntent.getActivity(Add_reminder.this,
cursor.getInt(0), intent, PendingIntent.FLAG_CANCEL_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
24*3600*1000, pi);
db.close()
}
});
}
}
Database is updated correctly, but the ReminderActivity never starts on specified time. I dont know what could be wrong. I saw some example codes using BroadcastReceiver instead of starting the Activity right on with the PendingIntent, but this should work too, right? Does anyone knows what could be wrong?
My second question is if Im going to need the same instance of AlarmManager when I want to add or remove some alarms from a different Activity, or do I just declare another AlarmManager in every Activity I need?
Thank you!
You should use a broadcast receiver for alarms, and then start a service that does the actual work. Broadcast receivers shouldn't block the UI thread with lengthy operations (such as writing to the DB). Additionally, 'once a day' alarms might be problematic: if the user reboots the phone: registered alarms will be lost. You need to:
save the time the alarm is supposed to run to, say, SharedPreferecnes
re-register your alarm when the phone boots (receive the BOOT_COMPLETED broadcast)
don't use setRepeating() but let each alarm register the next on
Using a shorter period (1 or 2 minutes) for testing also helps.
As for the AlarmManager instance, it's a system service, you don't need to care about what instance you are using. Just get it using getSystemService()
For testing purposes i have made a service that beeps
every 1 minute. (No client-server interface yet). It beeps okay when
the screen in on, but when it goes to sleep the beeping stops.
I am making an application that has to periodically poll the a server
for something.
For this, I am trying to create a service that'll constantly be
running in the background, poll the server every 1 min and then based
on the reply from server it shall generate a task bar notification.
I have a test activity with two buttons, 1 to start and the other to
stop the service. And one service class named S_PS_PollService
The setOnClickListener of 'Start Activity' button contains:
Thread pollServiceThread = new Thread() {
public void run() {
startService(new Intent(MM_MainMenu.this,
S_PS_PollService.class));
}
};
pollServiceThread.start();
The 'Stop Activity' button simply has:
stopService(new Intent(MM_MainMenu.this, S_PS_PollService.class));
Following are the methods from S_PS_PollService class:
public void onCreate() {
pollSound = MediaPlayer.create(this, R.raw.chirp);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent myIntent = new Intent(this, S_PS_PollService.class);
pendingIntent = PendingIntent.getService(this, 0, myIntent, 0);
// for wake lock
pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag")
// for calendar
calendar = Calendar.getInstance();
}
Onstart:
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
wl.acquire();
pollSound.start();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.MILLISECOND, 60000);
alarmManager.set(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), pendingIntent);
wl.release();
}
Whenever the alarm kicks off onStart() method is executed, making the
beep and setting new alarm. But it works only as long as screen is on.
I have tried for https://github.com/commonsguy/cwac-wakeful but didnt
get it. Relatively new to android ...
Please help me, im very desperate :) Thanks, !
You have to use the AlarmManager, there are plenty of posts here on stackoverflow.
You want to acquire a partial wake lock (leaving the CPU running whenever sleep is entered on the device) as suggested by your code.
The issue is your presumably overriden on start releases the wake lock. You want to release your wakeLock in onDestroy .. once your service is finished running.
This finally worked for me.
Download the CWAC-WakefulIntentService.jar from https://github.com/commonsguy/cwac-wakeful
add a class in your project
import com.commonsware.cwac.wakeful.WakefulIntentService;
public class WakeService extends WakefulIntentService {
public WakeService(String name) {
super(name);
}
#Override
protected void doWakefulWork(Intent intent) {
}
}
now add the following line in your code where ever you want to repeat the loop and wake the device up
WakefulIntentService.sendWakefulWork(this, S_WS_WakeService.class);
Ive implemented a mediaplayer and mediacontroller that streams a mp3 url. However my device on the TMobile network doesnt get a great 3G signal so it operates on EDGE. Im assuming that the mediaplayer is crashing because the stream is too slow or incomplete, is there a timeout I can set?
There is no timeout method in MediaPlayer, but you can implement it yourself - there are variety of ways you can do that.
I suggest one of them, that I used myself and it worked for me - BroadcastReceiver
Code would look like that:
public class ConnectivityCheckingReceiver extends WakefulBroadcastReceiver
{
private AlarmManager alarmManager;
private PendingIntent pendingIntent;
#Override
public void onReceive(Context context, Intent intent)
{
if (MusicService.mediaPlayer != null)
{
if (!MusicService.mediaPlayer.isPlaying())
Log.v("Music", "Music is NOT playing");
//stop service and notify user
else
Log.v("Music", "Music is playing");
}
else
{
Log.v("Music", "User stopped player");
}
}
public void setAlarm (Context context, int hour, int minute, int second)
{
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, ConnectivityCheckingReceiver.class);
pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
}
In your activity/service/fragment you add this line:
ConnectivityCheckingReceiver conCheck = new ConnectivityCheckingReceiver();
conCheck.setAlarm(context, hour, min, second);
You will need to implement hour/min/second checking logic yourself, but it's easily done with libraries like Joda Time.
And don't forget to add to your manifest:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<receiver android:name=".receivers.ConnectivityCheckingReceiver" />
Ps, my solution is not perfect, but I have not seen any good answers for this question, so if find one, please share it.
You can also use prepare() instead of prepareAsync() on MediaPlayer and put it inside asyncTask or worker thread; then you can inmplement timeout functionality by yourself. I will add a code sample later, but the idea is clear I think.
Indeed Mediaplayer takes some time to buffer and on slow networks that can lead to problems.
You cannot control this process, there is no user set timeout, but you can make sure it doesn't crash your app by catching all exception that methods such as setDataSource(), prepare(), prepareAsync(), and start() can throw.
I have set a AlarmManager which will give alarm repeatedly after certain time. I used following code for that.
Intent intent = new Intent(ViewDoughnut.this, NotificationMessage.class);
PendingIntent sender = PendingIntent.getBroadcast(ViewDoughnut.this, 0, intent,PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP,nextAlarmTime, alarmInterval, sender);
Now to execute proper work at the alarm time I have created the following class extending BroadcastReceiver. Now I need the time in millisecond when the Alarm work should execute in that class. How to get it?
public class NotificationMessage extends BroadcastReceiver {
// Display an alert that we've received a message.
// #Override
public void onReceive(Context context, Intent intent) {
// here I need the time when the alarm should execute.
}
}
Here I like to add, system time is not working for me, because if the device is switch off at the alarm time, it execute that when the device is on after that time. But I need the time when it should execute.
You could create a class that derives from Application which holds all global variables. Then just set a long variable to hold the time before initialising the alarm