I am using intent service to periodically send queries to my server to check if there are any updates. In the intent service there is a timer task, which queries the server every 3 seconds, This starts running when the application is closed.
Now when the user again comes back in to the application I want to stop the service.
How should I do this? how can an intent service which is doing timertask be stopped form another activity?
Please give suggestions for Intent Service because that is what I am using.
Maybe it will be better to use just service instead of IntentService.
public class UpdateService extends Service {
public class LocalBinder extends Binder {
public void startUpdates() {
// start updateThread if it not started, or
// notify about resuming probes
}
public void stopUpdates() {
// make updateThread to wait, until startUpdates
// called again.
//
// REMEMBER this method can be called when startUpdates didnt called.
}
}
// For simplicity we will use local binder.
private final IBinder binder = new LocalBinder();
#Override
public IBinder onBind(Intent intent) {
return binder;
}
private Thread updateThread = new Thread() {
#Override
public void run() {
while (true) {
// Do updates. Sleep/awake managment.
}
}
};
}
Just bind to service (with AUTO_CREATE_FLAG) and start updates when you are need.
When your activity shows just bind again to service and make it stop updates.
First of all,IntentService cannot be stopped.It will stop itself only after it has completed all the tasks present in its queue.Hence,IntentService should not be used here.
Related
I have a class for using FusedLocationApi to send the location of user frequently to the server. All methods for getting location updates and communicating with server are set in this class except that when I want to run this class, I call a background service and then use this class inside it.
Uisng FusedLocationApi.requestLocationUpdates , the location is being sent to the server properly and I can see Toasts from this service. But when I check the Running services on android system, my application is not listed there.
My question is that why my service is not running anymore but the location is being updated? Is the FusedLocation Service is a background service itself? Do I need to call it frequently through a background service to keep it alive or I can call it inside the activity and let it continue running even after closing the app?
this is how I use the class inside my own service:
public class LocationService extends Service {
FusedClass mylocation=new FusedClass(this);
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals("turnOn")) {
HandlerThread handlerThread = new HandlerThread("LocationThread");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable() {
#Override
public void run() {
mylocation.LocationStartPoint();
}
});
}
if (intent.getAction().equals("turnOff")) {
stopSelf();
}
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
//TODO for communication return IBinder implementation
return null;
}
EDIT: I use FusedLocationApi.requestLocationUpdates and onLocationChanged to get location updates from this API.
I am having problem with my android IntentService. When I first open the application, the service gets started by intent from the profile activity and data is fetched from this service. If I switch to other activity and then back service is still running and that is ok.
However if you press back, so that activity is finished and put in the background, the service is still working as the application is in background but If I get it back to foreground service stops. I do not know why. Bellow is my code, please help.
I have read activity life cycle couple of times and still do not get it why this is happening.
What is weird is that Service receive data one more time before it stops when MainActivity is brought back to running state. Service is not crashing.
Service
public class SomeService extends IntentService
{
public static final String extra = "someData";
public SomeService()
{
super(SomeService.class.getSimpleName());
}
#Override
protected void onHandleIntent(Intent intent)
{
Log.e("SomeService", "starting service");
while (true)
{
SomeData data = Api.getNewSocketData();
//Broadcast data when received to update the view
Intent broadcastData = new Intent();
broadcastData.setAction(dataBroadcastReceiver.ACTION_DATA_RECEIVED);
broadcastData.addCategory(Intent.CATEGORY_DEFAULT);
broadcastData.putExtra(extra, " ");
sendBroadcast(broadcastData);
Log.e("SomeService", "received from socket");
}
}
}
Receiver
public class dataBroadcastReceiver extends BroadcastReceiver
{
public final static String ACTION_DATA_RECEIVED = "net.bitstamp.intent.action.ACTION_SOMEDATA_RECEIVED";
#Override
public void onReceive(Context context, Intent intent)
{
Log.e("receiver", "data received");
}
}
Main Activity
#Override
public void onPause()
{
super.onPause();
unregisterReceiver(dataBroadcastReceiver);
}
#Override
public void onResume()
{
super.onResume();
IntentFilter intentFilter = new IntentFilter(dataBroadcastReceiver.ACTION_DATA_RECEIVED);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
dataBroadcastReceiver = new dataBroadcastReceiver();
registerReceiver(dataBroadcastReceiver, intentFilter);
Intent someService = new Intent(this, SomeService.class);
startService(someService);
}
I really need help on this. Thanks
You don't want to the up the IntentService in an infinite loop. It will block all other incoming requests. From the documentation:
All requests are handled on a single worker thread -- they may take as long as necessary (and will not block the application's main loop), but only one request will be processed at a time.
Your Service is likely still happily running along, it just isn't processing your new request because your old one is still being handled in the infinite loop.
The app has a service which has to detect how many minutes the app is running and based on that, the service will initiate misc actions.
What is the proper way to implement this?
How can I be sure the service is running ONLY when the app is running in front of the user?
Starting the service seems easy - just start it on splash loading. But the harder part is ending it. I cannot just end it when the user press Back button on the last screen. How to handle situation when a user presses Home screen or some other other app (like phone call, or viber popup, or...) takes over the screen?
I tried taking suggestions from the other theme (How to start a android service from one activity and stop service in another activity?), but this does not handle the situation with Home button or other app taking over the screen.
The app has in total around 10 activities. Is it a proper way to bind this service to all 10 activities and when all are off, the service then turn itself off?
Make a BaseActivity for all of your Activities. In the BaseActivity, do the following:
public class MyActivity extends Activity implements ServiceConnection {
//you may add #override, it's optional
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, MyService.class);
bindService(intent, this, 0);
}
//you may add #override, it's optional
protected void onStop() {
super.onStop();
unbindService(this);
}
public void onServiceConnected(ComponentName name, IBinder binder) {};
public void onServiceDisconnected(ComponentName name) {};
/* lots of other stuff ... */
}
Your BaseActivity will need to implement ServiceConnection interface (or you can use an anonymous inner class), but you can leave those methods empty.
In your Service class, you need to implement the onBind(Intent) method and return an IBinder. The easiest way to do that is like so:
public class MyService extends Service {
private final IBinder localBinder = new LocalBinder();
public void onCreate() {
super.onCreate();
// first time the service is bound, it will be created
// you can start up your timed-operations here
}
public IBinder onBind(Intent intent) {
return localBinder;
}
public void onUnbind(Intent intent) {
// called when the last Activity is unbound from this service
// stop your timed operations here
}
public class LocalBinder extends Binder {
MyService getService() {
return MyService.this;
}
}
}
Bound Service is define specifically for this purpose, you can bind Activities to it, and when all the Activities are gone, it will be stopped as well. The link should contain enough detail for you to implement.
In the application that I am developing there is a bound service, that uses TCP socket connection. The requirement for the service is to keep the socket connection for a while after last Activity bound to the service is shut down, say for 1 minute. This is to avoid unneeded socket reconnections when another activity connects to the service just after one has unbound from it.
I have searched and found similar issue ( Service, Rebind or not bound at all? ) suggesting using started service, but current application architecture uses bound connections, and I would not like to redesign if it is not needed. Hence I am looking for other options.
My question is, can I somehow postpone bound service destruction or the only good approach is to rewrite the communication to the service using intents, thus converting it to started service?
public class SocketService extends Service {
private static final String LOG_TAG = SocketService.class.getSimpleName();
#Override
public final IBinder onBind(final Intent intent) {
Log.d(LOG_TAG, "onBind()");
return new LocalBinder<SocketService>(this);
}
#Override
public boolean onUnbind(Intent intent) {
Log.d(LOG_TAG, "onUnbind");
return super.onUnbind(intent);
}
#Override
public void onCreate() {
Log.d(LOG_TAG, "onCreate");
// create socket connection here
// ...
//
super.onCreate();
}
#Override
public void onDestroy() {
Log.d(LOG_TAG, "onDestroy");
// close socket connection
// ...
//
super.onDestroy();
}
// Other socket sending and receiving logic
// ...
//
}
Thanks in advance for you time.
Keep the First Activity you launch bound to the service , don't destroy it when you launch another one .
When you want to exit the application from your current activity send a signal to the service which will notify all activities to close .
OnCreate is only called on the first bind to the service (when the service doesn't exist ) , the bind that follows should not trigger the onCreate function .
I'm developing an android application which creates an android service which refresh the location of the mobile device using gps. It works with a timer that in 'x' time, it refresh the position.
The problem is that I would like to comunicate with that local android service from one activity of the application, because I would like to change the refresh time ('x') when I want. So, How do I can do it?
One possible solution is to stop the service and then start again every time the time refresh is changed, but I think it is not the optimal solution.
Any suggerence, help, pls?
If you are within the same Process-Space (Same Application/.apk) you can just establish a simple Service Connection
In your activity, include something like the following:
private ServiceConnection _svcConnection = new ServiceConnection() {
#Override
public void onServiceDisconnected(ComponentName arg0) {
_myService = null;
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
_myService = ((MyService.LocalBinder) service).getService();
if(!_myService.IsRunning())
_myService.Start();
}
};
#Override
protected void onResume() {
bindService(new Intent(Main.this, MyService.class), _svcConnection
BIND_AUTO_CREATE);
startService(new Intent(Main.this, MyService.class));
super.onResume();
}
#Override
protected void onPause() {
unbindService(_svcConnection);
super.onPause();
}
Your Service needs a binder:
private final IBinder _Binder = new LocalBinder();
#Override
public IBinder onBind(Intent arg0) {
return _Binder;
}
/**
* Class for clients to access. Because we know this service always runs in
* the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
public MyService getService() {
return MyService.this;
}
}
Then you can work with the _MyService object and call any Method on it. (E. g. Registering a Callback or request Location Updates), but be aware that if the service connection fails, the _MyService variable will be null!
_MyService.SetInterval(4);
If you need to access this service from another Application (Another Process), you have to deal with IPC.
It will help you, You do this in service, it will refresh your location in this method
Timer timer = new Timer("Refresh Time");
timer.schedule(RefreshTask, 1000L, 60 * 1000L);
private TimerTask refreshTask = new TimerTask() {
#Override
public void run() {
Log.i(TAG, "Update time here");
}
};