Android Service详细介绍

       Service 服务是 Android 系统最常用的四大组件之一,在Android系统中,一是简化后台任务的实现,二是实现在同一台设备当中跨进程的远程信息通信。在Android开发中Service也是我们必备的知识,本文对Service知识进行了一些梳理和总结,相信通过本文能让你对Service有更清晰的了解和认识。废话不多说,现在开车啦。

 一、Service的概念

       Service的官方定义:Service(服务)是一个应用程序组件,可以在后台执行长时间运行的操作,不提供用户界面。另一个应用程序组件可以启动一个服务,它将继续在后台运行,即使用户切换到另一个应用程序。另外,一个组件可以绑定到一个服务来与它交互,甚至可以执行进程间通信(IPC)。例如,服务可能处理网络传输、播放音乐、文件I/O或者与内容提供者交互,这些都来自后台。

        这里要说明的是,Service虽然是在后台运行,但是Service默认并不会运行在子线程中,它也不运行在一个独立的进程中,它同样执行在UI主线程中,因此,不要在Service中执行耗时的操作,除非你在Service中创建了子线程来完成耗时操作。

         Service的运行不依赖于任何用户界面,即使程序被切换到后台或者用户打开另一个应用程序,Service仍然能够保持正常运行,这也正是Service的使用场景。当某个应用程序进程被杀掉时,所有依赖于该进程的Service也会停止运行。

二、Service的分类

按运行地点分类:

类别 区别  优点 缺点   应用
本地服务(Local) 该服务依附在主进程上  服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外Local服务因为是在同一进程因此不需要IPC,也不需要AIDL。相应bindService会方便很多。  主进程被Kill后,服务便会终止。  常见的应用如:音乐播放的服务。
远程服务(Remote) 该服务是独立的进程  服务为独立的进程,对应进程名格式为所在包名加上你指定的android:process字符串。由于是独立的进程,因此在Activity所在进程被Kill的时候,该服务依然在运行,不受其他进程影响,有利于为多个进程提供服务具有较高的灵活性。  该服务是独立的进程,会占用一定资源,并且使用AIDL进行IPC稍微麻烦一点。  一些提供系统服务的Service,这种Service是常驻的。

其中remote服务还是很少见的,并且一般都是系统服务。 

按运行类型分类:

类别 区别 应用
前台服务 会在通知一栏显示 ONGOING 的 Notification。 当服务被终止的时候,通知一栏的 Notification 也会消失,这样对于用户有一定的通知作用。常见的如音乐播放服务。
后台服务 默认的服务即为后台服务,即不会在通知一栏显示 ONGOING 的 Notification。 当服务被终止的时候,用户是看不到效果的。某些不需要运行或终止提示的服务,如天气更新,一些在后台同步的服务等。

按使用方式分类:

类别 区别
startService 启动的服务 主要用于启动一个服务执行后台任务,不进行通信。停止服务使用stopService
bindService 启动的服务 该方法启动的服务要进行通信。停止服务使用unbindService
startService 同时也 bindService 启动的服务 停止服务应同时使用stopService与unbindService

三、Servie的用法

1.新建一个类,继承自Service,如果是startService要重写onStartCommand方法,如果是bindService要实现它的onBind()方法。示例如下:

public class FirstService extends Service {
    private static final String TAG = "FirstService";
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "--------->onBind: Thread ID = " + Thread.currentThread().getId());
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "--------->onCreate:Thread ID = " + Thread.currentThread().getId());
    }
    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
       Log.e(TAG, "--------->onStartCommand:- startId = " + startId + ", Thread ID = " + Thread.currentThread().getId());
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "--------->onDestroy: Thread ID = " + Thread.currentThread().getId());
        super.onDestroy();
    }
}

2.接着在AndroidManifest.xml中注册Service

<application  
        android:allowBackup="true"  
        android:icon="@mipmap/ic_launcher"  
        android:label="@string/app_name"  
        android:supportsRtl="true"  
        android:theme="@style/AppTheme"> 
        <service android:name=".FirstService">  
        </service>  

    </application>  

3.在Activity或者其他组件中就可以通过startService或者bindService来启动Service。

四、Service生命周期

1.Android官方Service生命周期图:

        Android Service详细介绍

左边的图显示了使用startService()创建服务时的生命周期,右边的图表显示了使用bindService()创建服务时的生命周期。

2. Service 服务的常用方法说明:

