2

I have an activity in which I start a service, for example I staty MyService as:

Intent intent1 = new Intent(this, MyService.class);
startService(intent1);

Inside my service I create a thread and run it. Here is part of my code:

public class MyService extends Service {
...
@Override
public void onStart(Intent intent, int startid) {
    Thread mythread= new Thread() {
        @Override
        public void run() {
            while(true)
            {
              ...
            }
        }
    };
    mythread.start();
}

}

Now instead of while(true) I want to use while(a), where a is a parameter that is passed from my activity to this service. Please note that my activity is a different class than my service. How can this be done? Please show specific example with some codes.

CloudyMarble
  • 36,908
  • 70
  • 97
  • 130
TJ1
  • 7,578
  • 19
  • 76
  • 119

5 Answers5

2

You can get access to your service by binding to it. Edit your service class so that it returns an IBinder onBind()

public class MyService extends Service {

    private static final String TAG = MyService.class.getSimpleName();
    private final IBinder binder = new ServiceBinder();
    private boolean a;

    @Override
    public IBinder onBind( Intent intent ) {

        return binder;
    }

    @Override
    public int onStartCommand( Intent intent, int flags, int startId ) {

        return super.onStartCommand( intent, flags, startId );
    }

    @Override
    public void onCreate() {

        super.onCreate();
    }

    public class ServiceBinder extends Binder {

        public MyService getService() {

            return MyService.this;
        }
    }

    public void setA(boolean a) {

        this.a = a;
    }
}

Now in your activity you need to handle binding and unbinding to your service. In this example, the service sticks around whether you are bound or not. If this is not the functionality you want, you can just not call startService(...):

public class MyActivity extends Activity {

    //...
    private MyService myService;
    private boolean bound;

    @Override    
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        Intent intent = new Intent( this, MyService.class );
        startService( intent );
        doBindService();
    }

    private final ServiceConnection serviceConnection = new ServiceConnection() {

        public void onServiceConnected( ComponentName className, IBinder service ) {

            myService = ( (MyService.ServiceBinder) service ).getService();
            bound = true;
        }

        public void onServiceDisconnected( ComponentName className ) {

            myService = null;
            bound = false;
        }
    };

    void doBindService() {

        boolean bound = bindService( new Intent( this, MyService.class ), serviceConnection, Context.BIND_AUTO_CREATE );
        if ( bound ) {

            Log.d( TAG, "Successfully bound to service" );
        }
        else {

            Log.d( TAG, "Failed to bind service" );
        }
    }

    void doUnbindService() {

        unbindService( serviceConnection );
    }
}

Now you have a reference to your bound service in your activity and you can just call myService.setA(true) to set your parameter.

James McCracken
  • 15,488
  • 5
  • 54
  • 62
  • Thanks for the response. When I modified the code as you suggested, as soon as I added the line `myService.setA(true)` to my main activity where I have a start button; when I click the start button the app crashes (Force close). Do you have any idea why? thanks again. – TJ1 Feb 06 '13 at 15:27
  • You need to check that you are successfully binding and that mService is not `null`. Do you have a logcat stack trace you can post? – James McCracken Feb 06 '13 at 22:38
  • To expand on that a little bit, it's not immediate that you bind to your service. You should implement some latch that waits until the bind succeeds before you try to call methods on that service. – James McCracken Feb 06 '13 at 23:52
  • Thanks for the response. Actually I tried to debug this and I see that *mService* is `null`. Do you know why is it `null`? – TJ1 Feb 07 '13 at 04:32
  • Did you step through `doBindService()` to make sure it is completing successfully? There's more documentation [here](http://developer.android.com/guide/components/services.html) and [here](http://developer.android.com/guide/components/bound-services.html) – James McCracken Feb 07 '13 at 14:46
  • I did, when I go inside the `doBindService()` it returns bound=true but myService is `null`. Also when I am at this line: `boolean bound = bindService( new Intent( this, MyService.class ), serviceConnection, Context.BIND_AUTO_CREATE );` when I try to step into in debugging mode I get this message that android.jar is not found! why is that? So I can not go inside `private final ServiceConnection serviceConnection = new ServiceConnection() {`. – TJ1 Feb 07 '13 at 16:24
  • You need to attach the android source code to be able to step into their classes when debugging. – James McCracken Feb 07 '13 at 18:40
  • Looking at the code can you see any reason why myService is null? Do I need to make it static or final? – TJ1 Feb 07 '13 at 21:50
1

Instead of calling start service use bindService which allows you access to the service object.

Here is a detailed topic about it Android Doc

Once your activity is bound to your service you can call from your activity any method from your service. you could do something like this:

.... Activity Code
          mService.stopThread();


..... Service Code
         public void stopThread(){
             a = false;
         }

Here is How I do it:

In your activity when you try to connect to the service :

    Intent serviceIntent = new Intent(this, MyService.class);
    bindService(serviceIntent, serviceConnection, BIND_AUTO_CREATE);

private ServiceConnection serviceConnection  = new ServiceConnection(){

    @Override
    public void onServiceConnected(ComponentName arg0, IBinder arg1) {
        mService = (MyService) ((MyService.LocalBinder) arg1)
                .getService();


    }

    @Override
    public void onServiceDisconnected(ComponentName arg0) {
        // TODO Auto-generated method stub
    }

};

And In my service : I add this member

private LocalBinder mBinder;


    protected void onCreate(Bundle bundle) {
               super.onCreate(bundle);
               mBinde = new LocalBinder();
         }

and this class:

public class LocalBinder extends Binder {
    public MyService getService() {
        // Return this instance of LocalService so clients can call public
        // methods
        return MyService.this;
    }
}
Mr.Me
  • 9,192
  • 5
  • 39
  • 51
1

Simple Use

Intent intent1 = new Intent(this, MyService.class);
intent1.putExtra("key",value);
startService(intent1);

and retrieve it in service using

 a = intent.getStringExtra("key");// or Int, ArrayList whatever
Sunny
  • 14,522
  • 15
  • 84
  • 129
1

I think service binding will be overkill for your case, since you have simple interaction between the activity and your service.

As suggested, you can pass the parameters using startService. Another solution, is to use LocalBroadcast, here is an example

Regarding your thread, you might need to define it as separate class in your service not anonymous class, for example:

class MyThread extends Thread{
   private boolean a = true;
   public void setA(boolean a){
      this.a = a;
   }
   public void run() {
        while(a)
        {
          ...
        }
    }

}
Community
  • 1
  • 1
iTech
  • 18,192
  • 4
  • 57
  • 80
0

If I have understood the question correctly, this is what you need:

In the activity class, right before calling startService(), add this line:

intent1.putExtra("keyName","keyValue");

In the service, in onStartCommand():

Bundle extras = intent.getExtras();
String param = extras.getString("keyName");

param will hold your parameter.

Zedot
  • 41
  • 3