Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my Service started twice?

Why is my Service started twice? I am returning START_STICKY.

I install it from Eclipse using Run As, and am starting it in a windows console window:

D:\>adb shell am startservice --user 0 -a android.intent.action.MAIN -n "com.sandbox.mq/.MainService"
Starting service: Intent { act=android.intent.action.MAIN cmp=com.sandbox.mq/.MainService }

In the Logcat window, I see it has been run twice! :

09-07 21:49:19.427: D/MQ(14027): Hi, the system is up! Today is: Sep 7, 2014 9:49:19 PM
09-07 21:49:19.427: V/MQ(14027): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-07 21:49:19.427: V/MQ(14027): BackgroundThread0. Thread id = 866 sent message 0
09-07 21:49:19.427: V/MQ(14027): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-07 21:49:19.437: V/MQ(14027): BackgroundThread0. Thread id = 869 sent message 0
09-07 21:49:19.437: V/MQ(14027): MessageHandler on thread Thread id = 1 received message 0
09-07 21:49:19.437: V/MQ(14027): MessageHandler on thread Thread id = 1 received message 0

When I install from adb it is still started twice but output is different:

adb install MQ.apk

--

09-07 22:07:28.567: D/MQ(14642): Hi, the system is up! Today is: Sep 7, 2014 10:07:28 PM
09-07 22:07:28.567: V/MQ(14642): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-07 22:07:28.577: V/MQ(14642): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-07 22:07:28.577: V/MQ(14642): BackgroundThread0. Thread id = 872 sent message 0
09-07 22:07:28.577: V/MQ(14642): MessageHandler on thread Thread id = 1 received message 0

package com.sandbox.mq;

public class StartMainService extends Application {
    final static String TAG = "MQ";

    public void onCreate() {
        super.onCreate();
        Context context = getApplicationContext();
        Log.d(TAG, "Hi, the system is up! Today is: " + DateFormat.getDateTimeInstance().format(new Date()));
        Intent startServiceIntent = new Intent(context, MainService.class);
        context.startService(startServiceIntent);
    }
}

--

public class MainService extends Service {
    final static String TAG = "MQ";
    BackgroundThread0 bthread0;
    BackgroundThread1 bthread1;

    public class MqBinder extends Binder {
        public MqBinder(Context ctxt) {
            Log.v(TAG, "MqBinder() " + "Thread id = "
                    + Thread.currentThread().getId());
        }
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return new MqBinder(this);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.v(TAG, "onStartCommand(). I am INSIDE THE main sERVICE "
                + "Thread id = " + Thread.currentThread().getId());
        bthread0 = new BackgroundThread0();
        if (!bthread0.isAlive()) {
            bthread0.start();
        } else {
            Log.v(TAG, "onStartCommand(). bthread0 was already started");
        }
        bthread1 = new BackgroundThread1();
        if (!bthread1.isAlive()) {
            bthread1.start();
        } else {
            Log.v(TAG, "onStartCommand(). bthread1 was already started");
        }
        return START_STICKY;
    }

    private class BackgroundThread0 extends Thread {
        Handler b1Handler;

        @Override
        public void run() {
            super.run();
            b1Handler = bthread1.b1Handler;
            Message msg = b1Handler.obtainMessage(MessageHandler.TYPE0);
            b1Handler.sendMessage(msg);
            Log.v(TAG, "BackgroundThread0. " + "Thread id = "
                    + Thread.currentThread().getId() + " sent message "
                    + msg.what);
        }

    }

    private class BackgroundThread1 extends Thread {
        public BackgroundThread1() {
            super();
            b1Handler = new MessageHandler();
        }

        Handler b1Handler;

        @Override
        public void run() {
            super.run();
            Looper.prepare();
            Looper.loop();
        }

    }

    private static class MessageHandler extends Handler {
        static final int TYPE0 = 0;
        static final int TYPE1 = 1;
        static final int TYPE2 = 2;

        public MessageHandler() {

        }

        @Override
        public void handleMessage(Message msg) {
            Log.v(TAG, "MessageHandler on thread " + "Thread id = "
                    + Thread.currentThread().getId() + " received message "
                    + msg.what);

            switch (msg.what) {
            case TYPE0:
                break;
            case TYPE1:
                break;
            case TYPE2:
                break;
            }
            super.handleMessage(msg);
        }
    }
}

--

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.sandbox.mq" >

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

    <uses-sdk
        android:minSdkVersion="19"
        android:targetSdkVersion="19" />

    <application
        android:name="com.sandbox.mq.StartMainService"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:persistent="true"
        android:theme="@style/AppTheme" >
        <service android:name="com.sandbox.mq.MainService" android:exported="true"> 
             <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>          
        </service>        
    </application>

</manifest>

Update:

From Ian's answer below, when I comment out the startService call in onCreate, it is called only once.

09-08 09:29:10.393: D/MQ(4746): Hi, the system is up! Today is: Sep 8, 2014 9:29:10 AM
09-08 09:29:10.393: V/MQ(4746): onStartCommand(). I am INSIDE THE main sERVICE Thread id = 1
09-08 09:29:10.393: V/MQ(4746): BackgroundThread0. Thread id = 1050 sent message 0
09-08 09:29:10.393: V/MQ(4746): MessageHandler on thread Thread id = 1 received message 0

My original question is answered but I am wondering... Why does BackgroundThread1 have the same thread id as the main service thread id = 1?

like image 431
likejudo Avatar asked Sep 08 '14 02:09

likejudo


1 Answers

It starts twice because you start it twice:

  1. adb shell am startservice starts the service
  2. The process starts, triggering your Application's onCreate(), which also starts the service.

onStartCommand is called every time something starts your service. If you only want something to be done once for the lifecycle of your service, you should do it in your service's onCreate() method or check before doing the work again in onStartCommand (i.e., check if bthread0 is null before creating/starting it again).

like image 197
ianhanniballake Avatar answered Oct 20 '22 01:10

ianhanniballake