方法  说明
void onCreate() 当Service被启动时被触发,无论使用Context.startServcie还是Context.bindService启动服务,在Service整个生命周期内只会被触发一次
int onStartCommand(Intent intent, int flags, int startId) 当通过Context.startService启动服务时将触发此方法,但当使用 Context.bindService 方法时不会触发此方法,其中参数 intent 是 startCommand 的输入对象,参数 flags 代表 service 的启动方式,参数 startId 当前启动 service 的唯一标式符。返回值决定服务结束后的处理方式,下文将再作详细说明。
void onStart(Intent intent,int startId) 2.0旧版本的方法,已被Android抛弃,不推荐使用,默认在onStartCommand 执行中会调用此方法
IBinder onBind(Intent intent) 使用 Context.bindService 触发服务时将调用此方法,返回一个IBinder 对象,在远程服务时可用于对 Service 对象进行远程操控
void onRebind(Intent intent) 当使用startService启动Service,调用bindService启动Service,且 onUnbind 返回值为 true 时,下次再次调用 Context.bindService 将触发方法
boolean onUnbind(Intent intent) 调用 Context.unbindService 触发此方法,默认返回 false, 当返回值 true 后,再次调用 Context.bindService 时将触发 onRebind 方法
void onDestory() 分三种情况:1.以Context.startService启动service,调用Context.stopService结束时触发此方法;2.以Context.bindService启动service,以Context.unbindService结束时触发此方法;3.先以Context.startService 启动服务,再用Context.bindService绑定服务,结束时必须先调用Context.unbindService解绑再使用Context.stopService结束service才会触发此方法。

3.详细说下onStartCommand 方法:

由于手机的RAM、内部资源有限,所以很多Service都会因为资源不足而被Kill掉,这时候返回值就决定了Service被Kill后的处理方式,一般 int onStartCommand(intent,flags,startId)的返回值分为以下几种:
START_STICKY
如果service进程被kill掉,系统会尝试重新创建Service,如果在此期间没有任何启动命令被传递到Service,那么参数intent将为NULL。
START_NOT_STICKY
使用这个返回值时,如果在执行完onStartCommand()后,服务被异常kill掉,系统不会自动重启该服务。
START_REDELIVER_INTENT
使用这个返回值时,如果在执行完onStartCommand()后,服务被异常kill掉,系统会自动重启该服务,并将intent的值传入。
START_STICKY_COMPATIBILITY

START_STICKY的兼容版本,但不保证服务被kill后一定能重启。

而输入参数flags正是代表此次onStartCommand()方法的启动方式,正常启动时,flags默认为0,被kill后重新启动,参数分为以下两种:
START_FLAG_RETRY
代表service被kill后重新启动,由于上次返回值为START_STICKY,所以参数 intent 为null
START_FLAG_REDELIVERY

代表service被kill后重新启动,由于上次返回值为START_REDELIVER_INTENT,所以带输入参数intent。

4.service生命周期方法详细调用的顺序:

(一)startServie的生命周期方法的调用顺序:

创建FirstService,并在Manifest里注册。然后在Activity里操作,代码如下:

public class FirstService extends Service {
    private static final String TAG = "FirstService";
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "--------->onBind: Thread ID = " + Thread.currentThread().getId());
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "--------->onCreate:Thread ID = " + Thread.currentThread().getId());
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
      Log.e(TAG, "--------->onStartCommand:- startId = " + startId + ", Thread ID = " +  Thread.currentThread().getId());
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "--------->onDestroy: Thread ID = " + Thread.currentThread().getId());
        super.onDestroy();
    }

}

在MainActivity中三次startService,之后stopService。

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i(TAG, "Thread ID = " + Thread.currentThread().getId());
        Log.i(TAG, "before StartService");
        //连续启动Service
        Intent intentOne = new Intent(this, FirstService.class);
        startService(intentOne);
        Intent intentTwo = new Intent(this, FirstService.class);
        startService(intentTwo);
        Intent intentThree = new Intent(this, FirstService.class);
        startService(intentThree);
        //停止Service
        Intent intentFour = new Intent(this, FirstService.class);
        stopService(intentFour);
        //再次启动Service
        Intent intentFive = new Intent(this, FirstService.class);
        startService(intentFive);
        Log.i(TAG, "after StartService");
    }

}

打印出的Log如下:

04-27 16:00:19.120 16775-16775/com.jiusi.equiview E/FirstService: --------->onCreate:Thread ID = 1
    --------->onStartCommand:- startId = 1, Thread ID = 1
