related to threads of services in android - 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.

Related

Android Service shuts down while Runnable is still executing

I have a Service in my app with which I send requests to a server. After I send a request to start an operation on the server, I need to poll the server for updates by sending a request every 15 seconds to track the progress. For this I use a ScheduledExecutorService that calls a Runnable.
The Service does a bunch of things in onHandleIntent and then starts the ScheduledExecutorService that does the polling. All of this is working fine.
The issue is while the ScheduledExecutorService is executing the Runnable at intervals, the service gets destroyed, as in the onDestroy method is called. Is there a way to prevent this from happening?
I have a Broadcast Receiver registered in the service that can be triggered any time by the user while the ScheduledExecutorService is executing the Runnable. But since the Service is destroyed, the Receiver gets unregistered.
Here is some simplified code:
#Override
protected void onHandleIntent(Intent intent) {
Log.d(TAG, "OnHandleIntent started");
try {
if (intent != null) {
final String action = intent.getAction();
if (getActionUpload().equals(action)) {
wakeLock.acquire();
notificationConfig = new CustomNotificationConfig();
//Register receiver to stop operation
IntentFilter filter = new IntentFilter(ThirdPartyStopReceiver.ACTION_STOP);
filter.addCategory(Intent.CATEGORY_DEFAULT);
mThirdPartyStopReceiver = new ThirdPartyStopReceiver();
registerReceiver(mThirdPartyStopReceiver, filter);
Boolean operationStarted = startOperation();
if (operationStarted) {
checkProgressAtIntervals();
}
}
}
} catch (Exception e) {
Log.e(TAG, "Error with XML");
e.printStackTrace();
} finally {
wakeLock.release();
}
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
try {
//Unregister the receiver
unregisterReceiver(mThirdPartyStopReceiver);
} catch (IllegalArgumentException e) {
//Receiver has already been unregistered. Do nothing
e.printStackTrace();
}
}
private void checkProgressAtIntervals() {
Log.d(TAG,"in checkProgressAtIntervals");
final ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
ses.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
try {
int progress = sendProgressRequest();
if(isCanceled){
sendCancelRequest();
ses.shutdown(); //Stop polling
}
if (progress >= 100) {
ses.shutdown(); //Stop polling
}
} catch (Exception e) {
Log.e(TAG, "Exception in sendProgressRequest ");
e.printStackTrace();
}
}
}, 1, 15, TimeUnit.SECONDS);
}
public class ThirdPartyStopReceiver extends BroadcastReceiver {
public static final String ACTION_STOP = "thirdpartystop";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Cancel request received in onReceive");
isCanceled = true;
//...
}
}
So as you can see, I need to execute some code in the service if a "Stop" broadcast is received.
I have tried using a Handler with its postDelayed method but the service gets destroyed before the Handler starts to execute so the Runnable never executes. I tried instantiating the Handler with Looper.myLooper() but with the same result.
Since the runnable contains HTTP calls, instantiating Handler with Looper.getMainLooper() throws a NetworkOnMainThreadException
It seems you are using an IntentService, which stops after it ends its work, that is, the onHandleIntent method. An IntentService is intended to be short-lived.
Try using a regular Service instead. Mind that Android can stop a Service at its own discretion, but in a general manner the Service will run for a long period.

Can't save and display data using Service/IntentService properly

