Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android service for TCP Sockets

Based on a suggestion in a previous question I asked on here, I'm trying to push my socket connection for an application that I've written into a service. I spent the better part of the day yesterday researching services and actually mocked up a few (one remote, one local).

My question is in two parts:

1) after having played with both a local service and a remote service, I'm still not sure as to which one would be best for my situation. This is due in large part to the fact that I guess I still don't quite understand what advantages running in another 'process' is going to give me. I'm spawning a new thread for the socket connection no matter what so I won't have any thread contention with the UI. So what does putting the service in another process enable me to do? Will I potentially see better performance that way? My limited understanding is that by putting it in a different process, the service will run independently of whatever activity I have running on my app. I do have a few different activities, but only one of them requires the socket connection which I will rebuild everytime that activity is opened anyway. So would a local service be the way to go for me?

2) I'm going to have my socket "listener" (DataInputStream().readLine() inside a while loop) inside my service for any new data that gets passed down from the server. After the playing I did yesterday, I could not figure out how to pass the data that it reads to the actual "client" (either bound client by remote service, or local client itself) in "realtime".

Would greatly appreciate some suggestions for part 1, and some help with part 2 (code examples? :))

TIA

Edit: added code of my service - going with local service

Service Class:

   public class SocketService extends Service {

    Socket s;
    PrintStream os;

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return myBinder;
    }

    private final IBinder myBinder = new LocalBinder();

    public class LocalBinder extends Binder {
        public SocketService getService() {
            return SocketService.this;
        }
    }


    @Override
    public void onCreate() {
        super.onCreate();
        s = new Socket();
    }

    public void IsBoundable(){
        Toast.makeText(this,"I bind like butter", Toast.LENGTH_LONG).show();
    }

    public void onStart(Intent intent, int startId){
        super.onStart(intent, startId);
        Toast.makeText(this,"Service created ...", Toast.LENGTH_LONG).show();
        Runnable connect = new connectSocket();
        new Thread(connect).start();
    }

    class connectSocket implements Runnable {

        @Override
        public void run() {
            SocketAddress socketAddress = new InetSocketAddress("192.168.1.104", 4505);
            try {               
                s.connect(socketAddress);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        try {
            s.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        s = null;
    }
}

Activity that calls service:

public class SocketServiceController extends Activity {

        private SocketService mBoundService;
        private Boolean mIsBound;
        public SocketServiceController ssc;
       @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ssc = this;
            setContentView(R.layout.main);

            Button start = (Button)findViewById(R.id.serviceButton);
            Button stop = (Button)findViewById(R.id.cancelButton);

            start.setOnClickListener(startListener);
            stop.setOnClickListener(stopListener);

       }

       private ServiceConnection mConnection = new ServiceConnection() {
            public void onServiceConnected(ComponentName className, IBinder service) {
                mBoundService = ((SocketService.LocalBinder)service).getService();

            }
            public void onServiceDisconnected(ComponentName className) {
                mBoundService = null;
            }
        };

        private void doBindService() {
            bindService(new Intent(SocketServiceController.this, SocketService.class), mConnection, Context.BIND_AUTO_CREATE);
            mIsBound = true;
            mBoundService.IsBoundable();
        }


        private void doUnbindService() {
            if (mIsBound) {
                // Detach our existing connection.
                unbindService(mConnection);
                mIsBound = false;
            }
        }

        @Override
        protected void onDestroy() {
            super.onDestroy();
            doUnbindService();
        }


       private OnClickListener startListener = new OnClickListener() {
        public void onClick(View v){
            startService(new Intent(SocketServiceController.this,SocketService.class));
            doBindService(); 

        }               
       };

       private OnClickListener stopListener = new OnClickListener() {
            public void onClick(View v){
                stopService(new Intent(SocketServiceController.this,SocketService.class));
            }               
          };
}
like image 914
Kyle Avatar asked Sep 01 '10 14:09

Kyle


1 Answers

This is due in large part to the fact that I guess I still don't quite understand what advantages running in another 'process' is going to give me.

Generally, none. You create a remote service if you are expecting other applications to communicate with the service. If it will only be used by your own application, use a local service.

Also, a remote service has nothing to do with creating a separate process within your application.

Will I potentially see better performance that way?

You will see worse performance that way, due to extra memory consumption.

My limited understanding is that by putting it in a different process, the service will run independently of whatever activity I have running on my app.

Services have a lifecycle independent from activities regardless of whether it is local or remote.

So would a local service be the way to go for me?

Sounds likely.

After the playing I did yesterday, I could not figure out how to pass the data that it reads to the actual "client" (either bound client by remote service, or local client itself) in "realtime".

Use the local binding pattern, and have the activity call an API on the service to register (and unregister) an event listener. Have the service pass the data to the activity via the listener.

like image 121
CommonsWare Avatar answered Oct 20 '22 10:10

CommonsWare