Service服务

服务是安卓四大组件之一,能够长期运行在后台,且不需要提供用户界面;服务的状态与开启者没有关系

服务的创建

  • startService() 直接开启

通过startService()启动,需要调stopService()才能停止

  • bindService () 绑定开启

通过bindService()绑定,需要与unbindService()解绑后,服务才被销毁

官方解释

  服务的整个生命周期从调用 onCreate() 开始起,到 onDestroy() 返回时结束。与 Activity 类似,服务也在 onCreate() 中完成初始设置,并在 onDestroy() 中释放所有剩余资源。例如,音乐播放服务可以在 onCreate() 中创建用于播放音乐的线程,然后在 onDestroy() 中停止该线程。
  无论服务是通过 startService() 还是 bindService() 创建,都会为所有服务调用 onCreate() 和 onDestroy() 方法。
  服务的有效生命周期从调用 onStartCommand() 或 onBind() 方法开始。每种方法均有 Intent 对象,该对象分别传递到 startService() 或 bindService()。
  对于启动服务,有效生命周期与整个生命周期同时结束(即便是在 onStartCommand() 返回之后,服务仍然处于活动状态)。对于绑定服务,有效生命周期在 onUnbind() 返回时结束。

服务的生命周期

有五种方法

  • onCreate()创建

  • onStartCommand() 开始

  • onDestroy()销毁

  • onBind() 绑定

  • onUnbind() 解绑

三种状态

  • 启动
    startService() 启动服务,处于“启动”状态,启动后不管启动服务的组件是否销毁,服务依然运行
  • 绑定
    bindService() 绑定服务,处于“绑定”状态,服务只会在组件与其绑定时运行
  • 启动且绑定
    调用onStartCommand()onBind(),处于“启动且绑定”状态

1.在整个生命周期内,只有onstartCommand()能被多次调用,绑定和解绑都只能调用一次
2.绑定后没有解绑,无法使用stopService()将其停止
3.如果已经onCreate(),那么startService()将调用startCommand()
4.如果是以bindService开启,那么使用unbindService时就会自动调用onDestroy销毁

服务的通讯

服务的必须以绑定服务形式才能通讯

  • 本地服务通讯:应用内的通讯
  • 远程服务通讯:应用之间的通讯

服务例子

模拟两种服务

样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >


<Button
android:id="@+id/start_service1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="start1"
android:text="直接开启" />

<Button
android:id="@+id/stop_service1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="stop1"
android:text="结束" />

<Button
android:id="@+id/start_service2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="start2"
android:text="绑定开启" />

<Button
android:id="@+id/stop_service2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="stop2"
android:text="结束" />

</LinearLayout>

Activity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.example.musicplayer;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startService1 = (Button) findViewById(R.id.start_service1);
Button stopService1 = (Button) findViewById(R.id.stop_service1);
Button startService2 = (Button) findViewById(R.id.start_service2);
Button stopService2 = (Button) findViewById(R.id.stop_service2);
}

public void start1(View view){
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
}
public void stop1(View view){
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
}

private ServiceConnection connection = new ServiceConnection() {
private MyService.MyBinder myBinder;
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myBinder = (MyService.MyBinder) service;
myBinder.dosomething();
}
};
public void start2(View view){
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE);
}
public void stop2(View view){
unbindService(connection);
}


}

服务类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.example.musicplayer;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class MyService extends Service {
private MyBinder mBinder = new MyBinder();
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "onCreate()", Toast.LENGTH_SHORT).show();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "onStartCommand()", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent, flags, startId);
}

@Override
public void onDestroy() {
super.onDestroy();
Log.e("日志", "已清除");
}

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

class MyBinder extends Binder {
public void dosomething(){
Log.e("日志", "服务被activity调用");
}
}
}

manifest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dist="http://schemas.android.com/apk/distribution"
package="com.example.musicplayer">

<dist:module dist:instant="true" />

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

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="服务示例"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>

<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

结果