i'm trying to write an android program where there are 2 service, one for bluetooth connection and another to call the method in bluetooth connection service. I'd like to know if i could bind these 2 services together, i tried but stuck
this code is from 2nd service when i tried to bind it to the bluetooth service
public class ActionHandler extends Service {
BTservice btService;
boolean mBound = false;
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
ActionHandler getService() {
// Return this instance of LocalService so clients can call public methods
return ActionHandler.this;
}
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return mBinder;
}
#Override
public int onStartCommand(Intent in, int flags, int startId) {
// TODO Auto-generated method stub
//Bind to Service
Intent intent = new Intent(this,BTservice.class);
bindService(intent,mConnection,Context.BIND_AUTO_CREATE);
return START_STICKY;
}
/** 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;
btService = binder.getService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}
eclipse said that btService type mismatch, what should i do?
Related
I am trying to constantly update the UI based on a long-running service output.
Basically, I want to display and append a list of users one by one after they get processed by the bound service.
MainActivityViewModel
public class MainActivityViewModel extends ViewModel {
private MutableLiveData<User> user = new MutableLiveData<>();
private MutableLiveData<MyService.MyBinder> mBinder = new MutableLiveData<>();
private ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder iBinder) {
MyService.MyBinder binder = (MyService.MyBinder) iBinder;
mBinder.postValue(binder);
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBinder.postValue(null);
}
};
public ServiceConnection getServiceConnection(){
return serviceConnection;
}
public LiveData<User> getUser(){
return user;
}
public LiveData<MyService.MyBinder> getBinder(){
return mBinder;
}
}
My Service
public class MyService extends Service {
private final IBinder mBinder = new MyBinder();
private Handler mHandler;
#Override
public void onCreate() {
super.onCreate();
mHandler = new Handler();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public void starFetchingUsers(User obj){
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
/**********************************************************/
Here i will be sending POST method one by one for 100 times and will get
a response as a user object which needs to be a liveData. So once this object
is changed after next post method, i want it to get displayed or appended on UI.
How to bind this dynamic user object variable to the MutableLiveData user created in MainActivityViewModel class? so this get auto updated in UI.
/**********************************************************/
}
});
thread.start();
}
public class MyBinder extends Binder{
MyService getService(){
return MyService.this;
}
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
stopSelf();
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
Please let me know what I am missing in both classes.
In my application I want to establish a TCP connection with a service and bind this service to every activity where it is needed. It gets started in my Login activity and everything is working like it should. Here is the code:
private TCPService mService;
private boolean mBound = false;
#Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, TCPService.class);
startService(intent);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
/** 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
TCPService.LocalBinder binder = (TCPService.LocalBinder)service;
mService = binder.getService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
Now I want to bind the service in another activity by using almost the same code just without startService(intent); But the mBound is never set to true and I can't access the service functions like it is intented.
Here is the implementation of the service:
public class TCPService extends Service {
private final IBinder myBinder = new LocalBinder();
public class LocalBinder extends Binder {
public TCPService getService() {
return TCPService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return myBinder;
}
}
What am I missing out? Is there anything I should check that may cause this behaviour?
Thanks in advance
How can I have something like this java code in Kotlin?
Even the IDE does not convert it to Kotlin perfectly!
/** 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;
}
};
I tried using inner class but then I was not able to use it like this:
#Override
protected void onStart() {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
You're creating an anonymous class here. In Kotlin, these are object expressions:
val connection = object: ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
//Something to do
}
override fun onServiceDisconnected(arg0: ComponentName) {
//Something to do
}
}
I have the following code being executed, I'm running this through a debugger and audioPlayerConnection.service is always null. Why may this be?
The various log calls don't always seem to be executed either (I guess this may have to do with the service being already starte).
Intent intent = new Intent(this, AudioPlayer.class);
AudioPlayerConnection audioPlayerConnection = new AudioPlayerConnection();
startService(intent);
bindService(intent, audioPlayerConnection, Context.BIND_AUTO_CREATE);
AudioPlayerConnection
public class AudioPlayerConnection implements ServiceConnection {
public IBinder service;
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
this.service = service;
Log.d("hmm", "audio service connected!!!");
}
#Override
public void onServiceDisconnected(ComponentName name) {
}
}
AudioPlayer
public class AudioPlayer extends Service {
public ArrayList<MediaPlayer> audioResources = new ArrayList<MediaPlayer>();
public AudioPlayer() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
Log.d("hmm", "audio service binded!!!");
return new AudioPlayerBinder();
}
public class AudioPlayerBinder extends Binder {
public void stopAll()
{
int i = 0;
for (MediaPlayer mp : audioResources)
{
mp.stop();
mp.release();
audioResources.remove(i);
i++;
}
}
public void add(Integer resourceId, boolean loop)
{
MediaPlayer mp = MediaPlayer.create(null, resourceId);
if (loop)
{
mp.setLooping(true);
audioResources.add(mp);
}
mp.start();
}
}
}
You're declaring audioPlayerService in the local scope where you are calling bindService(). The call to bindService is asynchronous, and onServiceConnected() is not being called before you are (presumably) trying to use audioPlayerConnection as if the Service was already bound.
How to pass handler from an activity to service? I am trying to update the activity UI on the state of Bluetooth connection by using Handler as shown below from service class.
mHandler.obtainMessage(MenuActivity.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
In the activity, I implemented this:
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_STATE_CHANGE:
if (true)
Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
switch(msg.arg1){
case BluetoothService.STATE_CONNECTED:
showToast("Connected to " + mConnectedDeviceName, Toast.LENGTH_SHORT);
break;
I tried to use a constructor to pass the handler from the activity to service like this:
public BluetoothService(Handler handler, BluetoothAdapter mBluetoothAdapter) {
mAdapter = mBluetoothAdapter;
mState = STATE_NONE;
mHandler = handler;
}
But there was an error which shows Unable to instantiate service and found that the service needs to have a public no-args constructor. But after removing the constructor, the handler did not get passed into the service.
How to solve this problem?
You have to bind to the service from activity and establish a ServiceConnection and then get the instance of service and set your handler.
Here is the activity and service class which i use for one of my media player application.....
public class MainActivity extends Activity
{
private CustomService mService = null;
private boolean mIsBound;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
startService(new Intent(this.getBaseContext(), CustomService.class));
doBindService();
}
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder)
{
mService = ((CustomService.LocalBinder)iBinder).getInstance();
mService.setHandler(yourHandler);
}
#Override
public void onServiceDisconnected(ComponentName componentName)
{
mService = null;
}
};
private void doBindService()
{
// Establish a connection with the service. We use an explicit
// class name because we want a specific service implementation that
// we know will be running in our own process (and thus won't be
// supporting component replacement by other applications).
bindService(new Intent(this,
CustomService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
private void doUnbindService()
{
if (mIsBound)
{
// Detach our existing connection.
unbindService(mConnection);
mIsBound = false;
}
}
#Override
protected void onDestroy()
{
super.onDestroy();
doUnbindService();
}
}
CustomService Code ....
public class CustomService extends Service
{
private final IBinder mIBinder = new LocalBinder();
private Handler mHandler = null;
#Override
public void onCreate()
{
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flag, int startId)
{
return START_STICKY;
}
#Override
public void onDestroy()
{
if(mHandler != null)
{
mHandler = null;
}
}
#Override
public IBinder onBind(Intent intent)
{
return mIBinder;
}
public class LocalBinder extends Binder
{
public CustomService getInstance()
{
return CustomService.this;
}
}
public void setHandler(Handler handler)
{
mHandler = handler;
}
}