I have a countdown timer, that starts when user Logged In. After 10 Minutes it Logged Out User.
It works fine, but if user stops application, then timer stops working, and user is logged in forever.
So i put this whole thing in a service, so that it will work, either user stops application or not.
The problem is that, this has stopped working after adding Countdown Timer in Service. I have checked it on debug mode, and its not going into the service- onCreate method.
This is how i am calling the service.
startService(new Intent(this,LogoutService.class));
My Service Class, calls the CountdownTimer Class, first this code was written in the place where i write startService() now
public class LogoutService extends Service {
#Override
public void onCreate() {
UserLoggedInTimer logoutTimer= new UserLoggedInTimer(60000,1000);
logoutTimer.setContext(getApplicationContext());
logoutTimer.start();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
The countdown timer works perfectly fine when i call it without service, but here its just not getting into the service, i hope it will work fine, once my application starts the above service successfully.
put it in onStartCommand() and make it return START_STICKY
refer to this
Related
I have an Android application that has a button that starts the service.
Here is the service:
public class SimpleService extends Service
{
#Override
public int onStartCommand(Intent intent,int flags, int startId)
{
Toast.makeText(this,"Service Started",Toast.LENGTH_SHORT).show();
Integer i=0;
while (i<10)
{
Log.d("Hi",i.toString());
SystemClock.sleep(5000);
i++;
}
Log.d("Hi","return START_STICKY");
return START_STICKY;
}
public void onDestroy()
{
super.onDestroy();
Toast.makeText(this,"Service Stopped",Toast.LENGTH_SHORT).show();
}
}
When I clicked on the button, the service starts successfully, but after some while, in the emulator, I got an error like
Application is not responding. Would you like to close it?
Am I doing anything wrong in service implementation?
What I want to do is perform a task on every 5 seconds even if my application got killed.
I tried with IntentService but it got killed when my app got killed so my task remains incomplete.
while (i<10)
{
Log.d("Hi",i.toString());
SystemClock.sleep(5000);
i++;
}
I would like to point out this part of your code. Here what you are doing is once your service starts, you are doing 10 iterations of loop and in each iteration you are pausing execution for five seconds (which is a lot of time in terms of execution). As services run in the main process, in my opinion, they block the main thread, which means during the sleep, if your app is accessed, you will get the ANR (App not responding) error. Thus, these types of tasks should be run in a separate thread.
If you want to perform some repetitive tasks on the background, I'd suggest you make use of a AlarmManager component of the Android SDK.Alarm manager is a system service, thus you can access it by using the following line of code.
AlarmManager mAlarmMgr=(AlarmManager) getSystemService(Context.ALARM_SERVICE);
//Then you can set alarm using mAlarmMgr.set().
You will then receive the alarm in a AlarmReceiver.
AlarmReciever class extends BroadcastReceiver and overrides onRecieve() method. inside onReceive() you can start an activity or service depending on your need like you can start an activity to vibrate phone or to ring the phone.
I hope this helps. Cheers!
Since By Default, all your app components (like Activity, Service etc) runs in Main/UI Thread, and if it get blocked, Android shows ANR dialog.
Also, Each of lifecycle method of service is called from UI thread. If you need background task to be running all the time, you can crate new thread for this.
You may try below code inside your Service class:
new Thread(new Runnable(){
public void run() {
while(i<10)
{
Thread.sleep(5000)
//REST OF CODE HERE//
}
}
}).start();
I have an application, where I have put a connection to e certain service in a custom Application class, so that all activities can access it, but I need to close the service once my application is closed.
I want to send the bundled data just one time, not every time a single activity hits onPause/Destroy().
I also figured onTerminate() in the Application class is not always invoked.
Is there a better way to do this?
If you are targeting API level 14 or above you can use the registerActivityLifecycleCallbacks to register a listener and count the launches/stops in onActivityResumed and onActivityStopped. When the counter is 0 then you know there is no more activity in the stack and you can close your service
unfortunately, there is no callback / method to detect when your application process has stopped, or going to be stopped. #Alex suggestion to listen to the Activity lifecycle callbacks can be more tricky then it seems.
but if you want to detect this only for purposes of stopping running Service , then this problem is not relevant, because if your process stooped, then all running services it owns is also stopped anyway!!
if you meant that you want to stop the service when the application is not in foreground (completely different thing..) then the solutions is different:
if you'll always use bindService() instead of startService() within the onResume activity callback, and in the onPause() stop it, then when your app would enter background - the service will be stopped automatically.
another option would be to use the Service callbacks to detect if currently there is bounded activity:
#Override
public IBinder onBind(Intent intent) {
mBoundedToActivity = true;
return mBinder;
}
#Override
public void onRebind(Intent intent) {
mBoundedToActivity = true;
super.onRebind(intent);
}
#Override
public boolean onUnbind(Intent intent) {
mBoundedToActivity = false;
return super.onUnbind(intent);
}
My app has a background Service. In the Service I need to detect and log all app launches. For example: whether the user opens Facebook or Google+ or Twitter (any app) - I want a receiver in my Service to catch it for me to perform an action.
The only way I have been able to come up to do this - is to have a Timer running in the onCreate() function of my Service. My concern is that this 1 second timer may drain battery.
Is that assumption correct?
If yes, is there another way (some intent filter?) that I can register with my Broadcast Receiver to catch any App Launch?
Things I have tried:
(1) My Service code with the TimerTask. My trigger action code will be placed inside the "run()" function of the TimerTask.
public class KillService extends Service {
ActivityManager mActivityManager;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
Timer timer = new Timer();
TimerTask refresher = new TimerTask() {
public void run() {
//PLACING MY TRIGGER ACTION HERE
};
};
//TIMER RUNS EVERY 1 SECOND
timer.scheduleAtFixedRate(refresher, 1000,1000);
}
}
(2) Reviewed Available Broadcast Actions
I reviewed the broadcast_actions.txt that comes in the SDK Folder (sdk\platforms\android-19\data), but I did not find any Intent that will be appropriate for this use case.
Link to file
All I want is to know when any App Activity is started (i.e. in the Foreground) so that I dont have to continually check with Timer (afraid that it may drain battery)
Perhaps my answer in this question might help you. Android how to know an app has been started and range apps priority according the starting times
Place that code inside your background service.
Based on the package name of the activity in the foreground, you can detect that app name by checking all the apps on the phone and matching it with the app that has the same package name.
Edit
Since you want a continuous check, you could use an AsyncTask(), and in the doInBackground() function, just keep getting the list of running activities in each iteration, like I have suggested in that link, and the first item in the taskInfo list will have the activity/app in the foreground. You can also provide another button in your app which on click you stop this , by keeping a bool variable in shared preferences (which you poll for in the while condition in doInBackGround() function of the AsyncTask()).
I have done something similar in the past, and it worked for me.
I have a widget that, when pressed, sends a broadcast that starts a CountDownTimer that updates my widget, and at the end plays an alarm. This works beautifully in the emulator.
On my phone, however, it's a different story. My phone is so resource constrained that my process is killed regularly, which, of course, means that the CountDownTimer no longer updates my widget.
It seems to be that the only way to reliably do stuff in the future is to use the AlarmManager, as this sets a system-level alarm. However, the documentation states, and I agree, that you're not supposed to use it for ticks. However, since anything else you're likely to use has the possibility of being shut down arbitrarily, they're not really giving us much choice.
My question is: is there a way to ensure that a CountDownTimer keeps ticking and finally calls onFinish(), or do I have to simply drop it and switch to AlarmManager, and "misuse" it? Any other options of guaranteeing that the thing ticks and finishes are also welcome.
I should add that I can't rely on the OS calling onUpdate(), both because it will do so no faster than every 30 minutes, and also because most of the time the widget just does nothing. It's only when it is clicked that it ticks down every second for a handful of minutes.
I think this is a solution.. Create a dummy service..
public class DummyService extends Service{
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
and start it from your activity using countdowntimer like this.. in oncreate of the activity
Intent intent = new Intent(this, DummyService.class);
startService(intent);
and also dont forget to declare this service in your manifest like this..
<service android:name=".DummyService" >
</service>
hope this helps..
What I ended up doing was moving from a BroadcastReceiver to a Service.
Not just using a dummy service, but having a real service embody what the BroadcastReceiver did previously.
As this won't guarantee that my timers won't get killed, if requested, android will automatically try to restart your service after it's been killed. In this event, I plan to have some code that will restore the running state from disk and continue.
To add to the accepted answer: from what I remember, the BroadcastReceiver only lives as long as it takes to process the broadcast.
So launching a timer or something from within the BroadcastReceiver will not work (as stated).
This is why it is recommended to use the BroadcastReceiver to launch a Service that will do the timing. Sure, the service can still be killed, but not as early as the BroadcastReceiver.
I'm facing a problem trying to fetch data by the background service started at the device boot time. When run from the dedicated application, it retrieves the data just fine, but when run separately, it starts correctly but returns nothing. It doesn't rely on any other classes, it uses only its own methods.
Is it possible at all to execute http requests from a background service started in that way?
BackgroundService.java fragment:
public class BackgroundService extends Service {
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
new BackgroundTask(this).run();
}
The BackgroundTask class does all his job in its run() method containing the code for http requests which works fine if the service is run from the application. Do I have to do something about onBind method?
You should call startService() from you BOOT_COMPLETED broadcast receiver. Your Service will be considered active until it calls stopSelfResult() or stopSelf(), or somebody calls stopService() on your service. And while service is active it can run any web-request it needs (this should be done in separate thread of course).
You should refer to "Creating a Started Service" section in Android Documentation for more details.