I am updaiting database on each app launch, i was using IntentService before, but my activity was starting before data is updated, so data list was empty, i have rewriten it using Service(i have created my own Service acting like IntentService so i could controll thread created by the Service). As you see first of all i am saving data, and only after that i am starting my activity. But my activity is starting before data is saved anyway, any suggestions why, or how can i fix this?
Also
If you have some expirience working with ORM/Database async it would be great, i am just trying to learn how to work with database properly. Any suggestions are apreciated.
public class DatabaseWorkService extends Service {
private ServiceHandler mServiceHandler;
private DatabaseReference mDatabase;
private ConnectivityManager conMan;
private NetworkInfo netInfo;
private String currentTask;
private Intent tempIntent;
private Looper mServiceLooper;
private ResultReceiver resultReceiver;
private Context context =this;
public DatabaseWorkService delegate = null;
// 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) {
if(msg.getData()!=null) {
switch (msg.getData().getString(Utils.INTENT_SERVICE_INVOKE)) {
case Utils.LOAD_All_DATA: {
saveActivities();
savePersons();
savePictureData();
Intent intent = new Intent(context, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Log.e("order", "forth");
break;
}
case Utils.READ_ACTIONS_DATA: {
readActionData();
break;
}
case Utils.READ_PERSONS_DATA: {
readPersonsData();
break;
}
}
}
stopSelf(msg.arg1);
}
}
#Override
public void onCreate() {
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
HandlerThread thread = new HandlerThread("ServiceStartArguments");
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("service","service started");
Log.e("data",intent.getStringExtra(Utils.INTENT_SERVICE_INVOKE));
Bundle bundle = new Bundle();
bundle.putString(Utils.INTENT_SERVICE_INVOKE,intent.getStringExtra(Utils.INTENT_SERVICE_INVOKE));
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.setData(bundle);
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
#Override
public void onDestroy() {
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
if these quires returning any values after insertion in database, then only you have to launch activity
saveActivities();
savePersons();
savePictureData();
try below code launch your activity inside Main thread handler
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(context, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});

Android background service with background thread causing anr error

I have implemented an android service which performs following long operations
when screen goes off start recording accelerometer data.
When data reaches 3000 samples I write it to the file.
then I perform data processing on the after reading recorded data.
Then I extract gait template from that data.
Then I compute similarity score.
I want to keep that service running as long as user explicitly does not quit this service.
In case if screen goes on I stop data recording and check if number of samples are more than minimum number of samples i repeat steps 2-5. else just drop recorded samples.
I have a broadcast receiver to get SCREEN_ON and SCREEN _OFF broadcasts writing file works fine but time taking part is feature (or template generation) I read from android documentation
A service runs in the main thread of its hosting process—the service does not create its own thread and does not run in a separate process (unless you specify otherwise). This means that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 playback or networking), you should create a new thread within the service to do that work. By using a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the application's main thread can remain dedicated to user interaction with your activities.
Therefore I am trying to implement service with background thread. But still i am getting anr errors any help ?.
public class GaitAuthenticationService extends Service {
int mStartMode; // indicates how to behave if the service is killed
IBinder mBinder; // interface for clients that bind
boolean mAllowRebind; // indicates whether onRebind should be used
private int serviceState = 0; // This will maintain state of our service
private BroadcastReceiver screenOnOffReceiver = new ScreenOffBroadCastReciever();;
private SensorManager mSensorManager;
private PowerManager mPowerManager;
private PowerManager.WakeLock mLock;
private AccelRecorderTesting mAccelRecorder;
private Context context;
private boolean screenOff;
private KeyguardManager keyGaurdManager;
private boolean screenState;
private IntentFilter mfilter;
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) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
// Stop the service using the startId, so that we don't stop
// the service in the middle of handling another job
if (screenState==true && (keyGaurdManager.isKeyguardLocked() || keyGaurdManager.isKeyguardSecure())){
Log.d("SCREEN ON OFF RECIEVER","screen is oFF(onStartCommand)");
Log.d("GaitAuthenticationService", "Started recording data");
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
mAccelRecorder.onStartButtonIsClicked();
}
// stopSelf(msg.arg1);
}
}
#Override
public void onCreate() {
mAccelRecorder = new AccelRecorderTesting();
keyGaurdManager = (KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE);
mAccelRecorder = new AccelRecorderTesting(this.getApplicationContext());
Log.i("GaitAuthenticationService", " is started");
mfilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
mfilter.addAction(Intent.ACTION_SCREEN_ON);
registerReceiver(screenOnOffReceiver, mfilter);
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work will not disrupt our UI.
HandlerThread thread = new HandlerThread("ServiceStartArguments",new Process().THREAD_PRIORITY_BACKGROUND);
thread.start();
// Get the HandlerThread's Looper and use it for our Handler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
#SuppressLint("NewApi")
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// The service is starting, due to a call to startService()
// if(intent!=null){
//screenOnOffReceiver = new ScreenOffBroadCastReciever();
screenState = intent.getBooleanExtra("screen_state",screenOff);
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
if (screenState){
mServiceHandler.sendMessage(msg);
}
if(screenState == false){
Log.d("SCREEN ON OFF RECIEVER","screenON(onStartCommand)");
try {
mAccelRecorder.onStopButtonIsClicked(true);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d("GaitAuthenticationService", "Stop Recording data");
}
// }
return GaitAuthenticationService.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
Log.i(" GaitAuthenticationService", "Service is destroyed");
if(screenOnOffReceiver!=null){
Log.i("screenreciever", "true");
unregisterReceiver(screenOnOffReceiver);
screenOnOffReceiver=null;
}
super.onDestroy();
}
/* (non-Javadoc)
* #see android.app.Service#onUnbind(android.content.Intaent)
*/
#Override
public boolean onUnbind(Intent intent) {
if(screenOnOffReceiver!=null){
Log.i("screenreciever", "true");
unregisterReceiver(screenOnOffReceiver);
screenOnOffReceiver = null;
}
return super.onUnbind(intent);
}
}
Here is my broadcast Reciever
public class ScreenOffBroadCastReciever extends BroadcastReceiver {
private boolean screenOff;
#Override
public void onReceive(Context context, Intent intent) {
if(intent!=null){
if ((intent.getAction().equals(Intent.ACTION_SCREEN_OFF))) {
screenOff = true;
}
if(intent.getAction().equals(Intent.ACTION_SCREEN_ON)){
screenOff = false;
}
Intent i = new Intent(context, GaitAuthenticationService.class);
i.putExtra("screen_state", screenOff);
context.startService(i);
}
}
}
Receiver in AndroidManifest.xml
<receiver android:name="ScreenOffBroadCastReciever" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.SCREEN_OFF"/>
<action android:name="android.intent.action.SCREEN_ON"/>
</intent-filter>
</receiver>

