how to reference object created with Intent / startService - android

If I create a service in my app's onCreatelike this:
Intent srv = new Intent( this, MyService.class );
startService( srv );
how do I get a reference to the service object and how does the service object reference the app which launched it?
(Yes, I have listed the service in my AndroidManifest).

There are a few ways to handle this. You can bind to the service (bindService) where you will be called back with an IBinder interface.
Another approach is to just keep calling startService() with different intent data as a way of messaging to the service, with intent extra data containing message specifics.
Finally, if you know the service is in the same process, you can share the service instance in some static memory.

Building a Service
First of all, we need to create the Service in the AndroidManifest.xml file. Remember, that every Activity, Service, Content Provider you create in the code, you need to create a reference for here, in the Manifest, if not, the application will not recognize it.
<service android:name=".subpackagename.ServiceName"/>
In the code, we need to create a class that extends from “Service”
public class ServiceName extends Service {
private Timer timer = new Timer();
protected void onCreate() {
super.onCreate();
startservice();
}
}
This is a way to create Services, there are others ways, or the way I use to work with them. Here, we create a Timer, that every X seconds, calls to a method. This is running until we stop it. This can be used, for example, to check updates in an RSS feed. The “Timer” class is used in the startservice method like this
private void startservice() {
timer.scheduleAtFixedRate( new TimerTask() {
public void run() {
//Do whatever you want to do every “INTERVAL”
}
}, 0, INTERVAL);
; }
Where INTERVAL, is the time, every time the run method is executed.
To stop the service, we can stop the timer, for example, when the application is destroyed (in onDestroy())
private void stopservice() {
if (timer != null){
timer.cancel();
}
}
So, this application will be running in the background...

Related

Same Intent Service running multiple background tasks parallely (ISSUE)

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);

AlarmManager Calling Function in Same Class

I am trying to give a LocationClient a two-minute period to connect before calling getLastLocation on it. Initially I implemented this with a Timer (and TimerTask), but because Timers do not work in sleepmode, I would like to translate it to an AlarmManager. However, I am a bit confused as to how to do this, considering an AlarmManager calls another class, whereas I want to remain in the same class and simply delay for a two-minute period.
This is how it looks with a Timer.
Timer theTimer = new Timer();
theTimer.schedule(new TimerTask() {
#Override
public void run() {
if(checkIfGooglePlay() && checkTime()) {
getPostLocation();
stopSelf();
mLocationClient.disconnect();
}
}
}, TWO_MINUTES);
Alarm Manager calls a broadcast receiver via a pending intent. Just make that BroadcastReceiver implementation a private subclass of the class that registers it. That way it has full access to class member variables and functions.
You may try using Java's Thread.sleep(). It's a static method so you don't need to instantiate a new Thread. It throws a InterruptedException, which, in simpler cases, shouldn't bother you.
From http://developer.android.com/reference/java/lang/Thread.html:
Causes the thread which sent this message to sleep for the given interval of time (given in milliseconds and nanoseconds).

how to stop Intent services in android

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.

How do I cancel all pending intents that are qued for intent Service