04-27 16:00:19.130 16775-16775/com.jiusi.equiview E/FirstService: --------->onStartCommand:- startId = 2, Thread ID = 1
    --------->onStartCommand:- startId = 3, Thread ID = 1
    --------->onDestroy: Thread ID = 1
    --------->onCreate:Thread ID = 1
    --------->onStartCommand:- startId = 1, Thread ID = 1

分析:
a. 主线程打印出是1,所有回调方法中打印出的执行线程ID都是1,证明回调方法都是在主线程中执行的
b. 三次调用startService,只触发一次onCreate回调,触发了三次onStartCommand回调,且startId分别为1,2,3。证明 多次startService不会重复执行onCreate回调,但每次都会执行onStartCommand回调

(二)通过bindService启动Service,

(1)这种方式启动服务的特点:

1. bindService启动的服务和调用者之间是典型的client-server模式。调用者是client,Service则是server端。Service只有一个,但绑定到Service上面的client可以有一个或很多个。这里所提到的client指的是组件,比如某个Activity。
2. client可以通过IBinder接口获取Service的实例,从而实现在client端直接调用Service中的方法以实现灵活交互,这在通过startService方法启动中是无法实现的。
3. bindService启动服务的生命周期与其绑定的client息息相关。当client销毁时,client会自动与Service解除绑定。当然,client也可以明确调用unbindService()方法与Service解除绑定。当没有任何client与Service绑定时,Service就会自行销毁
(2)示例如下:
要想让Service支持bindService调用方式,需要做以下事情:
1.在实现的Service的onBind()方法中返回IBinder类型的实例。
2.onBInd()方法返回的IBinder的实例需要能够返回Service实例本身。通常,最简单的方法就是在service中创建binder的内部类,加入类似getService()的方法返回Service,这样绑定的client就可以通过getService()方法获得Service实例了。
代码如下:
public class SecondService extends Service {
    private static final String TAG = "SecondService";
    //client 可以通过Binder获取Service实例
    public class MyBinder extends Binder {
        public SecondService getService() {
            return SecondService.this;
        }
    }

    //通过binder实现调用者client与Service之间的通信
    private MyBinder binder = new MyBinder();
  
    @Override
    public void onCreate() {
        Log.e(TAG,"TestTwoService - onCreate - Thread = " + Thread.currentThread().getName());
        super.onCreate();
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
   Log.e(TAG,"TestTwoService-onStartCommand-startId="+startId+", Thread = " + Thread.currentThread().getName());
        return START_NOT_STICKY;
    }
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "TestTwoService - onBind - Thread = " + Thread.currentThread().getName());
        return binder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e(TAG, "TestTwoService - onUnbind - from = " + intent.getStringExtra("from"));
        return false;
    }
    @Override
    public void onDestroy() {
        Log.e(TAG, "TestTwoService - onDestroy - Thread = " + Thread.currentThread().getName());
        super.onDestroy();
    }
    //Service暴露出去供client调用的公共方法
    public int getRestult() {
        return 10;
    }
}

client端要做的事情:
1.创建ServiceConnection类型实例,并重写onServiceConnected()方法和onServiceDisconnected()方法。
2.当执行到onServiceConnected回调时,可通过IBinder实例得到Service实例对象,这样可实现client与Service的连接。
3.onServiceDisconnected回调被执行时,表示client与Service断开连接,在此可以写一些断开连接后需要做的处理。

创建Activity1,代码如下:

