Multiple Services on Multiple Threads Lifecycle - android

These methods are implemented in a class extending Service. A new service is started every time a button is pressed.
If the button is pressed once, LogCat outputs what I expect, which includes a final output of "Service onDestroy." However, when the button is pressed twice, the second time before the first service ended, "Service onDestroy." displays only once when the first service is done, and the second service prints out the rest of "Service Running" logs but not "Service onDestroy."
Can anyone tell me why? Thank you!
public int onStartCommand(Intent intent,int flags, int startId) {
Log.i(TAG,"Service onStartCommand " + startId);
final int currentId = startId;
Runnable r = new Runnable() {
public void run() {
for (int i = 0; i < 3; i++) {
long endTime = System.currentTimeMillis() + 10*1000;
while (System.currentTimeMillis() < endTime) {
synchronized(this) {
try {
wait(endTime - System.currentTimeMillis());
}catch (Exception e) {
}
}
}
Log.i(TAG,"Service running");
}
stopSelf();
}
};
Thread t = new Thread(r);
t.start();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.i(TAG,"Service onBind");
return null;
}
#Override
public void onDestroy() {
Log.i(TAG,"Service onDestroy");
}

In the guide for Services they use don't use stopSelf() but stopSelf(startId) when extending Service. The first stopSelf() propably stops both executions of your Service.
See here: http://developer.android.com/guide/components/services.html
Edit: Also a service is only created and destroyed once even when there are several executions of it running it is still a single service. In your case (a Bound Service) it will only be destroyed when the last excecution finishes. For logging every excecution ending you could try to override the stopSelf(int startId) method.

Related

Not able to run service indefinitley in background

I am working on below code to run a service in background,but the problem is i am not getting how to run the service indefinitely even though the app is closed,here on press of back my service is stopping.I have read many tutorials but still confused with this.
public class HelloService extends Service {
private static final String TAG = "HelloService";
private boolean isRunning = false;
#Override
public void onCreate() {
Log.i(TAG, "Service onCreate");
isRunning = true;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service onStartCommand");
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
if (isRunning) {
Log.i(TAG, "Service running");
}
}
//Stop service once it finishes its task
stopSelf();
}
}).start();
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
Log.i(TAG, "Service onBind");
return null;
}
#Override
public void onDestroy() {
isRunning = false;
Log.i(TAG, "Service onDestroy");
}
}
On Android there is NO way (at least for a third party app) to have a never ending process running. The system can always kill your service. So you can use a foreground service but the system can kill your service even in this case (even with low probability). In addition, you should consider that the cpu can go to sleep. So you should take a wakelock but in this way you can kill the user battery so it's not a good solution. My suggestion is to always work "on event" for example with a brodacast receiver that starts a intent service, it does some work and then exit. The always running processes are simply a wrong design choices on Android.
One Way is to use while loop but keep a check i.e
while(true) {
if (condition != true) {
Thread.sleep(time);
} else {
break;
}
}

service in infinite loop android

