新建一个
day17_ServiceTest
空项目
一、定义一个服务
默认代码:
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
这个服务类是继承于Service
类的,其中必须实现抽象方法onBind()
服务中最常见的三个重写方法:
onCreate()
:创建时调用onStartCommand()
:启动时调用onDestroy()
:销毁时调用
服务也需要注册:
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
</service>
Exported
表示是否允许其他程序访问此服务Enabled
表示是否启用此服务
二、启动和停止服务
主布局:
<?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:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/start"
android:text="启动服务"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/stop"
android:text="关闭服务"/>
</LinearLayout>
主活动:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button_start = findViewById(R.id.start);
Button button_stop = findViewById(R.id.stop);
button_start.setOnClickListener(this);
button_stop.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.start:
Intent intent_start = new Intent(this, MyService.class);
startService(intent_start);
break;
case R.id.stop:
Intent intent_stop = new Intent(this, MyService.class);
stopService(intent_stop);
break;
default:
break;
}
}
}
首先new
一个Intent
出来,第二个参数是Service
实例,调用startService()
或stopService()
即可运行或停止服务
怎么样服务主动停止呢,只需要在服务类里调用stopSelf()
即可
修改服务:
public class MyService extends Service {
private static final String TAG = "MyService";
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: 创建服务");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: 启动服务");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: 销毁服务");
}
}
运行:
三、服务和活动通信
通信需要在服务中借助onBind()
方法,一般需要创建一个专门的Binder
对象管理。
模拟下载功能:
1、服务类
public class MyService extends Service {
private static final String TAG = "MyService";
private DownloadBinder mBinder = new DownloadBinder();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
......
class DownloadBinder extends Binder {
public void startDownload(){
Log.d(TAG, "startDownload: 开始下载");
}
public int getProgress(){
Log.d(TAG, "getProgress: 获取进度");
return 0;
}
}
}
2、主布局
<?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:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/bind_service"
android:text="绑定服务"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/unbind_service"
android:text="解绑服务"/>
</LinearLayout>
3、主活动
当活动和服务绑定以后,就可以调用服务里的Binder
提供的方法了
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private MyService.DownloadBinder downloadBinder;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
downloadBinder = (MyService.DownloadBinder) service;
downloadBinder.startDownload();
downloadBinder.getProgress();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button_start = findViewById(R.id.start);
Button button_stop = findViewById(R.id.stop);
button_start.setOnClickListener(this);
button_stop.setOnClickListener(this);
Button button_bind = findViewById(R.id.bind_service);
Button button_unbind = findViewById(R.id.unbind_service);
button_bind.setOnClickListener(this);
button_unbind.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.start:
Intent intent_start = new Intent(this, MyService.class);
startService(intent_start);
break;
case R.id.stop:
Intent intent_stop = new Intent(this, MyService.class);
stopService(intent_stop);
break;
case R.id.bind_service:
Intent intent_bind = new Intent(this, MyService.class);
bindService(intent_bind, connection, BIND_AUTO_CREATE); // 绑定服务
break;
case R.id.unbind_service:
unbindService(connection); // 解绑服务
break;
default:
break;
}
}
}
- 创建了
ServiceConnected
匿名类,重写了里面的onServiceConnected()
和onServiceDisconnected()
方法,这两个方法会在绑定成功和连接断开时调用 - 在
onServiceConnected()
将Service
向下转型为自定义的DownloadBinder
实例,然后用这个实例就能调用在DownloadBinder
中的任何方法【必须先绑定】 bindService()
可以将活动和服务绑定,第一个参数是Intent
对象【和服务联系起来】,第二个参数是创建好的ServiceConnection
实例【指定要绑定的服务】,第三个参数是一个标志位,传入BIND_AUTO_CREATE
表示绑定后自动创建服务【onCreate()
执行,onStartCommand()
不执行【即创建而不启动】】- 解绑
unBindService()
,参数就是绑定好的ServiceConnection
实例 - 一个服务可以与不同的活动绑定,绑定后会获取到相同的实例
4、运行
四、服务的生命周期
- 调用
Context.startService()
服务就会启动并回调onStartCommand()
方法,若服务还未创建过,就会先执行onCreate()
- 服务启动后一直处于运行状态,直到
Context.stopService()
或stopSelf()
被调用 - 每个服务都只会存在一个实例,不管调用多少次
startService()
,都只会存在一个实例,关闭只需一次 - 通过
Context.bindService()
获取服务的持久连接,就会回调服务的onBind()
方法,onBind()
返回一个IBinder
对象实例,就能实现自由通信了 - 调用
Context.stopService()
服务就会被销毁并回调onDestroy()
方法 - 类似的,被绑定的服务执行
unbindService()
也会被销毁,而且回调onDestroy()
- 如果一个服务既执行了
startService()
,也执行了bindService()
,那么,销毁这个服务就必须都执行stopService()
和unbindService()
才能被销毁,onDestroy()
才能被执行