I have two Bounded Services, and some Activities that bind themselves to the services when they need it.
The problem is the performance of the app is slow when the activities write the information got from the services in the display.
Android's documentation says about the Stated Services:
Caution: A services runs in the same process as the application in
which it is declared and in the main thread of that application, by
default. So, if your service performs intensive or blocking operations
while the user interacts with an activity from the same application,
the service will slow down activity performance. To avoid impacting
application performance, you should start a new thread inside the
service.
But it says nothing about the Bound Services running in other threads. So i decided to start the services in this way:
private void startRunService()
{
final Intent intent = new Intent(this, RunService.class);
Thread thread = new Thread(new Runnable() {
public void run() {
startService(intent);
}
});
thread.start();
}
private void startLinkerRunService()
{
final Intent intent = new Intent(this, LinkerRunService.class);
Thread thread = new Thread(new Runnable() {
public void run() {
startService(intent);
}
});
thread.start();
}
So starting each service in a different service I got an unexpected improvement of the performance. But I'm not sure that it is a good idea.
Do you know if it has side effects?
Thanks in advance.
Related
public class DataManager extends IntentService {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
}
public DataManager() {
super("DataManager");
setIntentRedelivery(true);
}
#Override
protected void onHandleIntent(final Intent intent) {
// download and parsing task done here
}
}
This is my intent service which i am using to download file and parse it. Now if i get a new request for a file download, i have to clear the ongoing task and start the download for new request cancelling the older one. so i use the below code for doing it :.
private void refreshSync() {
context.stopService(new Intent(context, DataManager.class));
final Intent mServiceIntent = new Intent(context, DataManager.class);
mServiceIntent.putExtras(bundle);
context.startService(mServiceIntent);
}
So the service gets killed and the next request to start service is intented. But the previous tasks starts again running two parallel tasks performing download. Basically the previous task doesnt get killed which i intended to.
Is there any work around to kill the ongoing task of the service and start another fresh task ?
Don't use IntentService. This doesn't match your requirements. IntentService is a simple Service that accepts a queue of work and processes the queue and then shuts itself down when the queue is empty.
You need more intelligence, and you are better off implementing that yourself. Just extend Service instead of IntentService. In onStartCommand() start a background Thread that downloads the data. Keep track of that background Thread in a member variable in the Service. If startService() gets called again, check if you already have a download in progress. If so, stop it and start a new background Thread to download the new file. To stop a background thread, you should provide a boolean variable in the Thread that gets examined every now and then inside the download loop. If that variable's state changes, it means the Thread should stop. This is a standard mechanism for stopping background threads in Java.
You are setting setIntentRedelivery(true);, that force the intents to survive calls of the service if they are not handled completely (if onHandleIntent doesn't manage to return). Taking into account the fact that IntentService has only one working thread (can execute only one task at a time) the behavior of the service completely depends on the onHandleIntent implementation. So you need either analyze implementation and change it according to you goals, or set setIntentRedelivery(false);
What is the recommended approach for checking for new data regardless if the app is in the foreground or background? I am wondering which Android API people are typically using to do this. There seems to be a few ways to achieve my goal, and I want to make sure I'm on the right path.
I have something put together which uses AlarmManager.SetInexactRepeating() to call an IntentService which does the sync and inserts/updates data in the database. This works while the app is in the foreground and background, but if I force stop the app then I keep seeing "Unfortunately, has stopped working" messages when the AlarmManager alarm would've triggered. In this case, I only care about checking for new data only when the app is running in the foreground or background.
My first thought is to detect when the app is force closed, and stop the alarm, but that does not seem possible. So I am asking here, is my approach wrong? If so, which approach is used to perform some periodic task regardless if the phone is in the foreground or background? The problem with the AlarmManager solution I am using is the alarms continue to fire even when the app is closed.
If your idea is to check if your API has new data and perform a background sync to your local database or other data storage, I think you would like to take a look at this:
Creating a Sync Adapter
Running a Sync Adapter
The Sync adapter is the recommended way of achieving this in Android. The pros of using it are multiple:
Optimisations out of the box - the OS bundles calls, uses the most appropriate windows to run the sync adapter at a minimal bandwidth and battery cost
The lifecycle of your background sync component is managed internally by the OS
Observers can be notified when data has been changed so the UI can be updated easily
Multiple ways of running the sync - at intervals, automatically with the OS message to keep TCP/IP connections open or on demand
However, implementing this requires some things, that can cause a bit of a pain at first:
It is mandatory that the adapter works with a ContentProvider
Sync Adapters use Account for authentication. If this is not needed, a Stub has to be provided
For backgrounding on Android usually you use even a Service that can run alone and independently from the App or a Bounded service that takes and returns data from the App. A complete reference on backgrounding can be found here
Using a Service is the right way to go. Have your app start the Service and it will continue running while the app is in the foreground or the background. Then, if you want to kill the Service when your app closes, you could just call stopService(yourServiceIntent); from the onDestroy() override in your app's activity. That should effectively shut down the service when the app closes.
So some sample code of how this works (taken from the Services docs)...
The Service (just Logs a message every 1 second for 60 seconds):
public class MyService 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() + 60*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(1000);
Log.d("SERVICE", "The service is still running.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
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) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
}
}
And in your activity you would do something like:
public class MainActivity extends AppCompatActivity {
Intent serviceIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
serviceIntent = new Intent(this, MyService.class);
startService(serviceIntent);
}
#Override
protected void onDestroy() {
stopService(serviceIntent);
super.onDestroy();
}
What is the best way to implement an android Service (not IntentService) which polls a device using SNMP at regular intervals? I've tried implementing it with a Handler.postDelayed(Runnable) within onHandleIntent of IntentService. But later found it cannot be used in onHandleIntent() from this answer. My code just would not execute the runnable part.
make an IntentService not sleep until it executes a handler.postDelayed runnable
My code goes like:
public class MyPoller extends IntentService {
//Variable declarations
protected Handler handler;
public MyPoller() {
super("My service");
}
#Override
protected void onHandleIntent(Intent intent) {
.......
.......
runable = new Runnable() {
public void run() {
//My code here
handler.postDelayed(this, poll_interval);
}
};
handler.postDelayed(runable,poll_interval);
}
}
So I thought I could implement the same in a service, but I don't know how to implement this recurring task in a service also running it in a new thread. I found few answers demonstrating different ways of running recurring tasks in a new thread in a Service, but I'm confused.
Can someone suggest some way of implementing the same in a Service? It would be of great help. Thanks in advance.
How I can start my service in ASyncTask
for example
MyTask task = new MyTask();
startService(new Intent(MainActivity.this, MyService.class), task);
What is correct way to do this?
I want to tell service in which threads are executed
Quote from Android dev. :
AsyncTask enables proper and easy use of the UI thread. This class
allows to perform background operations and publish results on the UI
thread without having to manipulate threads and/or handlers.
I guess if you're not using directly startService, is that you want start it in a new thread, no ?
If so, you should do a new thread :
Thread t = new Thread(){
public void run(){
getApplicationContext().bindService(
new Intent(getApplicationContext(), YOURSERVICE.class),
serviceConnection,
Context.BIND_AUTO_CREATE
);
}
};
t.start();
i have created one intent service. Now I want to stop that service from activity how to stop that service? My code is:
MyActivity.java
#Override
public void onCreate(Bundle savedInstanceState) {
Intent intent = new Intent(this, myService.class);
intent.putExtra("myHand", new Messenger(this.myHand));
startService(intent);
}
myService.java
public class myService extends IntentService {
#Override
protected void onHandleIntent(Intent intent) {
String signal = intent.getAction();
if (signal != null && signal.equals("stop")) {
stopSelf();
} else {
t.schedule(new TimerTask() {System.out.println("print")}, 0, 10000);
}
}
}
to stop service on click of button
Intent in = new Intent(this, myService.class);
in.setAction("stop");
stopService(in);
can anybody help me to stop service?
From the docs for IntentService
IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.
In other words, you don't have to stop an IntentService - it will terminate itself when it has no more work to do.
EDIT:
Looking back at your code, it seems you don't wan't to stop the IntentService you want to stop the TimerTask???
t.schedule(new TimerTask() {System.out.println("print")}, 0, 10000);
I don't know what t is but I'm guessing it's a Timer. If that's the case it will be running with its own Thread and attempting to terminate the IntentService is pointless - kill the Timer instead.
Also, why are you using an IntentService to create any type of object which maintains its own thread of execution?
Now I want to stop that service from activity how to stop that
service?
IntentService stops itself, you shouldn't, you can't call stopSelf().
When all requests have been handled, the IntentService stops itself.
From what I know, IntentHandler creates a separate new thread, does its work, and kills itself.
So I don't think you need to explicitly stop it from an activity.