I want to call a service which repeatedly queries a Parse.com database and monitors a specific attribute.Here's what Ive got so far:
public class Battle extends Service {
#Override
public int onStartCommand(Intent intent,int flags,int startId)
{
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
ParseUser currentUser = ParseUser.getCurrentUser();
username = currentUser.getString("username");
findinBackground();
return START_STICKY;
}
private void findinBackground(){
//public void run() {
// TODO Auto-generated method stub
while(true)
{
query = ParseUser.getQuery();
query.whereEqualTo("isAttacking", username);
query.findInBackground(new FindCallback<ParseUser>() {
public void done(List<ParseUser> objects, ParseException e) {
if ((e == null)&(objects.size() != 0))
{
// The query was successful.
ParseUser attacker = objects.get(0);
String attackerName = attacker.getUsername();
Log.i("ambustest",attackerName);
makeToast(attackerName);
}
else
{
Log.i("fd","Something went wrong.");
}
}
});
}
}
}
This code compiles fine but stops responding at runtime.Here's my logcat:
You need to call the service on a separate thread
#Override
public int onStartCommand(Intent intent,int flags,int startId)
{
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
ParseUser currentUser = ParseUser.getCurrentUser();
username = currentUser.getString("username");
new Thread()
{
public void run() {
findinBackground();
}
}.start();
return START_STICKY;
}
It should be noted that Intent Service is automatically called on a separate thread, however a regular service is not.
Services are run on the same thread as your UI. If you want to do time consuming operations, you need to fire them off in a separate thread.
The best solution is a Remote Service with a Handler that reports your client(s) (Activity) about changes.
http://developer.android.com/reference/android/app/Service.html
Your Service will run in a seperate process
First you need a AIDL - as an interface to communicate with service and client
// IRemoteService.aidl
package de.contecon.android.util.abstractservice;
interface IRemoteService {
void registerCallback(IRemoteServiceCallback mCallback);
void unregisterCallback(IRemoteServiceCallback mCallback);
}
Your Service can look like this
//RemoteService.java
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY_COMPATIBILITY;
}
#Override
public void onCreate() {
// While this service is running, it will continually increment a
// number. Send the first message that is used to perform the
// increment.
mHandler.sendEmptyMessage(REPORT_MSG);
}
#Override
public IBinder onBind(Intent intent) {
// Select the interface to return. If your service only implements
// a single interface, you can just return it here without checking
// the Intent.
if (IRemoteService.class.getName().equals(intent.getAction())) {
return mBinder;
}
//Example for a second Binder
// if (IRemoteServiceSecondary.class.getName().equals(intent.getAction())) {
// return mBinderSec;
// }
return null;
}
private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
#Override
public void registerCallback(IRemoteServiceCallback mCallback) throws RemoteException {
if (mCallback != null) mCallbacks.register(mCallback);
}
#Override
public void unregisterCallback(IRemoteServiceCallback mCallback) throws RemoteException {
if (mCallback != null) mCallbacks.unregister(mCallback);
}
};
/**
* Our Handler used to execute operations on the main thread. This is used
* to schedule increments of our value.
*/
private final Handler mHandler = new Handler() {
#Override public void handleMessage(Message msg) {
switch (msg.what) {
// It is time to bump the value!
case REPORT_MSG: {
// Up it goes.
int value = ++mValue;
// Broadcast to all clients the new value.
final int N = mCallbacks.beginBroadcast();
for (int i=0; i<N; i++) {
try {
mCallbacks.getBroadcastItem(i).valueChanged(value);
} catch (RemoteException e) {
// The RemoteCallbackList will take care of removing
// the dead object for us.
}
}
mCallbacks.finishBroadcast();
// Repeat every 1 second.
sendMessageDelayed(obtainMessage(REPORT_MSG), 1*1000);
} break;
default:
super.handleMessage(msg);
}
}
};
And your Client
/**
* This implementation is used to receive callbacks from the remote
* service.
*/
private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() {
/**
* This is called by the remote service regularly to tell us about
* new values. Note that IPC calls are dispatched through a thread
* pool running in each process, so the code executing here will
* NOT be running in our main thread like most other things -- so,
* to update the UI, we need to use a Handler to hop over there.
*/
public void valueChanged(int value) {
mHandler.sendMessage(mHandler.obtainMessage(BUMP_MSG, value, 0));
}
};
private static final int BUMP_MSG = 1;
private Handler mHandler = new Handler() {
#Override public void handleMessage(Message msg) {
switch (msg.what) {
case BUMP_MSG:
mCallbackText.setText("Received from service: " + msg.arg1);
break;
default:
super.handleMessage(msg);
}
}
};
public void startService() {
// Make sure the service is started. It will continue running
// until someone calls stopService().
// We use an action code here, instead of explictly supplying
// the component name, so that other packages can replace
// the service.
startService(new Intent(
"your.action.uri.code.REMOTE_SERVICE"));
}
public void stopService() {
// Cancel a previous call to startService(). Note that the
// service will not actually stop at this point if there are
// still bound clients.
stopService(new Intent(
"your.action.uri.code.REMOTE_SERVICE"));
}
/**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. We are communicating with our
// service through an IDL interface, so get a client-side
// representation of that from the raw service object.
mService = IRemoteService.Stub.asInterface(service);
mCallbackText.setText("Attached.");
// We want to monitor the service for as long as we are
// connected to it.
try {
mService.registerCallback(mCallback);
} catch (RemoteException e) {
// In this case the service has crashed before we could even
// do anything with it; we can count on soon being
// disconnected (and then reconnected if it can be restarted)
// so there is no need to do anything here.
}
// As part of the sample, tell the user what happened.
Toast.makeText(RemoteServiceBinding.this, "service connected",
Toast.LENGTH_SHORT).show();
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
mCallbackText.setText("Disconnected.");
// As part of the sample, tell the user what happened.
Toast.makeText(RemoteServiceBinding.this,"service disconnected",
Toast.LENGTH_SHORT).show();
}
};
private void bindService(){
// Establish a couple connections with the service, binding
// by interface names. This allows other applications to be
// installed that replace the remote service by implementing
// the same interface.
bindService(new Intent(IRemoteService.class.getName()),
mConnection, Context.BIND_AUTO_CREATE);
bindService(new Intent(IRemoteServiceSecondary.class.getName()),
mSecondaryConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
mCallbackText.setText("RemoteServiceBinding.");
}
private void unbindService(){
if (mIsBound) {
// If we have received the service, and hence registered with
// it, then now is the time to unregister.
if (mService != null) {
try {
mService.unregisterCallback(mCallback);
} catch (RemoteException e) {
// There is nothing special we need to do if the service
// has crashed.
}
}
// Detach our existing connection.
unbindService(mConnection);
unbindService(mSecondaryConnection);
mIsBound = false;
mCallbackText.setText("Unbinding.");
}
}
AndroidManifest.xml
<service
android:name=".service.RemoteService"
android:process=":remote"
android:enabled="true" >
<intent-filter>
<!-- These are the interfaces supported by the service, which
you can bind to. -->
<action android:name="de.your.path.util.abstractservice.IRemoteService" />
<!-- This is an action code you can use to select the service
without explicitly supplying the implementation class. -->
<action android:name="your.action.uri.code.REMOTE_SERVICE" />
</intent-filter>
</service>

How to obtain information from onHandleIntent (Android)

I´m working on my IntentService, in which I generate values in a loop. In overriden methods onStartCommand() and onDestroy(), there is possible to display a message using Toast. I would like to use Toast also in onHandleIntent(), but it´s not working. I know there are better ways (files, attributes etc.) to display values, but I need these values immediately, when they are created. Not in the end (only for control, if it´s working properly). Please, can you help me identify the problem? Thanks in advance.
public class HelloIntentService extends IntentService {
public HelloIntentService() {
super("HelloIntentService");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
#Override
protected void onHandleIntent(Intent intent) {
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}}
#Override
public void onDestroy()
{
Toast.makeText(this, "Service is being destroyed now.", Toast.LENGTH_SHORT).show();
}
}
onHandleIntent runs on a separate thread in the background per the source code and therefore does not have any ability to update the UI. I would suggest using logging statements, rather than Toasts to display your information:
Log.d("HelloIntentService","service starting");

Keep Service running

Can anyone tell me the way to keep a Service always running or restarting itself when the user close it? I've watched that facebook services restart when i clear memory.
I don't want to make ForegroundServices.
You should create a sticky service. Read more about it here.
You can do this by returning START_STICKY in onStartCommand.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
Read also about application:persistent which is "Whether or not the application should remain running at all times". This is more troublesome - System will try not to kill your app which will effect others in the system, you should be careful using it.
I copied this from a service I used in an app I did before.
ITS IMPORTANT TO NOT UPDATE ANY UI. because you have no user interface in services. this applies to Toasts as well.
good luck
public class nasserservice extends Service {
private static long UPDATE_INTERVAL = 1*5*1000; //default
private static Timer timer = new Timer();
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
super.onCreate();
_startService();
}
private void _startService()
{
timer.scheduleAtFixedRate(
new TimerTask() {
public void run() {
doServiceWork();
}
}, 1000,UPDATE_INTERVAL);
Log.i(getClass().getSimpleName(), "FileScannerService Timer started....");
}
private void doServiceWork()
{
//do something wotever you want
//like reading file or getting data from network
try {
}
catch (Exception e) {
}
}
private void _shutdownService()
{
if (timer != null) timer.cancel();
Log.i(getClass().getSimpleName(), "Timer stopped...");
}
#Override
public void onDestroy()
{
super.onDestroy();
_shutdownService();
// if (MAIN_ACTIVITY != null) Log.d(getClass().getSimpleName(), "FileScannerService stopped");
}
}

related to threads of services in android

the service is started by a single activity 4 times, how many threads are created by a service? And if service is started by 4 different activities then how many threads are created? Which function must be implemented inside a service inherited from intentService? how many threads are required to create inside this function?
public class HelloService extends Service {
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
// Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
// Stop the service using the startId, so that we don't stop
// the service in the middle of handling another job
stopSelf(msg.arg1);
}
}
#Override
public void onCreate() {
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
}
the service is started by a single activity 4 times, how many threads are created by a service?
Depends. Your Service creates a new thread in onCreate, so if it's never killed then you'll only have 1 thread created. If somehow it did get killed, you would end up with one for every time you started your Service.
And if service is started by 4 different activities then how many threads are created?
Same as above.
Which function must be implemented inside a service inherited from intentService?
You might try reading the docs for IntentService, you'd find you want to implement onHandleIntent.
how many threads are required to create inside this function?
Zero.

Categories

Resources