public class Activity1 extends Activity implements View.OnClickListener {
    private static final String TAG = "Activity1";
    private SecondService service = null;
    private boolean isBind = false;
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            isBind = true;
            SecondService.MyBinder myBinder = (SecondService.MyBinder) binder;
            service = myBinder.getService();
            Log.e(TAG, "Activity1 - onServiceConnected");
            int num = service.getRestult();
            Log.e(TAG, "Activity1 - result = " + num);
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            isBind = false;
            Log.e(TAG, "Activity1 - onServiceDisconnected");
        }
    };
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_1);
        Log.e(TAG, "Activity1 - onCreate - Thread = " + Thread.currentThread().getName());
        findViewById(R.id.startService).setOnClickListener(this);
        findViewById(R.id.stopService).setOnClickListener(this);
        findViewById(R.id.bindService).setOnClickListener(this);
        findViewById(R.id.unBindService).setOnClickListener(this);
        findViewById(R.id.satart2Activity).setOnClickListener(this);
        findViewById(R.id.finish).setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.startService) {
            //单击了“bindService”按钮
            Intent intent = new Intent(this, SecondService.class);
            intent.putExtra("from", "Activity1");
            Log.e(TAG, "----------------------------------------------------------------------");
            Log.e(TAG, "Activity1 执行 startService");
          startService(intent);
        }  else if (v.getId() == R.id.stopService) {
            //单击了“bindService”按钮
            Intent intent = new Intent(this, SecondService.class);
            intent.putExtra("from", "Activity1");
            Log.e(TAG, "----------------------------------------------------------------------");
            Log.e(TAG, "Activity1 执行 stopService");
            stopService(intent);
        } else if (v.getId() == R.id.bindService) {
            //单击了“bindService”按钮
            Intent intent = new Intent(this, SecondService.class);
            intent.putExtra("from", "Activity1");
            Log.e(TAG, "----------------------------------------------------------------------");
            Log.e(TAG, "Activity1 执行 bindService");
            bindService(intent, conn, BIND_AUTO_CREATE);
        } else if (v.getId() == R.id.unBindService) {
            //单击了“unbindService”按钮
            if (isBind) {
                Log.e(TAG,
                        "----------------------------------------------------------------------");
                Log.e(TAG, "Activity1 执行 unbindService");
                unbindService(conn);
            }
        } else if (v.getId() == R.id.satart2Activity) {
            //单击了“start ActivityB”按钮
            Intent intent = new Intent(this, Activity2.class);
            Log.e(TAG,
                    "----------------------------------------------------------------------");
            Log.e(TAG, "Activity1 启动 Activity2");
            startActivity(intent);
        } else if (v.getId() == R.id.finish) {
            //单击了“Finish”按钮
            Log.e(TAG,
                    "----------------------------------------------------------------------");
            Log.e(TAG, "Activity1 执行 finish");
            this.finish();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (isBind) {
            unbindService(conn);
        }
        Log.e(TAG, "Activity1 - onDestroy");
    }
}

创建Activity2,代码如下:
public class Activity2 extends Activity implements View.OnClickListener {
    private static final String TAG = "Activity2";
    private SecondService service = null;
    private boolean isBind = false;
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            isBind = true;
            SecondService.MyBinder myBinder = (SecondService.MyBinder) binder;
            service = myBinder.getService();
            Log.i(TAG, "Activity2 - onServiceConnected");
            int num = service.getRestult();
            Log.i(TAG, "Activity2 - result = " + num);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            isBind = false;
            Log.i(TAG, "Activity2 - onServiceDisconnected");
        }
    };

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_2);
        Log.i(TAG, "Activity2 - onCreate - Thread = " + Thread.currentThread().getName());

        findViewById(R.id.bindService).setOnClickListener(this);
        findViewById(R.id.unBindService).setOnClickListener(this);
        findViewById(R.id.finish).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.bindService) {
            //单击了“bindService”按钮
            Intent intent = new Intent(this, SecondService.class);
            intent.putExtra("from", "Activity2");
            Log.i(TAG, "----------------------------------------------------------------------");
            Log.i(TAG, "Activity2 执行 bindService");
            bindService(intent, conn, BIND_AUTO_CREATE);
        } else if (v.getId() == R.id.unBindService) {
            //单击了“unbindService”按钮
            if (isBind) {
                Log.i(TAG,
                        "----------------------------------------------------------------------");
                Log.i(TAG, "Activity2 执行 unbindService");
                unbindService(conn);
            }
        } else if (v.getId() == R.id.finish) {
            //单击了“Finish”按钮
            Log.i(TAG,
                    "----------------------------------------------------------------------");
            Log.i(TAG, "Activity2 执行 finish");
            this.finish();
        }
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "Activity2 - onDestroy");
    }
}

测试1,启动Activity1,点击bindService按钮,再点击unBindService,log输出如下:
04-27 16:55:06.260 21342-21342/com.jiusi.equiview E/Activity1: ----------------------------------------------------------------------
    Activity1 执行 bindService
04-27 16:55:06.270 21342-21342/com.jiusi.equiview E/SecondService: TestTwoService - onCreate - Thread = main
    TestTwoService - onBind - Thread = main
04-27 16:55:06.300 21342-21342/com.jiusi.equiview E/Activity1: Activity1 - onServiceConnected

04-27 16:57:24.380 21342-21342/com.jiusi.equiview E/Activity1: ----------------------------------------------------------------------
    Activity1 执行 unbindService
