Obtaining context in service - android

I'm developing a service started from activity. The service starts a thread that after a long work should call a method from the activity. How can I deliver link at the activity to the thread?

You could just simply bind to the service in order to start it. When bounded, you get the binder in your activity and register a callback in your service. When your thread has finished you call the callback method which goes up to your activity.
In other word, use bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE) and get the binder from the serviceConnection implementation
private static ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceDisconnected(ComponentName name) {
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinder = (YourBinder) service;
mBinder.registerCallback(yourCallbackImplementation);
}
};
And you use yourCallbackImplementation to get messages from the service.

Related

Can I instantiate a bound service class in android by calling new?

Normal way of using a bound service:
private ServiceConnection musicConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
MusicBinder binder = (MusicBinder)service;
//get service
musicSrv = binder.getService();
//pass list
musicBound = true;
}
#Override
public void onServiceDisconnected(ComponentName name) {
musicBound = false;
}
};
Intent playIntent = new Intent(this, MusicService.class);
bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
Instead of this, can't we use this:
MusicService music=new MusicService();
If yes, will there be any differences between the two instances obtained in two different ways?
Bind service or start service will result in a corresponding call to the target service's life cycle methods.
If this service is not already running, it will be instantiated and started (creating a process for it if needed); if it is running then it remains running.
New a service is just create a new object, means nothing, system knows nothing about it.
Just like activity, you cannot new a activity, you should start a activity, then ActivityManager will be response for create the Activity instance and calls its onCreate method.

Interaction between IntentService and Activity - Android

In my application I am using an IntentService to download a file from a cloud. And showing the progress in NotificationManager. I need to show the status (Downloading/Completed or Failed) in the Activity which stared the IntentService too.
My problem is once I closed the app and open it back, I want to get the status of downloading from IntentService.
Which is the best way to do this?
You can let your Activity bind to your Service, by calling bindService() in your Activity. As per the documentation:
A service is "bound" when an application component binds to it by
calling bindService(). A bound service offers a client-server
interface that allows components to interact with the service, send
requests, get results, and even do so across processes with
interprocess communication (IPC). A bound service runs only as long as
another application component is bound to it. Multiple components can
bind to the service at once, but when all of them unbind, the service
is destroyed.
Also:
You should create a bound service when you want to interact with the
service from activities and other components in your application or to
expose some of your application's functionality to other applications,
through interprocess communication (IPC).
The documentation provides a fully functional example of this. Below is taken from the provided link.
Service class:
public class LocalService extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
// Random number generator
private final Random mGenerator = new Random();
/**
* Class used for the client Binder. 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 {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/** method for clients */
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}
Activity class:
public class BindingActivity extends Activity {
LocalService mService;
boolean mBound = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
#Override
protected void onStart() {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
/** Called when a button is clicked (the button in the layout file attaches to
* this method with the android:onClick attribute) */
public void onButtonClick(View v) {
if (mBound) {
// Call a method from the LocalService.
// However, if this call were something that might hang, then this request should
// occur in a separate thread to avoid slowing down the activity performance.
int num = mService.getRandomNumber();
Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
}
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}
In your Service, you can define public methods that your Activity can call, such as polling for your download progress. Please refer to the documentation for explanation in detail.
There are couple of ways to have communication connection between Service and Activity. I would suggest these 2
First, you can use the great library Otto. With Otto, you can also have #Produce annotated method. With this method you will return the latest information about the download. When you #Subscribe in your Activity you will get the latest info immediately. https://github.com/square/otto
If you are using Android built-in DownloadManager it returns the updates and results with a Broadcast, you can register to that Broadcast both in your Service and Activity. This way you will be able to update both of them. I suggest you to use DownloadManager, it is awesome.
http://developer.android.com/reference/android/app/DownloadManager.html

How to bind to a Service that was started by another instance of the application

I have a background Service that need to be running even if the application gets killed by Android. This is currently working perfectly.
My problem is that when I restart the application (with the background service still running), I want my Activity to bind to the service to have access to some of its methods. When I try to bind with a ServiceConnection, the onServiceConnected is never called.
final private ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
Log.d(TAG, "onServiceConnected"); //this is never called
MyBackgroundService.ServiceBinder binder = (MyBackgroundService.ServiceBinder) service;
backgroundService = binder.getService();
}
public void onServiceDisconnected(ComponentName className) {
Log.d(TAG, "onServiceDisconnected");
backgroundService = null;
}
};
private void bindBackgroundService(){
this.bindService(new Intent(this, MyBackgroundService.class), serviceConnection, Context.BIND_AUTO_CREATE);
}
Am I doing this the wrong way? Is it better to stop the Service and restart it?
Since the class that binded the background service is a singleton and my alarm broadcast receiver that is making sure the background service is always running instantiates this singleton, I had access to this singleton and I was trying to bind to the service that was already binded.

Android: Getting a variable from my running service

My activity starts a Service, and when I close my app, the service continues to run.
OK, that's right. But when I open my application again, in the activity, I need to know the value of a public variable defined on the running Service(class) that I've started previously.
How can I do that?
Thanks
If you are binding your Activity to the Service, you should have an implementation of the Binder interface in your Service, e.g.
public class ServiceBinder extends Binder {
public MyService getService() {
return MyService.this;
}
}
In your Activity, create a new ServiceConnection class which will be used to give you access to your Service:
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mMyService = ((MyService.ServiceBinder)service).getService();
}
public void onServiceDisconnected(ComponentName className) {
mMyService = null;
}
};
Here the member variable mMyService will give you access to all public members of your Service class.
To create the connection, implement doBindService and doUnbindService in your Activity:
void doBindService() {
bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE);
}
void doUnbindService() {
// Detach our existing connection.
unbindService(mConnection);
}
Hope this helps!
If you don't call unbindService, your activity still have connection to service and you can simply check the variable through the service's method.
You could use messenger.
As per android website
A messenger is reference to a Handler, which others can use to send messages to it. This allows for the implementation of message-based communication across processes, by creating a Messenger pointing to a Handler in one process, and handing that Messenger to another process.

Wait on startService before bindService

It is my understanding that if I want a service to run even if nothing is bounded to it, then it must first be started with startService(Intent i).
My question is WHAT IF I want to bind to the service immediately after I start it, would the following code guarantee the service is created with startService()?
Static method within the service class:
public static void actStart(Context ctx) {
Intent i = new Intent(ctx, BGService.class);
i.setAction(ACTION_START);
ctx.startService(i);
}
The binding activity:
BGService.actionStart(getApplicationContext());
bindService(new Intent(this, BGService.class), serviceConnection, Context.BIND_AUTO_CREATE);
I am not sure what you are trying to do here, but "Context.BIND_AUTO_CREATE" creates the service then binds to the service even if it hasn't been started.
Now if you want to access it immediately after binding, you can use the onServiceConnected() method of the serviceConnection:
new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
//put your code here...
} ...
To add to Bugdayci's answer, a complete example is as follows:
ServiceConnection myConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
... your code that needs to execute on service connection
}
#Override
public void onServiceDisconnected(ComponentName name) {
... your code that needs to execute on service disconnection
}
};
Intent intent = new Intent(this, TheServiceClassName.class);
bindService(intent, myConnection, Context.BIND_AUTO_CREATE);
...
Without the bindService at the end, the onServiceConnected() code will not execute.

Categories

Resources