I have an intentservice that gets qued by the user and by my app automatically. I need to be able to kill all pending intents that are qued when the user logs out of my application, but I cannot seem to get that to work. I have tried stopService() and stopself(), but the intents continue to fire off the intentservice after the user has logged out. I would try to get the id of the intent but that is difficult as everytime the intentservice starts, the variable holding the intent id's is empty. Here is my intentservice code:
public class MainUploadIntentService extends IntentService {
private final String TAG = "MAINUPLOADINTSER";
private GMLHandsetApplication app = null;
private SimpleDateFormat sdf = null;
public boolean recStops = true;
public MainUploadIntentService() {
super("Main Upload Intent Service");
GMLHandsetApplication.writeToLogs(TAG,
"GMLMainUploadIntentService Constructor");
}
#Override
protected void onHandleIntent(Intent intent) {
GMLHandsetApplication.writeToLogs(TAG, "onHandleIntent Started");
if (app == null) {
app = (GMLHandsetApplication) getApplication();
}
uploadData(app);
GMLHandsetApplication.writeToLogs(TAG, "onHandleIntent Finished");
}
#Override
public void onDestroy() {
GMLHandsetApplication.writeToLogs(TAG, "onDestroy Started");
app = null;
stopSelf();
GMLHandsetApplication.writeToLogs(TAG, "onDestroy completed");
}
public void uploadData(GMLHandsetApplication appl) {
//All of my code that needs to be ran
}
Unfortunately, I don't think it's possible to accomplish that with the standard IntentService methods since it doesn't offer a way to interrupt it while it's already going.
There are a few options I can think of that you can try to see if they fit your need.
Copy the IntentService code to make your own modifications to it that would allow you to remove pending messages. Looks like someone had some success with that here: Android: intentservice, how abort or skip a task in the handleintent queue
Instead of copying all the IntentService code, you might also be able to Bind to it like a normal Service (since IntentService extends Service) so you can write your own function to remove pending messages. This one is also mentioned in that link.
Rewrite the IntentService as a regular Service instead. With this option, you'd have more control over adding and removing messages.
I had what sounds like a similar situation where I was using an IntentService, and I eventually just converted it to a Service instead. That let me run the tasks concurrently and also cancel them when I needed to clear them.
Here
When should I free the native (Android NDK) handles? is the HangAroundIntentService class that has the method cancelQueue().
The class also has the method
public static Intent markedAsCancelIntent(Intent intent)
that converts an intent into a cancel intent, and
public static boolean isCancelIntent(Intent intent).
The class is based on the open-sourced Google's code.
Just a thought but inside of your onhandleintent can you have an argument that checks to see if app is running if not then don't run the code? example. In the start of your app you could have a static var
boolean appRunning;
Next in your onhandle of the intent, when you set the appRunning to false, after an onPause or onDestroy of activity, you could wrap the onhandleintent code in a boolean:
protected void onHandleIntent(final Intent intent) {
if(MainActivity.appRunning){
...
}
}
Just a thought

Android: Obtaining a class after a call to startService()

I am getting confused with all the different terminology when using Android: Activity, Service...
Right now I create a service:
startService(new Intent(this, RingerServer.class));
And this service starts a thread:
public class RingerServer extends Service {
public void onCreate() {
super.onCreate();
new Thread(new Ringer()).start();
}
public class Ringer implements Runnable { ... }
public void refuseConnection() { ... }
}
In this service, the RingerServer, I also have methods that I want to use. I would like to keep a reference to the RingerServer. I would basically like the Activity that created the service to be able to call refuseConnection(), but not make that method static.
startService returns a ComponentName, so I've been trying to cast it back to RingerServer but that doesn't seem to work. I see that it has getClass() and I've checked and getClassName() gives me the correct class. I haven't been able to use getClass() properly though.
Is there any way I can please keep a reference to the newly created RingerServer class? I am sure this is trivial, but I am stuck right now.
Thank you very much,
James
You have two options
1.Override onStartCommand of the service and start the server with intent using an action. that intent will be received in service, based on the intent action you can call refuseConnection()
//In Activity
...
//Start the service
Intent intent=new Intent("com.xx.xx.REFUSE_CONNECTION");
startService(this,intent);
...
//In Service
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
if(intent.getAction().equals("com.xx.xx.REFUSE_CONNECTION")){
//Refuse the connection
refuseConnection();
}else {
//Do something else
}
}
//In Manifest
<service android:name="RingerService">
<intent-filter>
<action android:name="com.xx.xx.REFUSE_CONNECTION"></action>
</intent-filter>
</service>
Implement AIDL interface and override onBind() of service , and use this interface to call refuseConnection(). Refer to this link http://developer.android.com/guide/developing/tools/aidl.html regarding AIDL.
You can use a ServiceConnection to get access to your service class. See sample code here:
Android service running after pressing Home key
That said, managing things via the service's onStart handler is much simpler.

Categories

Resources