在 Android四大组件之service(一) 文中我们讲到了 service 的 基本概念 和 startService 启动方式、stopService。
不过这种方式是有个缺点,我们无法调用 FirstService 类里面的方法。
这个时候有人会说 new FirstService() 不就好了吗?其实不然,作为四大组件,你是不能直接new的,必须由系统创建,并服务他们context(即上下文)。下面,我们就来讲一下另外一种启动服务的方式。bindService() / unBindService()
第一步:继承 Binder 编写 InnerBinder 类
public class InnerBinder extends Binder {
public void callServiceInnerMethod() {
sayHello();
}
}
第二步:在重写的 onBind() 方法中返回 InnerBinder 实例
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new InnerBinder();
}
第三步:编写 ServiceConnection
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected....");
mRemoteBinder = (FirstService.InnerBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected....");
mRemoteBinder = null;
}
};
第四步:绑定服务
public void bindServiceClick(View view) {
Intent intent = new Intent();
intent.setClass(this, FirstService.class);
isServiceBinded = bindService(intent, mConnection, BIND_AUTO_CREATE);
}
第五步:解绑服务
public void unBindServiceClick(View view) {
if (mConnection != null && isServiceBinded) {
unbindService(mConnection);
isServiceBinded = false;
}
}
完整代码
MainActivity.java
package com.wust.testdemo;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import services.FirstService;
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
private boolean isServiceBinded;
private FirstService.InnerBinder mRemoteBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "onCreate");
}
public void startServiceClick(View view) {
Intent intent = new Intent();
intent.setClass(this, FirstService.class);
startService(intent);
}
public void stopServiceClick(View view) {
Intent intent = new Intent();
intent.setClass(this, FirstService.class);
stopService(intent);
}
public void callServiceMethod(View view) {
Log.d(TAG, "call service inner method");
mRemoteBinder.callServiceInnerMethod();
}
public void bindServiceClick(View view) {
Intent intent = new Intent();
intent.setClass(this, FirstService.class);
isServiceBinded = bindService(intent, mConnection, BIND_AUTO_CREATE);
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected....");
mRemoteBinder = (FirstService.InnerBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected....");
mRemoteBinder = null;
}
};
public void unBindServiceClick(View view) {
if (mConnection != null && isServiceBinded) {
unbindService(mConnection);
isServiceBinded = false;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
}
}
FirstService.java
package services;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.Nullable;
/**
* ClassName: FirstService <br/>
* Description: <br/>
* date: 2021/10/17 21:44<br/>
*
* @author yiqi<br />
* @QQ 1820762465
* @微信 yiqiideallife
* @技术交流QQ群 928023749
*/
public class FirstService extends Service {
private static final String TAG = FirstService.class.getClass().getSimpleName();
public class InnerBinder extends Binder {
public void callServiceInnerMethod() {
sayHello();
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind....");
return new InnerBinder();
}
@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...");
}
private void sayHello() {
Toast.makeText(this, "Hello!", Toast.LENGTH_SHORT).show();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:onClick="startServiceClick"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开启服务"/>
<Button
android:onClick="stopServiceClick"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="停止服务"/>
<Button
android:onClick="bindServiceClick"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="绑定服务"/>
<Button
android:onClick="unBindServiceClick"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="解绑服务"/>
<Button
android:onClick="callServiceMethod"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="调用服务内部方法"/>
</LinearLayout>
效果展示
两种启动方式的优缺点
- startService的方法可以长期在后台运行,而 bindService 的方法则不可以长期在后台运行。
- bindService启动服务,可以跟服务进行通讯,但是startService启动服务不可以跟服务进行通讯。
- bindService启动服务,在软件退出时一定要记住 unBindService() 服务,要不然会报错