为什么我的服务开始两次?

时间:2014-09-08 02:56:38

标签: java android android-service

为什么我的服务启动了两次?我正在返回START_STICKY。

我使用Run As从Eclipse安装它,并在Windows控制台窗口中启动它:

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 }

在Logcat窗口中,我看到它已经运行了两次! :

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

当我从adb安装时,它仍然是 开始两次但输出不同:

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

包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>

更新

从Ian的回答中,当我在onCreate中注释掉startService调用时,它只被调用一次。

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

我的原始问题已经回答,但我想知道...为什么BackgroundThread1与主服务线程id = 1具有相同的线程ID?

3 个答案:

答案 0 :(得分:9)

它启动两次因为你启动它两次:

  1. adb shell am startservice启动服务
  2. 此过程开始,触发您的Application onCreate(),同时启动该服务。
  3. 每次启动服务时都会调用

    onStartCommand。如果您只想在服务的生命周期中执行一次某些操作,则应在服务的onCreate()方法中执行此操作,或在onStartCommand中再次执行工作之前进行检查(即,检查如果在创建/再次启动它之前bthread0为null)。

答案 1 :(得分:1)

我解决了这个问题,只需将启动服务的意图移动到我的MainActivity,就像评论部分中提到的ianhanniballake一样。我希望它可以帮助其他人:)

答案 2 :(得分:0)

我遇到了同样的问题,并通过放置来解决了问题

START_NOT_STICKY

代替

START_STICKY