Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run service not on main thread?

I'm trying to launch service and then open socket to have connection with server.

On button click I create new Thread and then start service.

Thread t = new Thread(){
        public void run(){
            mIntent= new Intent(MainActivity.this, ConnectonService.class);
            mIntent.putExtra("KEY1", "Value used by the service");
            context.startService(mIntent);
        }
    };
t.start();

Then on service, I try to open socket and have connection with server

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    //TODO do something useful


    try {
        InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
        socket = new Socket(serverAddr, SERVERPORT);
        Scanner scanner = new Scanner(socket.getInputStream());
        message = scanner.nextLine();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return Service.START_NOT_STICKY;
}

But when I call it, I have error

08-30 08:56:49.268: E/AndroidRuntime(3751): java.lang.RuntimeException: Unable to start service com.example.testofconnection.ConnectonService@40ef02a8 with Intent { cmp=com.example.testofconnection/.ConnectonService (has extras) }: android.os.NetworkOnMainThreadException*

I think problem is that service is on main thread, but I can't find how should I start service on new (independend) thread to keep connection alive?

like image 598
Ragaisis Avatar asked Aug 30 '13 06:08

Ragaisis


People also ask

How do I run a service from a different thread?

new Thread(new Runnable() { @Override public void run() { Intent intent=new Intent(getApplicationContext(), SensorService. class); startService(intent); } }). start(); this thread only start the service in different thread but service run in main thread.

Does service run on separate thread?

Caution: A service runs in the main thread of its hosting process; the service does not create its own thread and does not run in a separate process unless you specify otherwise.

Which service run on a separate worker thread?

IntentService. Like Service , IntentService runs on a separate thread, and stops itself automatically after it completes its work. IntentService is usually used for short tasks that don't need to be attached to any UI.

Can you start service from background thread?

A Service is an Android application component without a UI that runs on the main thread (of the hosting process). It also has to be declared in the AndroidManifest. xml. If you want the service code to run in a Background Thread, then you must manage that yourself.


2 Answers

You can use IntentService for this. Just launch it normally with an Intent from the main thread. onHandleIntent() method gets executed in background thread. Put your socket-code in there. Here is an example code.

public class MyIntentService extends IntentService {

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        // this method is called in background thread
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }    
}

In your activity you start the service as following.

startService(new Intent(this, MyIntentService.class));

If you need a long-lasting service, you can create a normal service and start a thread there. Here is an example. Make sure you launch it as "foreground" service. This will allow service to run longer without been killed by Android.

public class MyAsyncService extends Service {

    private AtomicBoolean working = new AtomicBoolean(true)

    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            while(working.get()) {
                // put your socket-code here
                ...
            }
        }
    }

    @Override
    public void onCreate() {

        // start new thread and you your work there
        new Thread(runnable).start();

        // prepare a notification for user and start service foreground
        Notification notification = ...
        // this will ensure your service won't be killed by Android
        startForeground(R.id.notification, notification);
    }

    @Override
    public onDestroy() {
        working.set(false)
    }
}
like image 195
sergej shafarenka Avatar answered Sep 22 '22 07:09

sergej shafarenka


Move this code to your thread:

try {
    InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
    socket = new Socket(serverAddr, SERVERPORT);
    Scanner scanner = new Scanner(socket.getInputStream());
    message = scanner.nextLine();
} catch (IOException e) {
    e.printStackTrace();
}

Just as an example (I'm not sure it this fits to your task):

Thread t = new Thread(){
        public void run(){
            try {
                InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
                socket = new Socket(serverAddr, SERVERPORT);
                Scanner scanner = new Scanner(socket.getInputStream());
                message = scanner.nextLine();
            } catch (IOException e) {
                e.printStackTrace();
            }

            mIntent= new Intent(MainActivity.this, ConnectonService.class);
            mIntent.putExtra("KEY1", "Value used by the service");
            context.startService(mIntent);
        }
    };
t.start();

You should know that a service is running on the UI thread, so you got this error. Check this nice site for more information about various threading approaches in Android.

like image 41
Trinimon Avatar answered Sep 24 '22 07:09

Trinimon