Service
1 Service 概述
service(服务)是安卓中的四大组件之一,它通常用作在后台处理耗时的逻辑,与Activity一样,它存在自己的生命周期,也需要在AndroidManifest.xml配置相关信息。
服务(Service)是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务。服务的运行不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序,服务仍然能够保持正常运行。
不过需要注意的是,服务并不是运行在一个独立的进程当中的,而是依赖于创建服务时所在的应用程序进程。与某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。另外.也不要被服务的后台概念所迷惑,实际上服务并不会自动开启线程,所有的代码都是默认运行在主线程当中的。也就是说,我们需要在服务的内部手动创建子线程,并在这里执行具体的任务,否则就有可能出现主线程被阻塞住的情况。
Service注意知识:
1、开发人员需要在应用程序配置文件中声明全部的service,使用
2、Service通常位于后台运行,它一般不需要与用户交互,因此Service组件没有图形用户 界面。Service组件需要继承Service基类。Service组件通常用于为其他组件提供后台服务或监控其他组件的运行状态。
2 Service服务分类
service分为两种:started(启动)、bound(绑定)。
service用于在后台完成用户指定的操作。service分为两种:
1)、started(启动):当应用程序组件(如activity)调用startService()方法启动服务时,服务处于started状态。
2)、bound(绑定):当应用程序组件调用bindService()方法绑定到服务时,服务处于bound状态。
Service是一个专门在后台处理长时间任务的Android组件,它没有UI。它有两种启动方式,startService和bindService。
startService 和 bindService 区别:
startService 特点:一旦服务开启跟调用者(开启者)就没有任何关系了。开启者退出了,开启者挂了,服务还在后台长期的运行。开启者不能调用服务里面的方法。
bindService 特点:bind的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉。绑定者可以调用服务里面的方法。(说白了就和小程序一样,打开的时候使用,用完了就关闭拍屁股走人,一次性滴)注意:绑定服务不会调用onstart()或者onstartcommand()方法
3 Service启动方式
Service启动方式,一个是启动服务,另一个是绑定服务。启动服务,服务启动后,用户没法跟其进行交互,直到服务自己主动结束调用onDestory()方法。一旦服务开启跟调用者(开启者)就没有任何关系了。开启者退出了,开启者挂了,服务还在后台长期的运行。开启者不能调用服务里面的方法。绑定服务,bind的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉。绑定者可以调用服务里面的方法。
启动服务与绑定服务的区别,startService()与bindService()区别:
1)、started service(启动服务)是由其他组件调用startService()方法启动的,这导致服务的onStartCommand()方法被调用。当服务是started状态时,其生命周期与启动它的组件无关,并且可以在后台无限期运行,即使启动服务的组件已经被销毁。因此,服务需要在完成任务后调用stopSelf()方法停止,或者由其他组件调用stopService()方法停止。
2)、使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。
4 自定义Service的两种主要启动方式
Service启动方式(主要是1,2两种):
1、startService 启动的服务:主要用于启动一个服务执行后台任务,不进行通信。停止服务使用stopService;
2、bindService 启动的服务:该方法启动的服务可以进行通信。停止服务使用unbindService;
3、startService 同时也 bindService 启动的服务:停止服务应同时使用stepService与unbindService
自定义service的启动应用步骤,1.自定义MyService,继承自Service;2.在配置文件里声明;3.start启动服务。
具体步骤如下:
1、自定义MyService,继承自Service;
public class MyService extends Service {
String tag = "060_MyService";
private LocalBinder binder = new LocalBinder();
/**
* 创建Binder对象,返回给客户端即Activity使用,提供数据交换的接口
*/
public class LocalBinder extends Binder {
// 声明一个方法,getService。(提供给客户端调用)
MyService getService() {
// 返回当前对象LocalService,这样我们就可在客户端端调用Service的公共方法了
return MyService.this;
}
}
/**
* 把Binder类返回给客户端
*/
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.e(tag, "MyService onBind");
return binder;
}
/**
* 重写Service生命周期
*/
int count = 0;
Timer timer = new Timer();
@Override
public void onCreate() {
super.onCreate();
Log.e(tag, "MyService onCreate");
/* 注册屏幕唤醒时的广播 */
IntentFilter mScreenOnFilter = new IntentFilter("android.intent.action.SCREEN_ON");
registerReceiver(mScreenOReceiver, mScreenOnFilter);
timer.schedule(new TimerTask() {
@Override
public void run() {
count++;
Log.e(tag,"count ++ : " + (count));
}
}, 100,1000);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(tag,"MyService onStartCommand invoke");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(tag, "MyService onDestroy ,count is :" + count);
unregisterReceiver(mScreenOReceiver);
}
private BroadcastReceiver mScreenOReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals("android.intent.action.SCREEN_ON")) {
Log.e(tag, "—— SCREEN_ON ——");
} else if (action.equals("android.intent.action.SCREEN_OFF")) {
Log.e(tag, "—— SCREEN_OFF ——");
}
}
};
@Override
public void onLowMemory(){
super.onLowMemory();
}
@Override
public void onTrimMemory(int level){
super.onTrimMemory(level);
}
/**
* 公共方法
* @return
*/
public int getCount(){
return 10;
}
}
2、在配置文件里声明
3、start启动方式 startservice方式
Intent it = new Intent(MyApplication.getContext(), MyService.class);
private void startservice() {
startService(it);
}
private void stopservice() {
stopService(it);
}
4、bind启动方式
private void bindservice() {
Log.e(tag, “绑定调用:bindservice”);
bindService(it, conn, Service.BIND_AUTO_CREATE);
}
private void unbindservice() {
Log.e(tag, “解除绑定调用:unbindService”);
// 解除绑定
if(mService!=null) {
mService = null;
unbindService(conn);
}
}
private void getdata() {
Log.e(tag, “获取数据:getdata”);
if (mService != null) {
// 通过绑定服务传递的Binder对象,获取Service暴露出来的数据
Log.e(tag, "从服务端获取数据:" + mService.getCount());
} else {
Log.e(tag, "还没绑定呢,先绑定,无法从服务端获取数据");
}
}
5 Service的生命周期
- Service作为 Android四大组件之一,应用非常广泛
- 本章将介绍 Service最基础的知识:生命周期
5.1 生命周期常用方法
官方说明图
在Service的生命周期里,常用的有:
4个手动调用的方法
手动调用方法
作用
startService()
启动服务
stopService()
关闭服务
bindService()
绑定服务
unbindService()
解绑服务
5个自动调用的方法
内部自动调用的方法
作用
onCreat()
创建服务
onDestroy()
销毁服务
onBind()
绑定服务
onUnbind()
解绑服务
5.2 生命周期方法具体介绍
主要介绍内部调用方法 & 外部调用方法的关系。
bindService
5.3 常见的生命周期使用
网站链接 : https://www.jianshu.com/p/8d0cde35eb10
6 Service具体使用
6.1 Service分类
6.2 Service特点
Service类型的详细介绍如下:
6.3 Service具体使用分析
6.3.1 本地Service
这是最普通、最常用的后台服务Service。
6.3.1.1 本地Service具体使用方法
-
步骤1:新建子类继承Service类
需重写父类的onCreate()、onStartCommand()、onDestroy()和onBind()方法 -
步骤2:构建用于启动Service的Intent对象
-
步骤3:调用startService()启动Service、调用stopService()停止服务
-
步骤4:在AndroidManifest.xml里注册Service
6.3.1.2 本地Service具体使用实例Demo
Demo代码链接 : https://github.com/Carson-Ho/Demo_Service.git -
步骤1:新建子类继承Service类
需重写父类的onCreate()、onStartCommand()、onDestroy()和onBind()
MyService.java
public class MyService extends Service {
//启动Service之后,就可以在onCreate()或onStartCommand()方法里去执行一些具体的逻辑
//由于这里作Demo用,所以只打印一些语句
@Override
public void onCreate() {
super.onCreate();
System.out.println(“执行了onCreat()”);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("执行了onStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
System.out.println("执行了onDestory()");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
- 步骤2:在主布局文件设置两个Button分别用于启动和停止Service
activity_main.xml
<Button
android:layout_centerInParent="true"
android:id="@+id/startService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="启动服务" />
<Button
android:layout_centerInParent="true"
android:layout_below="@+id/startService"
android:id="@+id/stopService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止服务" />
-
步骤3:构建Intent对象,并调用startService()启动Service、stopService停止服务
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {private Button startService;
private Button stopService;@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);startService = (Button) findViewById(R.id.startService); stopService = (Button) findViewById(R.id.stopService); startService.setOnClickListener(this); startService.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {//点击启动Service Button case R.id.startService: //构建启动服务的Intent对象 Intent startIntent = new Intent(this, MyService.class); //调用startService()方法-传入Intent对象,以此启动服务 startService(startIntent); //点击停止Service Button case R.id.stopService: //构建停止服务的Intent对象 Intent stopIntent = new Intent(this, MyService.class); //调用stopService()方法-传入Intent对象,以此停止服务 stopService(stopIntent); }
}
}
步骤4:在AndroidManifest.xml里注册Service
AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
//注册Service服务
<service android:name=".MyService">
</service>
</application>
Androidmanifest里Service的常见属性说明
属性
说明
备注
android:name
Service的类名
android:label
Service的名字
若是不设置,默认为Service
android:icon
Service的图标
android:permission
申明此Service的权限
有提供了该权限的应用才能控制或连接此服务
android:process
表示该服务是否在另一个进程中运行(远程服务)
不设置默认为本地服务;remote则设置成远程服务
android:enabled
系统默认启动
true: Service将会默认被系统启动;不设置则默认为false
android:exported
该服务是否能够被其他应用程序所控制或连接
不设置默认此项为 false
6.3.2 可通信的服务Service
-
上面介绍的Service是最基础的,但只能单机使用,即无法与Activity通信
-
接下来将在上面的基础用法上,增设“与Activity通信”的功能,即使用绑定Service服务(Binder类、bindService()、onBind()、unbindService()、onUnbind())
git地址: https://github.com/Carson-Ho/Demo_Service/tree/719e3b9ffd5017c334cdfdaf45b6a72776a2066a
6.3.2.1 可通信的服务Service具体实现
接下来我将用一个实例Demo进行可通信的服务Service说明 -
步骤1:在新建子类继承Service类,并新建一个子类继承自Binder类、写入与Activity关联需要的方法、创建实例
public class MyService extends Service {private MyBinder mBinder = new MyBinder();
@Override
public void onCreate() {
super.onCreate();
System.out.println(“执行了onCreat()”);
}@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println(“执行了onStartCommand()”);
return super.onStartCommand(intent, flags, startId);}
@Override
public void onDestroy() {
super.onDestroy();
System.out.println(“执行了onDestory()”);
}@Nullable
@Override
public IBinder onBind(Intent intent) {
System.out.println(“执行了onBind()”);
//返回实例
return mBinder;
}@Override
public boolean onUnbind(Intent intent) {
System.out.println(“执行了onUnbind()”);
return super.onUnbind(intent);
}//新建一个子类继承自Binder类
class MyBinder extends Binder {public void service_connect_Activity() { System.out.println("Service关联了Activity,并在Activity执行了Service的方法"); }
}
} -
步骤2:在主布局文件再设置两个Button分别用于绑定和解绑Service
<Button
android:layout_centerInParent="true"
android:id="@+id/startService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="启动服务" />
<Button
android:layout_centerInParent="true"
android:layout_below="@+id/startService"
android:id="@+id/stopService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止服务" />
<Button
android:layout_centerInParent="true"
android:layout_below="@id/stopService"
android:id="@+id/bindService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="绑定服务" />
<Button
android:layout_centerInParent="true"
android:layout_below="@id/bindService"
android:id="@+id/unbindService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="解绑服务"
/>
- 步骤3:在Activity通过调用MyBinder类中的public方法来实现Activity与Service的联系
即实现了Activity指挥Service干什么Service就去干什么的功能
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button startService;
private Button stopService;
private Button bindService;
private Button unbindService;
private MyService.MyBinder myBinder;
//创建ServiceConnection的匿名类
private ServiceConnection connection = new ServiceConnection() {
//重写onServiceConnected()方法和onServiceDisconnected()方法
//在Activity与Service建立关联和解除关联的时候调用
@Override
public void onServiceDisconnected(ComponentName name) {
}
//在Activity与Service解除关联的时候调用
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//实例化Service的内部类myBinder
//通过向下转型得到了MyBinder的实例
myBinder = (MyService.MyBinder) service;
//在Activity调用Service类的方法
myBinder.service_connect_Activity();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService = (Button) findViewById(R.id.startService);
stopService = (Button) findViewById(R.id.stopService);
startService.setOnClickListener(this);
stopService.setOnClickListener(this);
bindService = (Button) findViewById(R.id.bindService);
unbindService = (Button) findViewById(R.id.unbindService);
bindService.setOnClickListener(this);
unbindService.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
//点击启动Service
case R.id.startService:
//构建启动服务的Intent对象
Intent startIntent = new Intent(this, MyService.class);
//调用startService()方法-传入Intent对象,以此启动服务
startService(startIntent);
break;
//点击停止Service
case R.id.stopService:
//构建停止服务的Intent对象
Intent stopIntent = new Intent(this, MyService.class);
//调用stopService()方法-传入Intent对象,以此停止服务
stopService(stopIntent);
break;
//点击绑定Service
case R.id.bindService:
//构建绑定服务的Intent对象
Intent bindIntent = new Intent(this, MyService.class);
//调用bindService()方法,以此停止服务
bindService(bindIntent,connection,BIND_AUTO_CREATE);
//参数说明
//第一个参数:Intent对象
//第二个参数:上面创建的Serviceconnection实例
//第三个参数:标志位
//这里传入BIND_AUTO_CREATE表示在Activity和Service建立关联后自动创建Service
//这会使得MyService中的onCreate()方法得到执行,但onStartCommand()方法不会执行
break;
//点击解绑Service
case R.id.unbindService:
//调用unbindService()解绑服务
//参数是上面创建的Serviceconnection实例
unbindService(connection);
break;
default:
break;
}
}
}
6.3.3 前台服务Service
前台Service和后台Service(普通)最大的区别就在于:
-
前台Service在下拉通知栏有显示通知(如下图),但后台Service没有;
-
前台Service优先级较高,不会由于系统内存不足而被回收;后台Service优先级较低,当系统出现内存不足情况时,很有可能会被回收
前台服务具体用法如下:
用法很简单,只需要在原有的Service类对onCreate()方法进行稍微修改即可,如下图:
@Override
public void onCreate() {
super.onCreate();
System.out.println(“执行了onCreat()”);//添加下列代码将后台Service变成前台Service //构建"点击通知后打开MainActivity"的Intent对象 Intent notificationIntent = new Intent(this,MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this,0,notificationIntent,0); //新建Builer对象 Notification.Builder builer = new Notification.Builder(this); builer.setContentTitle("前台服务通知的标题");//设置通知的标题 builer.setContentText("前台服务通知的内容");//设置通知的内容 builer.setSmallIcon(R.mipmap.ic_launcher);//设置通知的图标 builer.setContentIntent(pendingIntent);//设置点击通知后的操作 Notification notification = builer.getNotification();//将Builder对象转变成普通的notification startForeground(1, notification);//让Service变成前台Service,并在系统的状态栏显示出来
}
测试结果
运行后,当点击Start Service或Bind Service按钮,Service就会以前台Service的模式启动(通知栏上有通知),如下图
6.3.4 远程服务,远程Service
详细讲解见链接:https://www.jianshu.com/p/34326751b2c6
6.3.4.1 远程服务与本地服务的区别
- 远程服务与本地服务最大的区别是:远程Service与调用者不在同一个进程里(即远程Service是运行在另外一个进程);而本地服务则是与调用者运行在同一个进程里
- 二者区别的详细区别如下图:
6.3.4.2 远程服务使用场景
多个应用程序共享同一个后台服务(远程服务)
即一个远程Service与多个应用程序的组件(四大组件)进行跨进程通信
使用场景如下图:
6.3.4.3 远程服务具体使用过程
-
为了让远程Service与多个应用程序的组件(四大组件)进行跨进程通信(IPC),需要使用AIDL
IPC:Inter-Process Communication,即跨进程通信
AIDL:Android Interface Definition Language,即Android接口定义语言;用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能。 -
在多进程通信中,存在两个进程角色(以最简单的为例):服务器端和客户端
-
以下是两个进程角色的具体使用步骤:
服务器端(Service)
步骤1:新建定义AIDL文件,并声明该服务需要向客户端提供的接口
步骤2:在Service子类中实现AIDL中定义的接口方法,并定义生命周期的方法(onCreat、onBind()、blabla)
步骤3:在AndroidMainfest.xml中注册服务 & 声明为远程服务
客户端(Client)
步骤1:拷贝服务端的AIDL文件到目录下
步骤2:使用Stub.asInterface接口获取服务器的Binder,根据需要调用服务提供的接口方法
步骤3:通过Intent指定服务端的服务名称和所在包,绑定远程Service
6.3.4.3 远程服务具体实例 -
实例描述:客户端远程调用服务器端的远程Service
-
具体使用:
服务端(Service)
新建一个服务器端的工程:Service - server
代码地址 : https://github.com/Carson-Ho/Service_Server
步骤1. 新建一个AIDL文件
步骤2. 在新建AIDL文件里定义Service需要与Activity进行通信的内容(方法),并进行编译(Make Project)
// 在新建的AIDL_Service1.aidl里声明需要与Activity进行通信的方法
package scut.carson_ho.demo_service;
interface AIDL_Service1 {
void AIDL_Service();
}
//AIDL中支持以下的数据类型
//1. 基本数据类型
//2. String 和CharSequence
//3. List 和 Map ,List和Map 对象的元素必须是AIDL支持的数据类型;
//4. AIDL自动生成的接口(需要导入-import)
//5. 实现android.os.Parcelable 接口的类(需要导入-import)
步骤3:在Service子类中实现AIDL中定义的接口方法,并定义生命周期的方法(onCreat、onBind()、blabla)
MyService.java
public class MyService extends Service {
// 实例化AIDL的Stub类(Binder的子类)
AIDL_Service1.Stub mBinder = new AIDL_Service1.Stub() {
//重写接口里定义的方法
@Override
public void AIDL_Service() throws RemoteException {
System.out.println("客户端通过AIDL与远程后台成功通信");
}
};
//重写与Service生命周期的相关方法
@Override
public void onCreate() {
super.onCreate();
System.out.println("执行了onCreat()");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("执行了onStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
System.out.println("执行了onDestory()");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
System.out.println("执行了onBind()");
//在onBind()返回继承自Binder的Stub类型的Binder,非常重要
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
System.out.println("执行了onUnbind()");
return super.onUnbind(intent);
}
}
步骤4:在AndroidMainfest.xml中注册服务 & 声明为远程服务
<service
android:name=“.MyService”
android:process=“:remote” //将本地服务设置成远程服务
android:exported=“true” //设置可被其他进程调用
>
//该Service可以响应带有scut.carson_ho.service_server.AIDL_Service1这个action的Intent。
//此处Intent的action必须写成“服务器端包名.aidl文件名”
</service>
至此,服务器端(远程Service)已经完成了。
客户端(Client)
新建一个客户端的工程:Service - Client
代码地址: https://github.com/Carson-Ho/Service_Client
步骤1:将服务端的AIDL文件所在的包复制到客户端目录下(Project/app/src/main),并进行编译
复制后的目录
步骤2:在主布局文件定义“绑定服务”的按钮
MainActivity.xml
<Button
android:layout_centerInParent="true"
android:id="@+id/bind_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="绑定服务"
/>
步骤3:在MainActivity.java里
-
使用Stub.asInterface接口获取服务器的Binder;
-
通过Intent指定服务端的服务名称和所在包,进行Service绑定;
-
根据需要调用服务提供的接口方法。
MainActivity.java
public class MainActivity extends AppCompatActivity {private Button bindService; //定义aidl接口变量 private AIDL_Service1 mAIDL_Service; //创建ServiceConnection的匿名类 private ServiceConnection connection = new ServiceConnection() { //重写onServiceConnected()方法和onServiceDisconnected()方法 //在Activity与Service建立关联和解除关联的时候调用 @Override public void onServiceDisconnected(ComponentName name) { } //在Activity与Service建立关联时调用 @Override public void onServiceConnected(ComponentName name, IBinder service) { //使用AIDLService1.Stub.asInterface()方法获取服务器端返回的IBinder对象 //将IBinder对象传换成了mAIDL_Service接口对象 mAIDL_Service = AIDL_Service1.Stub.asInterface(service); try { //通过该对象调用在MyAIDLService.aidl文件中定义的接口方法,从而实现跨进程通信 mAIDL_Service.AIDL_Service(); } catch (RemoteException e) { e.printStackTrace(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bindService = (Button) findViewById(R.id.bind_service); //设置绑定服务的按钮 bindService.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //通过Intent指定服务端的服务名称和所在包,与远程Service进行绑定 //参数与服务器端的action要一致,即"服务器包名.aidl接口文件名" Intent intent = new Intent("scut.carson_ho.service_server.AIDL_Service1"); //Android5.0后无法只通过隐式Intent绑定远程Service //需要通过setPackage()方法指定包名 intent.setPackage("scut.carson_ho.service_server"); //绑定服务,传入intent和ServiceConnection对象 bindService(intent, connection, Context.BIND_AUTO_CREATE); } }); }
}
测试结果
从上面测试结果可以看出:
- 打印的语句分别运行在不同进程(看语句前面的包名);
- 客户端调用了服务端Service的方法
即客户端和服务端进行了跨进程通信