04-27 16:57:24.380 21342-21342/com.jiusi.equiview E/SecondService: TestTwoService - onUnbind - from = Activity1
    TestTwoService - onDestroy - Thread = main

调用bindService之后发生的事情:
1.client执行bindService()
2.如果Service不存在,则Service执行onCreate(),onBind()
3.client实例ServiceConnection执行onServiceConnected()方法

调用unbindService之后发生的事情:
1.client执行unbindService()
2.client与Service解除绑定连接状态
3.Service检测是否还有其他client与其连接,如果没有Service执行onUnbind()和onDestroy()

测试2 先点击Activity1的bindService按钮,再点击Activity1的Finish按钮,log输出:

04-27 17:08:34.400 25181-25181/com.jiusi.equiview E/Activity1: ----------------------------------------------------------------------

    Activity1 执行 bindService
04-27 17:08:34.410 25181-25181/com.jiusi.equiview E/SecondService: TestTwoService - onCreate - Thread = main
    TestTwoService - onBind - Thread = main
04-27 17:08:34.430 25181-25181/com.jiusi.equiview E/Activity1: Activity1 - onServiceConnected
    Activity1 - result = 10
04-27 17:09:10.080 25181-25181/com.jiusi.equiview E/Activity1: ----------------------------------------------------------------------
    Activity1 执行 finish
04-27 17:09:10.860 25181-25181/com.jiusi.equiview E/Activity1: Activity1 - onDestroy
04-27 17:09:10.860 25181-25181/com.jiusi.equiview E/SecondService: TestTwoService - onUnbind - from = Activity1
    TestTwoService - onDestroy - Thread = main
分析:如果client销毁,如果client没有与Service解除绑定,那么会报异常;client与Service先解除绑定就不会报异常。
测试3:step1: 点击Activity1的bindService按钮
step2: 点击Activity1的startActivity 1按钮,切换到Activity2
step3: 点击Activity2中的bindService按钮
step4: 点击Activity2中的unbindService按钮
step5: 点击Activity2中的Finish按钮
step6: 点击Activity1中的unbindService按钮
log输出:

04-27 17:32:08.210 29050-29050/com.jiusi.equiview E/Activity1: ----------------------------------------------------------------------
    Activity1 执行 bindService
04-27 17:32:08.210 29050-29050/com.jiusi.equiview E/SecondService: TestTwoService - onCreate - Thread = main
    TestTwoService - onBind - Thread = main
04-27 17:32:08.220 29050-29050/com.jiusi.equiview E/Activity1: Activity1 - onServiceConnected
    Activity1 - result = 10

04-27 17:33:45.080 29050-29050/com.jiusi.equiview E/Activity1: ----------------------------------------------------------------------
    Activity1 启动 Activity2
04-27 17:35:18.290 29050-29050/com.jiusi.equiview E/Activity2: ----------------------------------------------------------------------
    Activity2 执行 bindService
    Activity2 - onServiceConnected
    Activity2 - result = 10
04-27 17:38:27.750 30634-30634/com.jiusi.equiview E/Activity2: ----------------------------------------------------------------------
    Activity2 执行 finish
04-27 17:38:28.060 30634-30634/com.jiusi.equiview E/Activity2: Activity2 - onDestroy
04-27 17:39:07.470 30634-30634/com.jiusi.equiview E/Activity1: ----------------------------------------------------------------------
    Activity1 执行 unbindService
04-27 17:39:07.470 30634-30634/com.jiusi.equiview E/SecondService: TestTwoService - onUnbind - from = Activity1
    TestTwoService - onDestroy - Thread = main

总结bindService的生命周期:
1.点击ActivityA的bindService按钮
第一次调用bindService会实例化TestTwoService,然后执行其onBind()方法,得到IBinder类型的实例,将其作为参数传入ActivityA的ServiceConnection的onServiceConnected方法中,标志着Activity1与SecondService建立了绑定

2.点击Activity2中的bindService按钮
由于SecondService已处于运行状态,所以再次调用bindService不会重新创建它的实例,所以也不会执行SecondService的onCreate()方法和onBind()方法。Activity2与Activity1共享IBinder实例。此时有两个client与SecondService绑定

3.点击Activity2中的unbindService按钮
Activity2与SecondService解除了绑定,当没有任何client与Service绑定时,才会执行Service的onUnbind()方法。此时,Activity1还在绑定连接中,所以不会执行Service的解绑方法

