I have an ImageView in my activity that shows an "active" symbol when a service is activated.
After the Service has been executed the ImageView should go back to the "inactive" Symbol.
AlarManager that starts Service:
context = this;
Intent intent = new Intent(context, AlarmReceiver.class);
sender = PendingIntent.getBroadcast(context, INTENT_CODE, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, calNew.getTimeInMillis(), sender);
setImage(active);
AlarmManager:
#Override
public void onReceive(Context context, Intent intent) {
Intent wakeupIntent = new Intent(context, WakeupActivity.class);
context.startService(wakeupIntent);
}
How can I make the Image change back to inactive after the service has been executed? I tried to create a new Runnable and then postDelayed(runnable, calNew.getTimeInMillis()) using a handler. Actually it didn't work, nothing happened. Is there a better way to do this?
How can I make the Image change back to inactive after the service has been executed?
Step #1: Add the Android Support package to your application.
Step #2: Have your activity register a BroadcastReceiver with LocalBroadcastManager in onResume() and unregister it in onPause().
Step #3: Have your service send a broadcast via LocalBroadcastManager when its work is complete, to be picked up by the activity's BroadcastReceiver.
Here is a sample project demonstrating this technique.
Related
First of all I wanted to give codes here but the codes are way to long, it can be found here
http://www.c-sharpcorner.com/article/creating-and-scheduling-alarms-in-android/
The codes in the article doesn't create service.
As per my understanding, BroadcastReceiver is used to serve an activity based on its corresponding Service ( via an intent ).
Normally we would declare such :
Intent serviceIntent = new Intent(MainActivity.this, CustomeService.class);
startService(serviceIntent);
registerReceiver(mReceiver, mIntentFilter);
where mReceiver will be something like :
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
}
}
But there's something confusing me in AlarmManager class in the example that I shared by the link :
intent = new Intent(this, MyBroadcastReceiver.class);
pendingIntent = PendingIntent.getBroadcast(
this.getApplicationContext(), 280192, intent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis() + (i * 1000), 10000
, pendingIntent);
The line that is confusing me is this :
intent = new Intent(this, MyBroadcastReceiver.class);
the type of this MyBroadcastReceiver.class is BroadcastReceiver itself, and not Service.
So where's the Service that this MyBroadcastReceiver.class received broadcast from then?
Does BroadcastReceiver somehow create its own service?
the type of this MyBroadcastReceiver.class is BroadcastReceiver itself, and not Service
Correct. It is being used with PendingIntent.getBroadcast(), notgetService()`.
So where's the Service that this MyBroadcastReceiver.class received broadcast from then?
Few broadcasts are sent by some Service, though that is certainly possible. In this case, the broadcast is being sent from a system process, as part of sending the PendingIntent, when the alarm time comes around.
Does BroadcastReceiver somehow create its own service?
I am not sure what you mean by "create" here. A BroadcastReceiver may delegate its work to a Service. That is a common pattern with AlarmManager: have the alarms trigger a WakefulBroadcastReceiver, which in turn delegates work to an IntentService. In that case, the reason for the indirection stems from the way that AlarmManager works with WakeLocks.
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
In my App I use an AlarmManager to start an Activty at a certain days of the week and at a certain hour.
So I have an AlarmManager that an MON, TUE, WED.. at 12:00 fires off an Activity...
Now, the point is that I need to stop the same activity at a precise time (again using the AlarmManager if it is possible).
Please how do I achieve that: AlarmManager to STOP an Activity?
you can register a broadcastReceiver in that activity. if you wanna stop it, send a broadcast notification to that Activity, and trigger relevant callback function to finish the activity.
As Pankaj said use services and u can unregister the broadcast reciever
public void stopService() {
Log.d("TAG", "CancelAlarm Start");
Intent intent = new Intent(context, PullNotification.class);
PendingIntent sender = PendingIntent
.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
In Android to kill an activity, you just use finish(). But in my case I want to kill the activity when the PendingIntent is fired.
My code is as follow:
Intent intent = new Intent(MainActivity.this, NextActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Utils.KEY_RECORD_TIME, recordLength);
PendingIntent pintent = PendingIntent.getActivity(MainActivity.this,
piNumber, intent, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pintent);
If I add finish() beneath, the activity will be killed before the time set up in the AlarmManager.
I want the activity to be visible until the time goes off and kill it. Are there any ways to do this? I did some searches in Stack Overflow, Google but could not find an answer.
Inside a timer you get the time delay of the pending intent.
new Timer().schedule(new TimerTask() {
#Override
public void run() {
// TODO Auto-generated method stub
}
},pending intent delay);
Please try this.It work for me
You can register a BroadcastReceiver dynamically in your activity. With the pending intent, you use getBroadcast(). So you can call finish() inside the broadcast receiver when it is invoked by the alarm manager. Note that you must unregister the receiver when you don't need it anymore, you do that in onDestroy() for example.
Look at onNewIntent(Intent). If you can start your activity as a single top, then your instance should receive the pending intent through that call.
If you can't use singel top, and a new instance of your activity is being launched, you could use a shared static to get the original instance in onCreate() of the new one and finish() both.
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.