快速做网站团队,文字怎么生成网址链接,手机在线电影网站,素材网站哪个值得买Service 与 Thread 和 进程 之间的关系
进程#xff1a;应用程序在内存中分配的空间。#xff08;正在运行中的程序#xff09;线程#xff1a;负责程序执行的单元#xff0c;也称为执行路径。#xff08;需要线程来执行代码#xff09;。一个进程至少包含一条线程应用程序在内存中分配的空间。正在运行中的程序线程负责程序执行的单元也称为执行路径。需要线程来执行代码。一个进程至少包含一条线程如果一个进程中出现了条线程此程序就为多线程程序。Service是一个组件默认运行在Main线程进程中。和Thread没关系。如果Service在清单文件中用 android:process 属性另开进程运行此Service组件就算Service被销毁进程也不会停止。
Service的生命周期图
! | 【Android】跨进程通信——AIDL、之Service基本细节使用之精通
Service 与 Thread 和 进程 之间的关系
进程应用程序在内存中分配的空间。正在运行中的程序线程负责程序执行的单元也称为执行路径。需要线程来执行代码。一个进程至少包含一条线程如果一个进程中出现了条线程此程序就为多线程程序。Service是一个组件默认运行在Main线程进程中。和Thread没关系。如果Service在清单文件中用 android:process 属性另开进程运行此Service组件就算Service被销毁进程也不会停止。
Service的生命周期图 回调方法详解
onCreate()创建Service时调用整个生命周期中只执行一次。onBind()必须实现的方法客户端调用bindService()时回调该方法返回一个IBind对象通过此对象与被绑定Service通信。此后如果再次使用bindService绑定Service系统不会再调用onBind()方法只会直接把IBinder对象传递给其他后来增加的客户端onStartCommand()早期版本是onStart()。客户端通过startService()时调用。可多次调用startService()但不会创建新的Service对象继续复用已创建的Service会继续回调onStartCommand()方法。onUnbind()当该Service上绑定的所有客户端都断开时会回调该方法onDestroy()服务被关闭前调用此方法。如调用stopService()或者调用unbindService()。
三种服务的启动方式
startService()启动Service
方法回调onCreate() — onStartCommand() — 进入运行状态。联系绑定与调用者无联系就算调用者结束了生命只要不调用stopService()方法Service还会继续运行。结束方法stopService()
bindService()启动Service
方法回调onCreate() — onBind() — 进入运行状态。联系绑定服务与调用者进行联系绑定。1. 如果调用者没有手动调用unbindService()关闭服务当调用者销毁后服务也会被销毁并回调 onUnbind() — onDestroy()。 2. 如果是多个客户端绑定同一个Service的话当所有的客户端都和service解除绑定或销毁后系统才会销毁service。结束方法unbindService()注意如果中途中通过startService() 方法启动服务则服务不会和全部调用者进行联系绑定。
startService()启动Service后调用bindService()绑定Service
方法回调onCreate() — onStartCommand() — onBind() — 进入运行状态。方法回调2如果两条语句在一个方法内onCreate() — onBind() — onStartCommand() — 进入运行状态。联系绑定与调用者无联系因为服务是通过startService()启动的。结束方法先unbindService()解绑再调用stopService()关闭Service
不管哪种方法启动服务都可以调用 stopService() 关闭服务。上面是按照规范关闭服务当然你有需求的话。
清单文件声明 Service 组件及属性
android:exported表示是否允许除了当前程序之外的其他程序访问这个服务android:enabled表示是否启用这个服务android:permission是权限声明android:process是否需要在单独的进程中运行,当设置为android:process”:remote”时代表Service在单独的进程中运行。注意“”很重要它的意思是指要在当前进程名称前面附加上当前的包名所以“remote”和”:remote”不是同一个意思前者的进程名称为remote而后者的进程名称为App-packageName:remote。android:isolatedProcess设置 true 意味着服务会在一个特殊的进程下运行这个进程与系统其他进程分开且没有自己的权限。与其通信的唯一途径是通过服务的API(bind and start)。
service android:name.myServiceandroid:enabledtrueandroid:exportedtrueandroid:icondrawable/ic_launcherandroid:labelstringandroid:process:stringandroid:permissionstring
/serviceIntent的显式与隐式启动
一、显示启动service
Intent intent new Intent(this, MyService.class);
startService(intent);二、隐式启动service
首先自定义意图过滤器标签 intent-filter、Action
service android:name.MyService android:enabledtrue intent-filter android:priority1000 action android:namecom.bin.action.MyService //intent-filter
/service
!-- android:priority1000 服务优先级 --三、5.0后隐式启动 service
5.0 之前的隐式启动service
Intent intent new Intent(com.bin.action.MyService);
startService(intent);5.0 之后的隐式启动service
Intent intent new Intent(com.bin.action.MyService);
intent.setPackage(getPackageName()); //如果是另一个程序的service则指定它的包名
startService(intent);前台Service
原理在服务里通过 startForeground() 方法启动一个通知 Notification也可以使用兼容包里的 通知对象。
public void onCreate()
{super.onCreate();Notification.Builder localBuilder new Notification.Builder(this);localBuilder.setSmallIcon(R.drawable.ic_launcher);localBuilder.setContentTitle(Service标题);localBuilder.setContentText(正在运行...);startForeground(1, localBuilder.getNotification());
}系统8.0、8.1的后台 Service 必须切换成前台服务
注意调用startForegroundService()后5秒内没有调用startForeground(会有ANR(Application Not Responding)
public class MyService extends Service {Overridepublic void onCreate(){super.onCreate();// 调用startForegroundService()后5秒内没有调用startForeground(会有ANRif (Build.VERSION.SDK_INT Build.VERSION_CODE.O) {Notification.Builder localBuilder new Notification.Builder(this);localBuilder.setSmallIcon(R.drawable.ic_launcher);localBuilder.setContentTitle(Service标题);localBuilder.setContentText(正在运行...);startForeground(1, localBuilder.getNotification());}}Overridepublic void onDestroy() {stopForeground(true);super.onDestroy();}
}版本兼容判断 启动Service8.0、8.1启动Service方法用startForegroundService()
if (Build.VERSION.SDK_INT Build.VERSION_CODE.O) {startForegroundService(intent);
} else {startService(intent);
}使用 startForegroundService() 方法启动service还需要添加权限 uses-permission android:nameandroid.permission.FOREGROUND_SERVICE/跨进程通信
跨进程通信的场景有两种
本地service跨进程通信是和当前程序内的service进行通信远程Service跨进程通信是和其它程序内的service进行通信已知方式
AIDL 接口描述文件方式不用AIDL方式使用 Binder 的 onTransact 方法使用MessengerHandler的方式
先来了解一下 bindService()、ServiceConnection、Binder
1.1 bindService(Intent service, ServiceConnection conn, int flags)
service : 通过该intent指定要启动的Serviceconn : ServiceConnection对象用户监听访问者与Service间的连接情况连接成功回调该对象中的onServiceConnected(ComponentName,IBinder)方法如果Service所在的宿主由于异常终止或者其他原因终止导致Service与访问者间断开连接时调用onServiceDisconnected(CompanentName)方法主动通过unbindService() 方法断开并不会调用上述方法flags : 指定绑定时是否自动创建Service(如果Service还未创建)参数可以是 0 (不自动创建)BIND_AUTO_CREATE(自动创建)
1.2 ServiceConnection
private IBinder myService;private ServiceConnection con new ServiceConnection(){Overridepublic void onServiceConnected(ComponentName package, IBinder service){myService service;Toast.makeText(MyService.this, 连接成功, Toast.LENGTH_LONG).show();}Overridepublic void onServiceDisconnected(ComponentName package){myService null;Toast.makeText(MyService.this, 连接断开, Toast.LENGTH_LONG).show();}
};1.3 返回的 Binder 对象
返回的对象不能为null否则连接不成立。
2. 本地 Service 跨进程通信
服务端
服务端需要写一个继承自 Binder 的类与服务通信。而这个类是你自定义的。
public class MyService extends Service
{private MyBinder binder;Overridepublic IBinder onBinder(Intent intent){if (binder null) {binder new MyBinder();}return binder;}private class MyBinder extends Binder{// ...code// 返回此对象与Service进行通信public void toast(Context context, String str){Toast.mackText(context, str, Toast.LENGTH_LONG).show();}}}然后在清单文件声明服务组件并用 android:process 属性另开进程
service android:name.MyService
android:enabledtrue
android:process:MyService /客户端
public class MainActivity extends Activity
{private IBinder myService;private ServiceConnection con new ServiceConnection() {Overridepublic void onServiceConnected(ComponentName package, IBinder service){myService service;Toast.makeText(MainActivity.this, 连接成功, Toast.LENGTH_LONG).show();try{if (myService ! null) {Toast.makeText(MainActivity.this, myService.toast(this, myService 弹出我吧), Toast.LENGTH_LONG).show();} else {Toast.makeText(MainActivity.this, 服务端未启动或异常关闭, Toast.LENGTH_LONG).show();}}catch (RemoteException e){}}Overridepublic void onServiceDisconnected(ComponentName package){myService null;Toast.makeText(MainActivity.this, 连接断开, Toast.LENGTH_LONG).show();}};Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);bindService(new Intent(this, MyService.class), con, BIND_AUTO_CREATE);}}3. 远程 Service 跨进程通信
1. AIDL跨进程通信
编写 AIDL 的注意事项
接口名词需要与aidl文件名相同。接口和方法前面不要加访问权限修饰符public ,private,protected等也不能用static final。AIDL默认支持的类型包括Java基本类型StringListMapCharSequence除此之外的其他类型都 需要import声明对于使用自定义类型作为参数或者返回值自定义类型需要实现Parcelable接口。自定义类型和AIDL生成的其它接口类型在aidl描述文件中应该显式import即便在该类和定义 的包在同一个包中。常见坑两个应用程序的AIDL描述文件所在的包必须一样。
服务端创建 AIDL 文件接口 IPerson.aidl
package com.bin.aidl;interface IPerson {String getContent(int postion);
}保存后会在 gen目录的包路径下 自动生成 IPerson.java 图片来源网络 自定义Service类
注意这时候我们返回的 Binder 对象是继承自 AIDL接口的 内部类StubIPerson.java下的 Stub类
public static abstract class Stub extends android.os.Binder implements com.bin.aidl.IPerson
public class AIDLService extends Service {private IBinder binder;Overridepublic IBinder onBind(Intent intent) {if (binder null) {binder new AIDLBinder();}return binder;}private final class AIDLBinder extends Stub {Overridepublic String getContent(int postion) throws RemoteException {String result null;switch (postion) {case 0:result 我是0;break;case 1:result 我是1;break;case 2:result 我是2;break;default:result 我是默认;break;}return result;}}
}在AndroidManifest.xml文件中注册Service
注意从一个进程启动另一个进程的 Service 要定义 意图过滤器
service android:name.AIDLServiceintent-filteraction android:nameandroid.intent.action.AIDLService /category android:nameandroid.intent.category.DEFAULT //intent-filter
/service是 Intent默认添加的附加属性所以加上。
服务端编写完毕
客户端
首先把 服务端的AIDL文件复制过来不能修改AIDL文件里的任何东西包括 所在 package …
注意AIDL存放的包路径必须与服务端一致
与服务端连接成功后返回的Binder对象要强转为 AIDL 接口对象才能使用自定义方法
// public static com.bin.aidl.IPerson asInterface(android.os.IBinder obj)IPerson.Stub.asInterface(service);
public class MainActivity extends Activity
{private IPerson iPerson;private ServiceConnection con new ServiceConnection(){Overridepublic void onServiceConnected(ComponentName package, IBinder service){Toast.makeText(MainActivity.this, 连接成功, Toast.LENGTH_LONG).show();iPerson IPC.Stub.asInterface(service);try{Toast.makeText(MainActivity.this, iPerson.getContent(0), Toast.LENGTH_LONG).show();}catch (RemoteException e){}}Overridepublic void onServiceDisconnected(ComponentName package){Toast.makeText(MainActivity.this, 断开连接, Toast.LENGTH_LONG).show();iPerson null;}};Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);Intent service new Intent(android.intent.action.AIDLService);service.setPackage(com.bin.aidl);bindService(service, con, BIND_AUTO_CREATE);}}2. 不用AIDL方式使用 Binder 的 onTransact 方法
服务端
public class IPCService extends Service {private static final String DESCRIPTOR IPCService;private IBinder binder;Overridepublic IBinder onBind(Intent intent) {if (binder null) {binder new IPCBinder();}return binder;}private final class IPCBinder extends Binder {Overrideprotected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {switch (code){case 0x001: {//读取发送来的消息data.enforceInterface(DESCRIPTOR);int postion data.readInt();//处理String result null;switch (postion) {case 0:result 我是0;break;case 1:result 我是1;break;case 2:result 我是2;break;default:result 我是默认;break;}//返回数据reply.writeNoException();reply.writeString(result);return true;}}return super.onTransact(code, data, reply, flags);}}
}客户端
public class MainActivity extends Activity
{private IBinder iBinder;private ServiceConnection con new ServiceConnection(){Overridepublic void onServiceConnected(ComponentName package, IBinder service){Toast.makeText(MainActivity.this, 连接成功, Toast.LENGTH_LONG).show();iBinder service;android.os.Parcel data android.os.Parcel.obtain();android.os.Parcel reply android.os.Parcel.obtain();String result null;int postion 1;try {//写入信息data.writeInterfaceToken(IPCService);data.writeInt(postion);//发送消息mIBinder.transact(0x001, data, reply, 0);//读取返回信息reply.readException();result reply.readString();}catch (RemoteException e) {e.printStackTrace();} finally { //释放资源reply.recycle();data.recycle();}Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();}Overridepublic void onServiceDisconnected(ComponentName package){Toast.makeText(MainActivity.this, 断开连接, Toast.LENGTH_LONG).show();iBinder null;}};Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);Intent service new Intent(android.intent.action.IPCService);service.setPackage(com.bin.ipcservice);bindService(service, con, BIND_AUTO_CREATE);}}3. 使用Messenger跨进程通信
服务端实现一个Handler由其接受来自客户端的每个调用的回调使用实现的Handler创建Messenger对象通过Messenger得到一个IBinder对象并将其通过onBind()返回给客户端客户端使用 IBinder 将 Messenger引用服务的 Handler实例化然后使用后者将 Message 对象发送给服务服务端在其 Handler 中具体地讲是在 handleMessage() 方法中接收每个 Message
服务端
public class MessengerService extends Service {private final Messenger mMessenger new Messenger(new ServiceHandler());class ServiceHandler extends Handler {Overridepublic void handleMessage(Message msg) {String result null;switch (msg.what) {case 0:result 我是0;break;case 1:result 我是1;break;case 2:result 我是2;break;default:result 我是默认;break;}Toast.makeText(MessengerService.this, result, Toast.LENGTH_LONG).show();super.handleMessage(msg);}}NullableOverridepublic IBinder onBind(Intent intent) {//返回给客户端一个IBinder实例return mMessenger.getBinder();}
}客户端
public class MainActivity extends Activity
{private Messenger mService;private ServiceConnection con new ServiceConnection(){Overridepublic void onServiceConnected(ComponentName package, IBinder service){Toast.makeText(MainActivity.this, 连接成功, Toast.LENGTH_LONG).show();//接收onBind()传回来的IBinder并用它构造MessengermService new Messenger(service);//构造一个消息对象Message msg Message.obtain(null, 2, 0, 0);try {//把这个信息发送给服务端mService.send(msg);} catch (RemoteException e) {e.printStackTrace();}}Overridepublic void onServiceDisconnected(ComponentName package){Toast.makeText(MainActivity.this, 断开连接, Toast.LENGTH_LONG).show();mService null;}};Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);Intent service new Intent(android.intent.action.MessengerService);service.setPackage(com.bin.messengerservice);bindService(service, con, BIND_AUTO_CREATE);}}双进程守护 原理两个服务之间互相绑定监听服务之间的 ServiceConnection 对象重写 onServiceDisconnected() 方法 在对方异常断开连接时重启对方。
服务1
public class MyService1 extends Service
{private MyBinder binder;private IBinder mService;private Intent intent;private ServiceConnection con new ServiceConnection(){Overridepublic void onServiceConnected(ComponentName package, IBinder service){Toast.makeText(MyService1.this, 连接成功, Toast.LENGTH_LONG).show();mService service;}Overridepublic void onServiceDisconnected(ComponentName package){Toast.makeText(MyService1.this, 连接断开, Toast.LENGTH_LONG).show();mService null;startService(intent);bindService(intent, con, 0);}};Overridepublic void onCreate(){intent new Intent(this, MyService2.class);startService(intent);bindService(intent, con, 0);super.onCreate();}Overridepublic IBinder onBinder(Intent intent){if (binder null) {binder new MyBinder();}return binder;}private class MyBinder extends Binder{// TODO}}服务2
public class MyService2 extends Service
{private MyBinder binder;private IBinder mService;private Intent intent;private ServiceConnection con new ServiceConnection(){Overridepublic void onServiceConnected(ComponentName package, IBinder service){Toast.makeText(MyService2.this, 连接成功, Toast.LENGTH_LONG).show();mService service;}Overridepublic void onServiceDisconnected(ComponentName package){Toast.makeText(MyService2.this, 连接断开, Toast.LENGTH_LONG).show();mService null;startService(intent);bindService(intent, con, 0);}};Overridepublic void onCreate(){intent new Intent(this, MyService1.class);startService(intent);bindService(intent, con, 0);super.onCreate();}Overridepublic IBinder onBinder(Intent intent){if (binder null) {binder new MyBinder();}return binder;}private class MyBinder extends Binder{// TODO}}启动服务的方式可以在 Activity 中也可以用广播接收器我这里就用活动来启动服务
public class MainActivity extends Activity
{Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);Intent service new Intent(this, MyService1.class);startService(service);}}记得在清单文件声明Service组件
service android:name.MyService1 /
service android:name.MyService2android:process:MyService2/注意双进程守护只能防止第三方应用kill并不能防止用户手动停止掉
| | |–|–| | | |
回调方法详解 onCreate()创建Service时调用整个生命周期中只执行一次。 onBind()必须实现的方法客户端调用bindService()时回调该方法返回一个IBind对象通过此对象与被绑定Service通信。此后如果再次使用bindService绑定Service系统不会再调用onBind()方法只会直接把IBinder对象传递给其他后来增加的客户端 onStartCommand()早期版本是onStart()。客户端通过startService()时调用。可多次调用startService()但不会创建新的Service对象继续复用已创建的Service会继续回调onStartCommand()方法。 onUnbind()当该Service上绑定的所有客户端都断开时会回调该方法 onDestroy()服务被关闭前调用此方法。如调用stopService()或者调用unbindService()。 三种服务的启动方式
startService()启动Service 方法回调onCreate() — onStartCommand() — 进入运行状态。 联系绑定与调用者无联系就算调用者结束了生命只要不调用stopService()方法Service还会继续运行。 结束方法stopService()bindService()启动Service 方法回调onCreate() — onBind() — 进入运行状态。 联系绑定服务与调用者进行联系绑定。1. 如果调用者没有手动调用unbindService()关闭服务当调用者销毁后服务也会被销毁并回调 onUnbind() — onDestroy()。 2. 如果是多个客户端绑定同一个Service的话当所有的客户端都和service解除绑定或销毁后系统才会销毁service。 结束方法unbindService() 注意如果中途中通过startService() 方法启动服务则服务不会和全部调用者进行联系绑定。startService()启动Service后调用bindService()绑定Service 方法回调onCreate() — onStartCommand() — onBind() — 进入运行状态。 方法回调2如果两条语句在一个方法内onCreate() — onBind() — onStartCommand() — 进入运行状态。 联系绑定与调用者无联系因为服务是通过startService()启动的。 结束方法先unbindService()解绑再调用stopService()关闭Service 不管哪种方法启动服务都可以调用 stopService() 关闭服务。上面是按照规范关闭服务当然你有需求的话。
清单文件声明 Service 组件及属性 android:exported 表示是否允许除了当前程序之外的其他程序访问这个服务 android:enabled 表示是否启用这个服务 android:permission 是权限声明 android:process 是否需要在单独的进程中运行,当设置为android:process”:remote”时代表Service在单独的进程中运行。注意“”很重要它的意思是指要在当前进程名称前面附加上当前的包名所以“remote”和”:remote”不是同一个意思前者的进程名称为remote而后者的进程名称为App-packageName:remote。 android:isolatedProcess 设置 true 意味着服务会在一个特殊的进程下运行这个进程与系统其他进程分开且没有自己的权限。与其通信的唯一途径是通过服务的API(bind and start)。 Intent的显式与隐式启动 一、显示启动service Intent intent new Intent(this, MyService.class); startService(intent); 二、隐式启动service 首先自定义意图过滤器标签 intent-filter、Action action android:namecom.bin.action.MyService //intent-filter三、5.0后隐式启动 service 5.0 之前的隐式启动service
Intent intent new Intent(“com.bin.action.MyService”); startService(intent); 5.0 之后的隐式启动service
Intent intent new Intent(“com.bin.action.MyService”); intent.setPackage(getPackageName()); //如果是另一个程序的service则指定它的包名 startService(intent); 前台Service 原理在服务里通过 startForeground() 方法启动一个通知 Notification也可以使用兼容包里的 通知对象。
public void onCreate() { super.onCreate(); Notification.Builder localBuilder new Notification.Builder(this); localBuilder.setSmallIcon(R.drawable.ic_launcher); localBuilder.setContentTitle(“Service标题”); localBuilder.setContentText(“正在运行…”); startForeground(1, localBuilder.getNotification()); } 系统8.0、8.1的后台 Service 必须切换成前台服务 注意调用startForegroundService()后5秒内没有调用startForeground(会有ANR
public class MyService extends Service {
Override
public void onCreate()
{super.onCreate();// 调用startForegroundService()后5秒内没有调用startForeground(会有ANRif (Build.VERSION.SDK_INT Build.VERSION_CODE.O) {Notification.Builder localBuilder new Notification.Builder(this);localBuilder.setSmallIcon(R.drawable.ic_launcher);localBuilder.setContentTitle(Service标题);localBuilder.setContentText(正在运行...);startForeground(1, localBuilder.getNotification());}
}Override
public void onDestroy() {stopForeground(true);super.onDestroy();
}}
版本兼容判断 启动Service8.0、8.1启动Service方法用startForegroundService()
if (Build.VERSION.SDK_INT Build.VERSION_CODE.O) { startForegroundService(intent); } else { startService(intent); } 使用 startForegroundService() 方法启动service还需要添加权限 跨进程通信 跨进程通信的场景有两种
本地service跨进程通信是和当前程序内的service进行通信 远程Service跨进程通信是和其它程序内的service进行通信已知方式 1. AIDL 接口描述文件方式 2. 不用AIDL方式使用 Binder 的 onTransact 方法3. 使用MessengerHandler的方式先来了解一下 bindService()、ServiceConnection、Binder
1.1 bindService(Intent service, ServiceConnection conn, int flags) service : 通过该intent指定要启动的Service conn : ServiceConnection对象用户监听访问者与Service间的连接情况连接成功回调该对象中的onServiceConnected(ComponentName,IBinder)方法如果Service所在的宿主由于异常终止或者其他原因终止导致Service与访问者间断开连接时调用onServiceDisconnected(CompanentName)方法主动通过unbindService() 方法断开并不会调用上述方法 flags : 指定绑定时是否自动创建Service(如果Service还未创建)参数可以是 0 (不自动创建)BIND_AUTO_CREATE(自动创建) 1.2 ServiceConnection private IBinder myService;
private ServiceConnection con new ServiceConnection(){ Overridepublic void onServiceConnected(ComponentName package, IBinder service){myService service;Toast.makeText(MyService.this, 连接成功, Toast.LENGTH_LONG).show();}Overridepublic void onServiceDisconnected(ComponentName package){myService null;Toast.makeText(MyService.this, 连接断开, Toast.LENGTH_LONG).show();}};
1.3 返回的 Binder 对象注意 返回的对象不能为null否则连接不成立。
本地 Service 跨进程通信 服务端
服务端需要写一个继承自 Binder 的类与服务通信。而这个类是你自定义的。
public class MyService extends Service { private MyBinder binder;
Override
public IBinder onBinder(Intent intent)
{if (binder null) {binder new MyBinder();}return binder;
}private class MyBinder extends Binder
{// ...code// 返回此对象与Service进行通信public void toast(Context context, String str){Toast.mackText(context, str, Toast.LENGTH_LONG).show();}
}}
然后在清单文件声明服务组件并用 android:process 属性另开进程 客户端
public class MainActivity extends Activity {
private IBinder myService;private ServiceConnection con new ServiceConnection() {Overridepublic void onServiceConnected(ComponentName package, IBinder service){myService service;Toast.makeText(MainActivity.this, 连接成功, Toast.LENGTH_LONG).show();try{if (myService ! null) {Toast.makeText(MainActivity.this, myService.toast(this, myService 弹出我吧), Toast.LENGTH_LONG).show();} else {Toast.makeText(MainActivity.this, 服务端未启动或异常关闭, Toast.LENGTH_LONG).show();}}catch (RemoteException e){}}Overridepublic void onServiceDisconnected(ComponentName package){myService null;Toast.makeText(MainActivity.this, 连接断开, Toast.LENGTH_LONG).show();}
};Override
protected void onCreate(Bundle savedInstanceState)
{super.onCreate(savedInstanceState);setContentView(R.layout.main);bindService(new Intent(this, MyService.class), con, BIND_AUTO_CREATE);
}}
远程 Service 跨进程通信AIDL跨进程通信 编写 AIDL 的注意事项
接口名词需要与aidl文件名相同。 接口和方法前面不要加访问权限修饰符public ,private,protected等也不能用static final。 AIDL默认支持的类型包括Java基本类型StringListMapCharSequence除此之外的其他类型都 需要import声明对于使用自定义类型作为参数或者返回值自定义类型需要实现Parcelable接口。 自定义类型和AIDL生成的其它接口类型在aidl描述文件中应该显式import即便在该类和定义 的包在同一个包中。 常见坑两个应用程序的AIDL描述文件所在的包必须一样。 服务端创建 AIDL 文件接口 IPerson.aidl
package com.bin.aidl;
interface IPerson { String getContent(int postion); } 保存后会在 gen目录的包路径下 自动生成 IPerson.java 图片来源网络
自定义Service类
注意这时候我们返回的 Binder 对象是继承自 AIDL接口的 内部类StubIPerson.java下的 Stub类
public static abstract class Stub extends android.os.Binder implements com.bin.aidl.IPerson public class AIDLService extends Service {
private IBinder binder;Override
public IBinder onBind(Intent intent) {if (binder null) {binder new AIDLBinder();}return binder;
}private final class AIDLBinder extends Stub {Overridepublic String getContent(int postion) throws RemoteException {String result null;switch (postion) {case 0:result 我是0;break;case 1:result 我是1;break;case 2:result 我是2;break;default:result 我是默认;break;}return result;}
}}
在AndroidManifest.xml文件中注册Service
注意从一个进程启动另一个进程的 Service 要定义 意图过滤器 是 Intent默认添加的附加属性所以加上。
服务端编写完毕
客户端
首先把 服务端的AIDL文件复制过来不能修改AIDL文件里的任何东西包括 所在 package …
注意AIDL存放的包路径必须与服务端一致
与服务端连接成功后返回的Binder对象要强转为 AIDL 接口对象才能使用自定义方法
// public static com.bin.aidl.IPerson asInterface(android.os.IBinder obj)
IPerson.Stub.asInterface(service); public class MainActivity extends Activity { private IPerson iPerson; private ServiceConnection con new ServiceConnection(){ Overridepublic void onServiceConnected(ComponentName package, IBinder service){Toast.makeText(MainActivity.this, 连接成功, Toast.LENGTH_LONG).show();iPerson IPC.Stub.asInterface(service);try{Toast.makeText(MainActivity.this, iPerson.getContent(0), Toast.LENGTH_LONG).show();}catch (RemoteException e){}}Overridepublic void onServiceDisconnected(ComponentName package){Toast.makeText(MainActivity.this, 断开连接, Toast.LENGTH_LONG).show();iPerson null;}
};Override
protected void onCreate(Bundle savedInstanceState)
{super.onCreate(savedInstanceState);setContentView(R.layout.main);Intent service new Intent(android.intent.action.AIDLService);service.setPackage(com.bin.aidl);bindService(service, con, BIND_AUTO_CREATE);
}}
不用AIDL方式使用 Binder 的 onTransact 方法 服务端
public class IPCService extends Service {
private static final String DESCRIPTOR IPCService;
private IBinder binder;Override
public IBinder onBind(Intent intent) {if (binder null) {binder new IPCBinder();}return binder;
}private final class IPCBinder extends Binder {Overrideprotected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {switch (code){case 0x001: {//读取发送来的消息data.enforceInterface(DESCRIPTOR);int postion data.readInt();//处理String result null;switch (postion) {case 0:result 我是0;break;case 1:result 我是1;break;case 2:result 我是2;break;default:result 我是默认;break;}//返回数据reply.writeNoException();reply.writeString(result);return true;}}return super.onTransact(code, data, reply, flags);}}}
客户端
public class MainActivity extends Activity { private IBinder iBinder; private ServiceConnection con new ServiceConnection(){ Overridepublic void onServiceConnected(ComponentName package, IBinder service){Toast.makeText(MainActivity.this, 连接成功, Toast.LENGTH_LONG).show();iBinder service;android.os.Parcel data android.os.Parcel.obtain();android.os.Parcel reply android.os.Parcel.obtain();String result null;int postion 1;try {//写入信息data.writeInterfaceToken(IPCService);data.writeInt(postion);//发送消息mIBinder.transact(0x001, data, reply, 0);//读取返回信息reply.readException();result reply.readString();}catch (RemoteException e) {e.printStackTrace();} finally { //释放资源reply.recycle();data.recycle();}Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();}Overridepublic void onServiceDisconnected(ComponentName package){Toast.makeText(MainActivity.this, 断开连接, Toast.LENGTH_LONG).show();iBinder null;}
};Override
protected void onCreate(Bundle savedInstanceState)
{super.onCreate(savedInstanceState);setContentView(R.layout.main);Intent service new Intent(android.intent.action.IPCService);service.setPackage(com.bin.ipcservice);bindService(service, con, BIND_AUTO_CREATE);
}}
使用Messenger跨进程通信 服务端实现一个Handler由其接受来自客户端的每个调用的回调 使用实现的Handler创建Messenger对象 通过Messenger得到一个IBinder对象并将其通过onBind()返回给客户端 客户端使用 IBinder 将 Messenger引用服务的 Handler实例化然后使用后者将 Message 对象发送给服务 服务端在其 Handler 中具体地讲是在 handleMessage() 方法中接收每个 Message 服务端
public class MessengerService extends Service {
private final Messenger mMessenger new Messenger(new ServiceHandler());class ServiceHandler extends Handler {Overridepublic void handleMessage(Message msg) {String result null;switch (msg.what) {case 0:result 我是0;break;case 1:result 我是1;break;case 2:result 我是2;break;default:result 我是默认;break;}Toast.makeText(MessengerService.this, result, Toast.LENGTH_LONG).show();super.handleMessage(msg);}
}Nullable
Override
public IBinder onBind(Intent intent) {//返回给客户端一个IBinder实例return mMessenger.getBinder();
}}
客户端
public class MainActivity extends Activity { private Messenger mService; private ServiceConnection con new ServiceConnection(){ Overridepublic void onServiceConnected(ComponentName package, IBinder service){Toast.makeText(MainActivity.this, 连接成功, Toast.LENGTH_LONG).show();//接收onBind()传回来的IBinder并用它构造MessengermService new Messenger(service);//构造一个消息对象Message msg Message.obtain(null, 2, 0, 0);try {//把这个信息发送给服务端mService.send(msg);} catch (RemoteException e) {e.printStackTrace();}}Overridepublic void onServiceDisconnected(ComponentName package){Toast.makeText(MainActivity.this, 断开连接, Toast.LENGTH_LONG).show();mService null;}
};Override
protected void onCreate(Bundle savedInstanceState)
{super.onCreate(savedInstanceState);setContentView(R.layout.main);Intent service new Intent(android.intent.action.MessengerService);service.setPackage(com.bin.messengerservice);bindService(service, con, BIND_AUTO_CREATE);
}}
双进程守护 原理两个服务之间互相绑定监听服务之间的 ServiceConnection 对象重写 onServiceDisconnected() 方法 在对方异常断开连接时重启对方。
服务1
public class MyService1 extends Service { private MyBinder binder; private IBinder mService; private Intent intent;
private ServiceConnection con new ServiceConnection(){Overridepublic void onServiceConnected(ComponentName package, IBinder service){Toast.makeText(MyService1.this, 连接成功, Toast.LENGTH_LONG).show();mService service;}Overridepublic void onServiceDisconnected(ComponentName package){Toast.makeText(MyService1.this, 连接断开, Toast.LENGTH_LONG).show();mService null;startService(intent);bindService(intent, con, 0);}
};Override
public void onCreate()
{intent new Intent(this, MyService2.class);startService(intent);bindService(intent, con, 0);super.onCreate();
}Override
public IBinder onBinder(Intent intent)
{if (binder null) {binder new MyBinder();}return binder;
}private class MyBinder extends Binder
{// TODO
}}
服务2
public class MyService2 extends Service { private MyBinder binder; private IBinder mService; private Intent intent;
private ServiceConnection con new ServiceConnection(){Overridepublic void onServiceConnected(ComponentName package, IBinder service){Toast.makeText(MyService2.this, 连接成功, Toast.LENGTH_LONG).show();mService service;}Overridepublic void onServiceDisconnected(ComponentName package){Toast.makeText(MyService2.this, 连接断开, Toast.LENGTH_LONG).show();mService null;startService(intent);bindService(intent, con, 0);}
};Override
public void onCreate()
{intent new Intent(this, MyService1.class);startService(intent);bindService(intent, con, 0);super.onCreate();
}Override
public IBinder onBinder(Intent intent)
{if (binder null) {binder new MyBinder();}return binder;
}private class MyBinder extends Binder
{// TODO
}}
启动服务的方式可以在 Activity 中也可以用广播接收器我这里就用活动来启动服务
public class MainActivity extends Activity { Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Intent service new Intent(this, MyService1.class);startService(service);
}} 记得在清单文件声明Service组件 注意双进程守护只能防止第三方应用kill并不能防止用户手动停止掉