Service是一个需要长期运行但不需要界面与用户交互的组件,其作用是告知系统有后台任务需要执行以及将自身应用程序的一些功能暴露给其他应用程序供其使用。
特点:若无特别指定,则service运行在创建服务的应用程序的进程中,且所有代码默认都在主线程中运行。
private ServiceConnection serviceConnection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
其中,ComponentName为与service绑定的组件名,IBinder为onBind()返回的对象,包含了暴露出来的可以操作service的方法,一个service只存在一个binder实例。onServiceConnected()方法在onBind()执行成功并返回非空IBinder对象之后被调用,onServiceDisconnected()方法在断开连接时调用,但主动解绑不会调用。注:如果activity销毁,则activity与service之间的绑定关系也销毁,当service没有和任何component绑定,且不是通过startService()方法启动时,service会自动销毁。
android系统中每个应用程序都运行在自己独立的进程中,每个进程有一个虚拟机的实例,而且一个应用程序中的service组件默认是运行在所属应用程序的进程中,但若有其他需求,service也可以设置android:process属性指定独立的进程。如果应用程序中的activity需要与本应用程序中运行在独立进程中的service进行通信或者与其他应用程序中的service进行通信,则会涉及到跨进程通信的问题。
应用程序运行在用户空间,但由于进程隔离的缘故,所以不同应用程序之间不能相互访问,而系统内核运行在内核空间,是一片公共但相对独立的空间。应用程序不能随意访问内核空间,但能通过系统调用的方式在受控制的前提下进行访问,这给跨进程通信提供了机会。其中,系统调用指的是Linux内核中设置的一组用于实现各种系统功能的子程序,即由系统提供的函数,运行于内核态。用户可以通过系统调用命令在自己的应用程序中调用它们。
无论是用户空间还是内核空间,使用的都是虚拟地址空间,并不能直接访问物理空间。 且每开启一个进程,32位系统就会分配一个4G大小的虚拟地址空间,linux系统将其中3G作为该进程的用户空间,而剩下的1G作为内核空间。对于每一个进程来说,它认为自己占用了系统所有的内存空间,空间地址都是从0开始。
binder驱动不属于系统内核,但由于linux的特性,即可加载内核模块,使得利用binder实现跨进程通信成为可能。可加载内核模块指的是一个具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行。例如,当系统需要安装新的设备驱动程序(如视频卡,蓝牙设备或USB设备),文件系统驱动程序,甚至系统扩展,必须将这些驱动程序嵌入内核中才能完全正常运行。在某些情况下,要添加驱动程序,必须重建、编辑和重新引导整个内核,但是Linux能够在不经过整个过程的情况下向内核添加一些模块,即可加载内核模块。
binder的实现方式是在service中创建binder对象,并将service中的一些可供其他应用或组件使用的方法暴露在binder对象中,当其他应用或组件需要调用service中的方法时,可以向service发送请求,service收到请求后将自身的binder对象的引用返回,供其他应用或组件使用,但实际上该binder引用中只包含了方法的声明,并没有具体功能的实现,当其他应用或组件需要调用service方法时,该binder引用只是负责收集参数并传输给service manager,service manager找到实际的binder对象所在service,并告知service调用binder对象执行相应的方法,将结果返回给binder引用,看上去就像binder引用去计算并返回的结果一样。除非service和发送请求的应用或组件在同一进程,此时返回的是binder实体。 service中有一个binder实体,而在应用程序或组件内部中有一个binder引用,该引用可看作是该binder实体的代理。在binder引用未接收到返回结果之前,应用或组件中发送调用请求的线程一直会处于阻塞状态。 其具体实现过程如下。
binder机制主要由四部分构成,Client、Server、Service Manager和Binder驱动程序。其中,发送请求的应用或组件作为client,提供功能的service作为server,而binder驱动程序建立通讯、传递binder对象等提供底层实现,service manager主要是为识别和匹配client想要的那个binder对象,具体如下:
server创建binder并将自身功能暴露其中供client使用,但系统中不止一个server能提供binder,这就需要一个标识来区分各自提供的binder,该标识需要给应用开发人员使用,所以需要简单好记,而service manager的作用就是将这种标识和binder对象关联起来,并由系统统一管理,以免出现混淆。只要server要提供binder,就需要在service manager中进行注册。而client要请求某个binder,就需要service manager对标识进行解析。
但是service manager并不运行在client或者是server进程中,而是独立运行在一个进程。那server向service manager注册binder、client经过service manager调用binder就涉及IPC,这样又需要使用binder与service manager进行通信,即binder注册后client才能找到自己想要的那个binder,而注册binder又需要使用binder。而这个binder是系统中用于server或者client与service manager进行通讯的,为此,需要有个binder不需要注册就能让server和client找到。所以,系统就在内部预先创建并规定了这样一个binder,专门供server和client与service manager通信使用。
binder机制中使用的接口语言,可以通过Android SDK的 platform-tools目录下的aidl.exe工具自动生成,在android studio中需要在main文件夹下新建aidl文件夹(与java文件夹同级),并在该文件夹下创建 .aidl文件。该文件中接口和方法前面不要加访问权限修饰符,也不能用static、final。AIDL默认支持Java基本类型,String,List,Map,CharSequence,除此之外的其他类型都需要import声明,对于使用自定义类型作为参数或者返回值,自定义类型需要实现Parcelable接口, 且需要显式import,即便二者在同一个包中。
// IMyAidlInterface.aidl
package com.example.myapplication;
// Declare any non-default types here with import statements
interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
int basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString);
}
package com.example.myapplication;
// Declare any non-default types here with import statements
public interface IMyAidlInterface extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.example.myapplication.IMyAidlInterface
{
...
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
public int basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;
}
该文件在创建aidl文件并编译后会自动生成在build/generated/路径中的某个文件夹下。该java文件包含一个stub的抽象内部类以及在aidl文件中声明的方法,该方法不用具体实现。IInterface的作用就是声明server暴露出来供client调用的相关功能。
3. stub抽象内部类
public static abstract class Stub extends android.os.Binder implements com.example.myapplication.IMyAidlInterface
{
private static final java.lang.String DESCRIPTOR = "com.example.myapplication.IMyAidlInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.example.myapplication.IMyAidlInterface interface,
* generating a proxy if needed.
*/
public static com.example.myapplication.IMyAidlInterface asInterface(android.os.IBinder obj)
{
...
}
@Override
public android.os.IBinder asBinder()
{
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
...
}
private static class Proxy implements com.example.myapplication.IMyAidlInterface
{
...
}
static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
IMyAidlInterface .stub类是个抽象类,继承Binder类并实现aidl定义的接口。stub的作用是在server中创建stub的子类去实现IInterface中声明的方法,将自身的功能暴露出来,该子类作为server的binder实体。在创建stub子类时会调用stub的构造方法,根据stub内置的DESCRIPTOR,将stub子类attach到IInterface。aidl接口中声明的方法在stub存在一个函数编号TRANSACTION_basicTypes,与声明的方法basicTypes()一一对应。
4. asInterface
public static com.example.myapplication.IMyAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.myapplication.IMyAidlInterface))) {
return ((com.example.myapplication.IMyAidlInterface)iin);
}
return new com.example.myapplication.IMyAidlInterface.Stub.Proxy(obj);
}
该方法的作用是可以在client中调用bindService(intent, serviceconnection, flag)绑定service时,传入的serviceconnection中的onServiceConnected(componentName, IBinder)回调函数中进行使用,接收binder驱动传来的binder,并将其转化为IInterface类型。在转化成IInterface的过程中,先调用binder的queryLocalInterface()在本地查找IInterface,如果这个binder是本地实体,即在本地创建了stub的子类对象(构造方法中会将stub对象与DESCRIPTOR 关联,DESCRIPTOR 为IInterface的全类名),则可以从本地找到对应的IInterface并返回,如果不是,则需要new一个stub.Proxy对象返回。
5. stub.Proxy
private static class Proxy implements com.example.myapplication.IMyAidlInterface
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override
public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
@Override
public int basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(anInt);
_data.writeLong(aLong);
_data.writeInt(((aBoolean)?(1):(0)));
_data.writeFloat(aFloat);
_data.writeDouble(aDouble);
_data.writeString(aString);
mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
Proxy是stub的静态内部类,实现了IInterface,构造方法接收binder并对成员变量进行赋值。其中,Proxy对IInterface的实现是将基本类型写入parcel中,并调用binder代理的transact( code, parcel, parcel, flag) 方法将封装的parcel通过binder驱动传递出去,并调用server中的binder实体(即stub的子类)中的onTransact()方法,其中,flag表示运行方式,0——RPC(remote procedure call)表示在没有获得返回数据前将线程阻塞,FLAG_ONEWAY表示发送完请求后直接返回,不等待返回结果 。
6. onTransact
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_basicTypes:
{
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
long _arg1;
_arg1 = data.readLong();
boolean _arg2;
_arg2 = (0!=data.readInt());
float _arg3;
_arg3 = data.readFloat();
double _arg4;
_arg4 = data.readDouble();
java.lang.String _arg5;
_arg5 = data.readString();
int _result =this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
该方法将接收的parcel参数解析出来,并根据aidl接口方法的函数编号,调用binder实体(即stub的子类对象,该对象在server中实现了IInterface方法)中对应的方法。
public class DownloadService extends Service {
private IBinder myBinder = new IMyAidlInterface.Stub() {
@Override
public void startDownload_service(AppInfo appInfo) {
...
}
@Override
public void setDownloadListener(DownloadListener downloadListener){
...
}
@Override
public void pauseDownload(AppInfo appInfo){
...
}
}
@Override
public IBinder onBind(Intent intent) {
...
return myBinder;
}
private ServiceConnection serviceConnection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mAidl = IMyAidlInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
mAidl = null;
}
};
Messenger可以看作是binder和handler的组合,使用消息队列来存放客户端请求。
public final class Messenger implements Parcelable {
private final IMessenger mTarget;
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
}
final IMessenger getIMessenger() {
synchronized (mQueue) {
if (mMessenger != null) {
return mMessenger;
}
mMessenger = new MessengerImpl();
return mMessenger;
}
}
private final class MessengerImpl extends IMessenger.Stub {
public void send(Message msg) {
msg.sendingUid = Binder.getCallingUid();
Handler.this.sendMessage(msg);
}
}
其中,IMessenger相当于自定义的IInterface接口,send(message) 是接口中定义的方法,MessengerImpl相当于server中的binder实体,即IMessenger.stub,而stub实现IMessenger接口。
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
public IBinder getBinder() {
return mTarget.asBinder();
}
返回binder是在server中进行返回,而在server中是通过handler构造的messenger,所以messenger中的成员变量IMessenger mTarget是MessengerImpl,即server中的binder实体,asBinder()方法返回的是其本身。
public class DownloadService extends Service {
private static class MessengerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
// 处理client发送给server的message
...
try {
//用client端的Messenger返回消息
msg.replyTo.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
private Messenger mMessenger=new Messenger(new MessengerHandler());
@Override
public IBinder onBind(Intent intent) {
...
return mMessenger.getBinder();
}
private ServiceConnection serviceConnection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Messenger mService=new Messenger(service);
...
message.replyTo=mRelyMessenger;
try {
//用server中的Messenger向server发送message
mService.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
...
}
};
private Messenger mRelyMessenger=new Messenger(mRelyHandler);
public static class RelyHandler extends Handler{
@Override
public void handleMessage(Message msg) {
//处理server发送给client的message
...
}
}
抽象类,需要创建子类继承。由两类线程池和一个handler组成。其中,线程池分为以下两类:
在定义子类时,可以设定三个泛型参数,params(需要传入的参数类型)、progress(进度的度量单位)、result(返回结果的数据类型);并且,可以选择重写4个方法:
通过调用AsyncTask的子类对象的execute(params…) 或者executeOnExecutor() 方法触发任务执行,并传递参数。
public class DownloadTask extends AsyncTask<Void, Integer, Integer> {
@Override
protected Integer doInBackground(Void... strings) {
...
return result;
}
@Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onCancelled(Integer result) {
super.onCancelled(result);
}
@Override
protected void onCancelled() {
super.onCancelled();
}
}
intentservice也是基于异步消息处理机制实现的,适用场景:
方式:
public class MyIntentService extends IntentService {
public MyIntentService() {
super(MyIntentService.class.getName());
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
...
}
}
参考:
https://www.runoob.com/w3cnote/android-tutorial-service-3.html