Multiple Services on Multiple Threads Lifecycle

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.

How to start a new Thread in a service?

I am developing an Android app and I am doing some heavy work (bringing data from an online web page and parsing it to store in database) in a service. Currently, it is taking about 20+ mins and for this time my UI is stuck. I was thinking of using a thread in service so my UI doesn't get stuck but it is giving error. I am using the following code:
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(1000);
Toast.makeText(getBaseContext(), "Running Thread...", Toast.LENGTH_LONG).show();
}
} catch (InterruptedException e) {
Toast.makeText(getBaseContext(), e.toString(), Toast.LENGTH_LONG).show();
}
}
};
thread.start();
This simple code is giving run time error. Even If I take out the while loop, it is still not working.
Please, can any one tell me what mistake I am doing. Apparently, I copied this code directly from an e-book. It is suppose to work but its not.
Android commandment: thou shall not interact with UI objects from your own threads
Wrap your Toast Display into runOnUIThread(new Runnable() { });
Example of new thread creation taken from Android samples (android-8\SampleSyncAdapter\src\com\example\android\samplesync\client\NetworkUtilities.java):
public static Thread performOnBackgroundThread(final Runnable runnable) {
final Thread t = new Thread() {
#Override
public void run() {
try {
runnable.run();
} finally {
}
}
};
t.start();
return t;
}
runnable is the Runnable that contains your Network operations.
You can use HandlerThread and post to it, here is an example to service that has one.
public class NetworkService extends Service {
private HandlerThread mHandlerThread;
private Handler mHandler;
private final IBinder mBinder = new MyLocalBinder();
#Override
public void onCreate() {
super.onCreate();
mHandlerThread = new HandlerThread("LocalServiceThread");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
}
public void postRunnable(Runnable runnable) {
mHandler.post(runnable);
}
public class MyLocalBinder extends Binder {
public NetworkService getService() {
return NetworkService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
You may define your jobs in a runnable object, use a thread object for running it and start this thread in your service's onStartCommand() function. Here is my notes:
In your service class:
define your main loop in an Runnable object
create Thread object with the runnable object as parameter
In your service class's onStartCommand method():
call thread object's start function()
my code :
private Runnable busyLoop = new Runnable() {
public void run() {
int count = 1;
while(true) {
count ++;
try {
Thread.sleep(100);
} catch (Exception ex) {
;
}
ConvertService.running.sendNotification("busyLoop" + count);
}
}
};
public int onStartCommand(Intent intent, int flags, int startId) {
sendNotification("onStartCommand");
if (! t.isAlive()) {
t.start();
}
return START_STICKY;
}

Categories

Resources