4.点击Activity1中的unbindService按钮
Activity1执行unbindService之后,Activity1与SecondService就解除绑定了,这样就没有client与SecondService绑定,这时候Android会销毁SecondService,在销毁前会先执行SecondService的onUnbind()方法,然后才会执行其onDestroy()方法,这样SecondService就销毁了。

(三)通过startServie再bindService或者先bindService再startServie。

代码还是参考Activity1的代码,

1.先startServie,再bindService,log输出如下:

04-27 18:28:23.870 2479-2479/com.jiusi.equiview E/Activity1: ----------------------------------------------------------------------

    Activity1 执行 startService
04-27 18:28:23.880 2479-2479/com.jiusi.equiview E/SecondService: TestTwoService - onCreate - Thread = main

    TestTwoService - onStartCommand - startId = 1, Thread = main

04-27 18:29:29.050 2479-2479/com.jiusi.equiview E/Activity1: ----------------------------------------------------------------------
04-27 18:29:29.070 2479-2479/com.jiusi.equiview E/Activity1: Activity1 执行 bindService
04-27 18:29:29.070 2479-2479/com.jiusi.equiview E/SecondService: TestTwoService - onBind - Thread = main
04-27 18:29:29.100 2479-2479/com.jiusi.equiview E/Activity1: Activity1 - onServiceConnected

    Activity1 - result = 10

分析:onCreate方法只执行了一次,onStartCommand ->onBind ;

2.先bindService,再,log输出如下:startServie

04-27 18:37:25.910 4927-4927/com.jiusi.equiview E/Activity1: ----------------------------------------------------------------------
    Activity1 执行 bindService
04-27 18:37:25.920 4927-4927/com.jiusi.equiview E/SecondService: TestTwoService - onCreate - Thread = main
04-27 18:37:25.930 4927-4927/com.jiusi.equiview E/SecondService: TestTwoService - onBind - Thread = main
04-27 18:37:25.930 4927-4927/com.jiusi.equiview E/Activity1: Activity1 - onServiceConnected

    Activity1 - result = 10

04-27 18:38:06.320 4927-4927/com.jiusi.equiview E/Activity1: ----------------------------------------------------------------------
    Activity1 执行 startService

04-27 18:38:06.320 4927-4927/com.jiusi.equiview E/SecondService: TestTwoService - onStartCommand - startId = 1, Thread = main

分析:onCreate方法只执行了一次,onBind ->onStartCommand;

3.当startService和bindService后,再多次执行startService,log输出:

04-27 18:44:57.120 5851-5851/com.jiusi.equiview E/Activity1: ----------------------------------------------------------------------
    Activity1 执行 startService

04-27 18:44:57.130 5851-5851/com.jiusi.equiview E/SecondService: TestTwoService - onStartCommand - startId = 2, Thread = main

分析:和startService多次启动结果一样,onStartCommand执行了多次;

4.当startService和bindService后,再多次执行bindService,已经绑定的service不会再执行service的方法。

5.当startService和bindService后,执行stopService,log输出如下:

04-27 18:48:26.750 5851-5851/com.jiusi.equiview E/Activity1: ----------------------------------------------------------------------

    Activity1 执行 stopService

分析,并没有执行service的onDestroy方法,可见service并没有停止。

6.当startService和bindService后,执行unBindService,log输出如下:

04-27 18:50:12.410 7171-7171/com.jiusi.equiview E/Activity1: ----------------------------------------------------------------------
    Activity1 执行 unbindService
04-27 18:50:12.410 7171-7171/com.jiusi.equiview E/SecondService: TestTwoService - onUnbind - from = Activity1

分析,并没有执行service的onDestroy方法,只是执行了SecondService的onUnbind ,可见Service并没有停止。

7.当startService和bindService后,执行unBindService,再执行stopService; log输出如下:

04-27 19:02:45.320 8952-8952/com.jiusi.equiview E/SecondService: TestTwoService - onDestroy - Thread = main

分析,这个时候Service销毁了。

8.当startService和bindService后,执行stopService,再执行unBindService; log输出如下:

04-27 19:03:59.210 8952-8952/com.jiusi.equiview E/SecondService: TestTwoService - onUnbind - from = Activity1
    TestTwoService - onDestroy - Thread = main

分析,这个时候Service也被销毁了。

总结:如果即startService又bindService,必须要执行stopService和unBindService Service才会被销毁。

Service相关的知识基本就先总结到这里,在下一篇博客里会讲述Sevice其它方面的一些知识,如有不合理之处欢迎拍砖。