I have 2 activities, a Main Activity and SetAlarm Activity. I call SetAlarm Activity from Main. When I set up the alarm I create an instance of my main. How do I set up the alarm without creating another instance of the Main or do I kill the main before setting up the alarm? Quite new to this. I have read several of the alarm manager examples, but they all seem to set up a new intent and I think this is what is creating my 2 instances. Is this how you set up the alarm. It does go off.
Here is how I call SetAlarm from the Main:
public void setAlarm(View view) {
Intent intent = new Intent(this, SetAlarmActivity.class);
startActivityForResult(intent, 2);
}
Here is how I set up the Alarm:
public void setUpAlarm() {
if (VERBOSE) Log.v(TAG, "+++ IN setUpAlarm +++");
PLAY_MUSIC = "Y";
Intent intentAlarm = new Intent(this, MainActivity.class);
intentAlarm.putExtra("playMusic",PLAY_MUSIC);
intentAlarm.putExtra("mPos", mPos);
intentAlarm.putExtra("result",ALARM_SET);
setResult(RESULT_OK,intentAlarm);
pIntent = PendingIntent.getActivity(this, 12345,
intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE ));
am.set(AlarmManager.RTC_WAKEUP, calSet.getTimeInMillis(), pIntent );
} // setAlarmPlaySong
I cut the alarm off in the main:
#Override
public void onResume() {
if (VERBOSE) Log.v(TAG, "+++ IN onResume +++");
super.onResume();
Intent intent = getIntent()
if (intent.hasExtra("playMusic") && intent.hasExtra("mPos")) {
playMusicFlag = intent.getStringExtra("playMusic");
mPos = intent.getIntExtra("mPos", 0);
if (playMusicFlag.equalsIgnoreCase("Y")) {
if (VERBOSE) Log.v(TAG, "+++ playMusicFlag is SET+++");
playSongs();
showStopAlarmButton();
} // if
}
}
if you want that your startActivity should not start multiple instances of alam activity
you should go to your manifest and have to add an attribute named launchMode for your alarm activity and set it to SingleTop that will ensure that only one instance remains in the taskk back stack(plac where every activity resides in LIFO manner)
In default, an Activity can be instantiated multiple times on multiple tasks. If you want to keep it single, specify android:launchMode="singleTask" on the activity declaration in AnroidManifest.xml and override Activity#onNewIntent() on your main activity to receive a new intent from AlarmManager if main activity is already instantiated.
See Tasks and Back Stack to learn more. You are facing almost same situation shown in Figure 3.
I dont know why you have the SetAlarm Activity, you dont need a activity to set the alarm. Anyways, AlarmManager is a pain to get working. It took me a while to get it up and running. This is what I have in my code now, running.
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 5);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent notifyintent = new Intent(this, OnAlarmReceiver.class);
notifyintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
notifyintent.setAction("android.intent.action.NOTIFY");
PendingIntent notifysender = PendingIntent.getBroadcast(this, 0, notifyintent,
PendingIntent.FLAG_UPDATE_CURRENT);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 20 * 1000,
notifysender);
OnAlarmReceiver
public class OnAlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// PullPendingRequests.acquireStaticLock(context)
try {
lock = getLock(context);
lock.acquire();
context.startService(new Intent(context, UpdateCustomerRequests.class));
} finally {
if (lock.isHeld()) {
lock.release();
}
}
}
private static final String NAME = "com.commonsware.cwac.wakeful.WakefulIntentService";
private static volatile PowerManager.WakeLock lockStatic = null;
private static PowerManager.WakeLock lock;
synchronized private static PowerManager.WakeLock getLock(Context context) {
if (lockStatic == null) {
PowerManager mgr = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NAME);
lockStatic.setReferenceCounted(true);
}
return (lockStatic);
}
}
IntentService which is called by OnAlarmReceiver
public class UpdateCustomerRequests extends IntentService {
#Override
final protected void onHandleIntent(Intent intent) {
//
//Your stuff here
//
}
public class LocalBinder extends Binder {
public UpdateCustomerRequests getService() {
return UpdateCustomerRequests.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return bindToHomeScreen;
}
}
Android Manifest
Inside manifest tag
<uses-permission android:name="android.permission.WAKE_LOCK" />
Inside application tag
<receiver
android:name="com.taxeeta.support.OnAlarmReceiver"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.NOTIFY" />
</intent-filter>
</receiver>
Related
I've been stuck on this for days now.
I want my alarm manager to fire off every 15 minutes even when the app is closed but it does not work when app is closed. It works while app is open though.
In my manifest file I have:
<!-- Used to consume the alarm manager alerts when app clsoed -->
<receiver
android:name="biz.customName.pkg.AlarmReceiver"
android:enabled="true">
<intent-filter>
<action android:name="biz.customName.pkg.msg"/>
</intent-filter>
</receiver>
My BroadcastReceiver class (AlarmReceiver)
public class AlarmReceiver extends BroadcastReceiver
{
// Alarm manager used to run install when app is closed
AlarmManager alarmManager;
// Called when alarm received
#Override
public void onReceive(Context context, Intent intent)
{
// Enable alarm
setupAlarm(context);
// Perform background task
}
// Setup alarm
public void setupAlarm(Context context)
{
// Setup reciever for alarm
// context.registerReceiver(this, new IntentFilter("biz.customName.pkg.msg"));
// Setup pending intent
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, new Intent(Loader.filterName), PendingIntent.FLAG_UPDATE_CURRENT);
// Setup alarm
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
final long triggerTime = System.currentTimeMillis() + 900 * 1000;
// Newest OS
if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 23)
{
alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent);
}
}
}
In main I call setup alarm to get the alarm going initially then each time the onReceive inside my Broadcast receiver is called I reset the alarm.
What am I doing wrong that it doesn't work when the app is closed?
Add this in your AndroidManifest.xml
<service
android:name=".MyService"
android:enabled="true"
android:exported="true" />
<receiver
android:name=".MyAlarmReceiver"
android:enabled="true"
android:exported="true" />
MyAlarmReceiver.java
public class MyAlarmReceiver extends BroadcastReceiver {
Context context;
public MyAlarmReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
intent = new Intent(context, MyService.class);
context.startService(intent);
}
}
MyService.java
public class MyService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
YourTask();
return Service.START_STICKY;
}
private void YourTask(){
// call api in background
// send push notification
//etc...
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
PendingIntent pendingIntent;
AlarmManager alarmManager;
Intent alarmIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AutoUpdateDataInBackground();
}
private void AutoUpdateDataInBackground() {
// Retrieve a PendingIntent that will perform a broadcast
alarmIntent = new Intent(MainActivity.this, MyReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, alarmIntent, 0);
alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
long interval = 15 * 60 * 1000;
// Repeating on every 15 minutes interval
Calendar calendar = Calendar.getInstance();
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),interval, pendingIntent);
}
}
BTW : AlarmManager will not be called with locked screen and enabled energy saving mode
I want to trigger a one-time alarm with the following, which is basically a replicate from https://developer.android.com/training/scheduling/alarms.html (second ELAPSED_REALTIME_WAKEUP example).
This is inside public static class PlaceholderFragment extends Fragment implements View.OnClickListener:
#Override
public void onClick(View v) {
Intent intent;
intent = new Intent(this.getActivity(), MuteReceiver.class);
AlarmManager alm = (AlarmManager)(this.getActivity().getSystemService(Context.ALARM_SERVICE));
PendingIntent alarmIntent = PendingIntent.getBroadcast(getActivity(), 0, intent, 0);
alm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 60*1000,
alarmIntent);
Log.d("MainActivity", "alarm set");
}
public class MuteReceiver extends BroadcastReceiver is like this:
public MuteReceiver() {
Log.d("MuteReceiver", "constructed");
}
#Override
public void onReceive(Context context, Intent intent) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean started = prefs.getBoolean(MuteService.STARTED, false);
Log.d("MuteReceiver", "Started=" + started);
}
I pressed the button in the Fragment, saw the log message "alarm set", but after one minute (and much later), still no log about MuteReceiver being constructed or MuteReceiver started (in onReceive)
You have a guaranteed list file with a registered broadcast
I am trying to implement an AlarmManager using an inner BroadcastReceiver class. Here is my inner class:
public class MyAlarm extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "alarm worked", Toast.LENGTH_SHORT).show();
}
public void setAlarm(Context context) {
AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyAlarm.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 10000, pi);
}
}
Since its an inner class I understand that I have to dynamically register the receiver. In my main activity I have the following code:
IntentFilter filter = new IntentFilter();
MyAlarm alarm = new MyAlarm();
alarm.setAlarm(this);
this.registerReceiver(alarm, filter);
The alarm isn't firing for me.
As far as I know, you can't use a LocalBroadcastReceiver with AlarmManager, because with localBroadcast the data doesn't leave the application, it works within the app process (local), and the alarm manager works with different processes.
Actually the pending intent would be the "problem" here:
The PendingIntent class provides a mechanism for creating intents that
can be fired on your application's behalf by another application at a
later time
As you can see by definition the pendingIntent works with different processes. That would be the reason you cannot make it work with a local broadcast.
You would need to register the receiver in the manifest, and as #leesei said, you have to declare the inner class as static.
Not knowing the details of your project, I'm inclined to say don't use a receiver, use a Handler and post a delayed runnable while your activity is in the foreground.
private static final long DELAY = 10000;
private Handler handler;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handler = new Handler();
}
protected void onStart() {
handler.postDelayed(doSomethingRunnable, DELAY);
}
protected void onStop() {
handler.removeCallbacks(doSomethingRunnable);
}
private Runnable doSomethingRunnable = new Runnable() {
#Override
public void run() {
doSomething(); // the method you wanted to call
handler.postDelayed(this, DELAY);
}
}
Docs: IntentService
public class MyService extends IntentService() {
private static final String TAG = "MyService"
public MyService() {
super(TAG);
}
#Override
public void onHandleIntent(Intent intent) {
// do your work here
}
}
Somewhere else, possibly in your activity, you will create an alarm to run your service periodically:
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyAlarm.class);
PendingIntent pi = PendingIntent.getService(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 10000, pi);
I'm not sure what your use case it, but once every ten seconds seems a bit aggressive. You may want to consider a longer interval.
use this code in your onreceive method of Broadcastreceiver-
#Override
public void onReceive(Context context, Intent intent)
{
//you need to acquire the power lock
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "YOUR TAG");
wl.acquire();
//do you things
//then release the lock
wl.release();
}
What am I doing wrong here? I have setalarm and wakelock in manifest. Im a beginner with Alarm Manager
public class AlarmManagerActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_alarm_manager);
}
public void scheduleAlarm(View V)
{
Intent intentAlarm = new Intent(this, AlarmReceiverActivity.class);
// create the object
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
//set the alarm for particular time
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (5 * 1000), PendingIntent.getBroadcast(this,1, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT));
}
}
public class AlarmReceiverActivity extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
System.out.println("YO!");
Toast.makeText(context, "Alarm Triggered in ", Toast.LENGTH_LONG).show();
}
}
Please help me, My goal is to update my database with alarm manager every 6 in the morning. It's like reseting a value so I limit the users activity for 1 day
I'll bet you forgot to register the BroadcastReceiver. You need, either, to:
registerReceiver(new AlarmReceiverActivity(), filter);
or, probably better in your case, in the Manifest
<receiver android:name="your.package.AlarmReceiverActivity">
<filter...
</receiver>
I am trying to set up an alarm that will run in the background and trigger (eventually) a save event. At the moment I simply have this code attached to a button. Press the button and the alarm should start leaving Toast messages behind as an indication that it is functioning. At the moment everything runs except the onReceive in the BroadcastReceiver is never triggered.
Here is my code:
The class setting up the alarm:
//FIXME - rename (ie BackgroundSave; more descriptive)
public class AlarmReceiver extends Service{
//FIXME - make sure you kill the service
public void onCreate() {
super.onCreate();
Toast.makeText(getApplication().getApplicationContext(), "Service onCreate called", Toast.LENGTH_SHORT).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(getApplication().getApplicationContext(), "Service started", Toast.LENGTH_SHORT).show();
setAlarm(AlarmReceiver.this);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
public void setAlarm(Context c) {
AlarmManager alarmManager = (AlarmManager)c.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(c, Alarm.class);
PendingIntent pi = PendingIntent.getBroadcast(c, 0, i, 0);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, System.currentTimeMillis() + 1000, 1000, pi);
Toast.makeText(c.getApplicationContext(), "setAlarm called", Toast.LENGTH_SHORT).show();
}
public void cancelAlarm(Context context) {
Intent intent = new Intent(context, Alarm.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
Here is the BroadcastReceiver:
public class Alarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm", Toast.LENGTH_SHORT).show();
}
}
And here is my manifest:
<!-- Alarm -->
<service android:name="com.xxxx.android.tools.AlarmReceiver" android:enabled="true" />
<receiver android:name="com.xxxx.android.tools.Alarm" ></receiver>
The alarm onReceive is never triggered.
You have to use android.os.SystemClock.elapsedRealtime() as your base time when using AlarmManager.ELAPSED_REALTIME_WAKEUP.
That said i think to use the AlarmManager for your saving purpose is not the best approach. The alarm manager is pretty heavyweight. You should consider using a simple Handler to trigger your save action.
Have a look at Handler.postAtTime().