I have a service which should be run for example every 1 minute. I used a broadcast receiver and AlarmManager to make this work. And also I call PowerManger.aquire() to make sure cpu doesn't sleep before the service starts. For first 2 or 3 days the app runs okay but after that the service doesn't get started. Sounds alarmManager doesn't start it. Any Idea why?
public class MyReceiver extends BroadcastReceiver {
PowerManager pawerManager;
public static PowerManager.WakeLock wakeLock=null;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
pawerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = pawerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wakeLock.acquire();
Intent serviceIntent=new Intent(context,MyService.class);
context.startService(serviceIntent);
}
}
And The Service:
public class MyService extends Service {
void releaseTheLock(){
if (MyReceiver.wakeLock != null){
MyReceiver.wakeLock.release();
MyReceiver.wakeLock=null;
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
final Context serviceContext=this;
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
/*
Do something
*/
//Now set the timer
long currntTime = System.currentTimeMillis();
AlarmManager mgr=(AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
Intent i= new Intent(serviceContext, MyReceiver.class);
PendingIntent pi=PendingIntent.getBroadcast(serviceContext, 0, i, 0);
mgr.set(AlarmManager.RTC_WAKEUP, currntTime + 60000 , pi);
stopSelf();
releaseTheLock();
return;
}
}).start();
return START_STICKY;
}
}
And here's the receiver registration in manifest:
<receiver android:name=".TimeReceiver"></receiver>
I suspect you're running into a race condition where the Service object (Context) is being cleaned up and destroyed, but is being used as the Context for your PendingIntent. Here are a couple of options:
Change your creation of PendingIntent to use the application context. This context is the the one in which your PendingIntent is sent. So if you use a transient context, like the Service object itself, it may no longer be valid.
Revise this to not use the BroadcastReceiver at all. You can create a PendingIntent for your Service via the PendingIntent.getService() method. Again, use your application context here rather than the Service object itself.
Have you tried with setRepeating?
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000 * 60, alarmIntent);
Related
I am calling service from the application class, If I close the app or remove from currently running apps, then the service will destroy automatically,I didn't written any code in on Destroy() method
to call service here is code :
Intent syncIntent = new Intent(this, ScanBLE_Service.class);
this.startService(syncIntent);
here is the code of service class
public class ScanBLE_Service extends IntentService {
public ScanBLE_Service() {
super(ScanBLE_Service.class.getName());
// TODO Auto-generated constructor stub
mHandler = new Handler();
}
#Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
demo();
}}
private void demo() {
mHandler.removeCallbacksAndMessages(null);
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Demoooo", Toast.LENGTH_SHORT).show();
demo();
}
}, 5000
);
}
You should use Service, not IntentService. Extend the Service class and override onStartCommand method, then do the calculations in this method
To run your service even after the application is destroyed you need to do the following.
extend your service with Service classs
return START_STICKY in onStartCommand()
override onTaskRemoved(refer the following example code).
public class MyIntentService extends Service
{
Timer mTimer;
#Override
public void onCreate()
{
super.onCreate();
mTimer = new Timer();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
mTimer.schedule(mTimerTask, 1000, 5000);
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent)
{
return null;
}
TimerTask mTimerTask = new TimerTask()
{
#Override
public void run()
{
System.out.println("timer task run");
}
};
#Override
public void onTaskRemoved(Intent rootIntent)
{
System.out.println("onTaskRemoved");
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 1000, restartServicePendingIntent);
super.onTaskRemoved(rootIntent);
}
}
Yes, the service will be closed if application is closed. One situation, when the service will not be closed in to have a constant Notification on notifications screen.
More here
The normal behavior is that the service will keep running even if the application is closed, because it's separated from the application and runs in background, unless you call stopSelf() or stopService(x,x) it should keep running..
PS: there's another type of service which is IntentService (extends IntentService rather then Service) and this will stop automatically once the code in onHandleIntent() is executed..
I have implemented an Alarm manager and receiver in my application, all is working perfectly. The issue I am having is when I press the back button to close the application, the alarm doesn't run at the time specified. Below is the code I am using:
My Receiver Code
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
System.out.println("SERVICE RECIEVED");
Intent service1 = new Intent(context, MyAlarmService.class);
context.startService(service1);
}
}
My Alarm Service Code
public class MyAlarmService extends Service {
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
}
#SuppressWarnings("static-access")
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Intent _intent = new Intent(getBaseContext(), FirstCallActivity.class);
_intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(_intent);
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
}
Start Alarm Code
public void startAlarm(Calendar cal) {
// Create a new PendingIntent and add it to the AlarmManager
Intent intent = new Intent(this, FirstCallActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 12345,
intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(Activity.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);
}
Manifest Code (within application tags)
<service
android:name=".MyAlarmService"
android:enabled="true" />
<receiver android:name=".MyReceiver" />
Could anyone explain why this is happening? I know if the application is fully closed nothing is going to happen, but I it seems strange the back button causing this issue because the application is still running in the background.
Thanks
It turns out that the app was being closed on the back button. By stopping the app closing on the back button press with the code below, the function required for the set alarm run correctly.
#Override
public void onBackPressed() {
System.out.println("BACK PRESS");
moveTaskToBack(true);
}
Here is my code for starting a service:
I am starting my service in onCreate() of my Activity.
Intent svc=new Intent(BeapSoundActivity.this, BackgroundService.class);
pendingIntent = PendingIntent.getService(BeapSoundActivity.this, 0, svc, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 2);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 10*1000, pendingIntent);
I cant able to stop a service by calling
stopService();
Here is my Service class:
public class BackgroundService extends Service{
// private static final String TAG = null;
// MediaPlayer player;
MediaPlayer mMediaPlayer;
String strResponse;
int i=0;
static {
// StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy( new StrictMode.ThreadPolicy.Builder().permitAll().build());
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
mMediaPlayer = new MediaPlayer();
Log.e("Oncreate","oncreate");
}
public int onStartCommand(Intent intent, int flags, int startId) {
// player.start();
Log.e("Onstartcommand","onstartcommand");
pendingCount();
return 1;
}
public void onStart(Intent intent, int startId) {
// TO DO
// super.onStart(intent,startId);
Log.e("Onstart","onstart");
// pendingCount();
}
public IBinder onUnBind(Intent arg0) {
// TO DO Auto-generated method
return null;
}
public void onStop() {
this.stopSelf();
}
public void onPause() {
}
#Override
public void onDestroy() {
super.onDestroy();
this.stopSelf();
// player.stop();
// player.release();
}
#Override
public void onLowMemory() {
}
}
public void pendingCount(){
my operations during the service
}
}
}
I have also tried with stopSelf() in my onDestroy(),but it also didnt worked for me.
Please suggest how can I solve this issue?
you've to call stopService() from another activity. Or you can call stopSelf() in the service (not in onDestroy()) when the required work finishes.
What I can see that your stopservice() is working fine to stop the service but anonymous class or what ever you are using inside pendingCount() is still working even though service is destroyed..
So do some thing like this
Rise a flag in ondestroy() and check this inside pendingCount() looping part and if this flag is high destroy this task also. For more accurate answer add complete pendingCount()
code
You can check my answer that I have posted previously and try to implement that. Hope it works for you.
Try using this code it may help you.
stopService(new Intent(MainActivity.this,BackgroundService.class));
I am having a problem getting my pendingIntent to fire. I have done some troubleshooting using the logcat etc. and in the end I am almost positive that my problem is actually in my pendingIntent method. The times I have set are correct, and the method is getting called, but nothing happens at the scheduled times.
Here is the method that I use to create the pendingIntent
public void scheduleAlarm(){
Log.d("Alarm scheduler","Alarm is being scheduled");
Intent changeVol = new Intent();
changeVol.setClass(this, VolumeService.class);
PendingIntent sender = PendingIntent.getService(this, 0, changeVol, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, time, sender);
//Toast.makeText(this, "Volume Adjusted!", Toast.LENGTH_LONG).show();
}
Here is the service class:
public class VolumeService extends Service{
#Override
public void onCreate() {
super.onCreate();
Log.d("Service", "Service has been called.");
Toast.makeText(getApplicationContext(), "Service Called!", Toast.LENGTH_LONG).show();
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
The log in the scheduleAlarm() class is working as I planned but then nothing happens, so I assume it is my pendingIntent.
Thanks in advance!
Figured it out! The problem was in the Service class, I changed a few other things around too.
However, I believe the main problem was that in my service class in the onCreate method I was trying to run my code. But this needed to be done in the onStartCommand method
public class VolumeService extends Service{
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(getApplicationContext(), "Service started", Toast.LENGTH_LONG).show();
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
and a few changes were made in the class starting the service as seen here:
public void scheduleAlarm(){
Log.d("Alarm scheduler","Alarm is being scheduled");
Intent intent = new Intent(AlarmSettings.this, VolumeService.class);
PendingIntent pintent = PendingIntent.getService(AlarmSettings.this, 0, intent, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.set(AlarmManager.RTC_WAKEUP, time, pintent);
}
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().