I have a bound Service. An activity is binding it. It unbinds the Service on Activity's onStop()
method.
The problem is, if runtime changes (for example, orientation change) happen to the Activity, then the Activity is recreated. So, onStop()
method is called from the Activity, and the Activity unbinds the Service in that method, which results in destruction of the Service (and restarting of it).
I want to preserve the Service from being destroyed in the runtime changes while keeping Service stopping when the Activity is invisible. You could say that try startService()
but it makes the Service not to stop when Activity is invisible. If I add stopService Activity's onStop()
, then the result is the same as bindService()
and unbindService()
.
PostDelaying unbindService()
in Acitivity's onStop()
can solve this problem partly, but the delaying time will be arbitrary, and this prevents the Activity from getting GC for some time. I want a more clear solution.
I don't want solutions like android:configChanges="orientation"
since there are other runtime changes as well, and it is a discouraged way of processing runtime changes.
In short, I want the Service to act like a Fragment that called setRetainInstance(true)
. However, Fragments don't have something like bindService()
. What should I do?
Binding to a started service If you do allow your service to be started and bound, then when the service has been started, the system does not destroy the service when all clients unbind. Instead, you must explicitly stop the service by calling stopSelf() or stopService() .
A service is termed as bounded when an application component binds itself with a service by calling bindService() method. To stop the execution of this service, all the components must unbind themselves from the service by using unbindService() method.
Bounded services are bounded to an activity which binds it and will work only till bounded activity is alive. while a unbounded service will work till the completion even after activity is destroyed.
Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC). For example, a service can handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.
However, Fragments don't have something like bindService().
But they can use bindService()
from the Application
context:
public class BshFragment extends Fragment implements OnClickListener,
ServiceConnection {
private IScript service=null;
private Button btn=null;
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
View result=inflater.inflate(R.layout.main, container, false);
btn=(Button)result.findViewById(R.id.eval);
btn.setOnClickListener(this);
btn.setEnabled(false);
setRetainInstance(true);
return(result);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getActivity().getApplicationContext()
.bindService(new Intent(getActivity(),
BshService.class), this,
Context.BIND_AUTO_CREATE);
}
@Override
public void onDestroy() {
getActivity().getApplicationContext().unbindService(this);
disconnect();
super.onDestroy();
}
@Override
public void onClick(View view) {
EditText script=(EditText)getView().findViewById(R.id.script);
String src=script.getText().toString();
service.executeScript(src);
}
@Override
public void onServiceConnected(ComponentName className, IBinder binder) {
service=(IScript)binder;
btn.setEnabled(true);
}
@Override
public void onServiceDisconnected(ComponentName className) {
disconnect();
}
private void disconnect() {
service=null;
btn.setEnabled(false);
}
}
(as seen in this sample project, covered in this book)
By using the Application
context, we are able to use the same Context
for binding and unbinding. By retaining the fragment, we can avoid unbinding and rebinding on a configuration change.
Personally, I just try to avoid the binding pattern. I am a fan of loosely-coupled interfaces, and so I prefer using services via the command pattern and startService()
.
Call startService in onCreate and then onStop
@Override
protected void onStop()
{
super.onStop();
if (!isChangingConfigurations ())
{
// call stopService
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With