AIDL:
AIDL可以作为客户端服务端连接,也可以访问系统里未对外暴露的api(比如挂断电话)
原理如下:
编写AIDL文件需注意以下几点:
实现进程通信:
AIDL默认支持传递基本类型,如要自定义传递类型:
AIDL中所指的服务端和客户端(访问者)之间的通信指的是两个应用之间的通信,并不是web中的Service和Client的通信。
当使用AIDL进行两个应用通信时,两边都需要使用相同的AIDL文件(通信规则文件)编译器会自动生成通信所需要的代码,只需要引用自动生成的代码进行通信即可。
如以下AIDL文件:
//aidl文件
interface StudentQuery {
String queryStudent(int number);
}
会在gen目录下自动生成(AndroidStudio切换到Packages结构)StudentQuery.java的接口文件,如下:
public interface StudentQuery extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements StudentQuery
{
这样服务端定义的继承Service的类(Service在Manifest的注册最好使用隐式意图)中即可使用编译器自动生成通信类返回IBinder的代理对象给客户端,如下:
public class SutdentQueryService extends Service{
private String[] names = {"aaa","bbb"};
private IBinder binder = new StudentQueryBinder();
@Override
public IBinder onBind(Intent intent) {
return binder;
}
private String query(int number){
return names[number-1];
}
private final class StudentQueryBinder extends StudentQuery.Stub {
@Override
public String queryStudent(int number) throws RemoteException {
return query(number);
服务端返回IBinder代理对象,在客户端先用Intent去bindServier连接服务然后继承ServiceConnection再转换成使用AIDL文件的编译器自动生成的通信类的接口类型,然后便可调用服务端中的方法queryStudent(int number)
,如下:
Intent intent = new Intent("cn.student.query");
bindService(intent,studentConnection,BIND_AUTO_CREATE);
private final class StudentConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
studentQuery = StudentQuery.Stub.asInterface(iBinder);
try {
studentQuery.queryStudent(i);
} catch (RemoteException e) {
其实就是服务端暴露接口给访问者,两者通过Service和AIDL规则建立连接(连接通过IBinder代理对象),访问者调用服务端的方法。
如果需要传递自定义对象则自定义javabean实现Parcelable接口。
Serializable和Parcelable区别:
在于存储媒介的不同。Serializable使用IO读写存储在硬盘上。序列化过程使用了反射技术,并且期间产生临时对象。Parcelable是直接在内存中读写,内存的读写速度肯定优于硬盘读写速度,所以Parcelable序列化方式性能上要优于Serializable方式很多。
==============================================================================
Binder:
Binder工作在Linux层面,属于一个驱动,客户端程序调用Binder是通过系统调用完成的。
Binder是一种架构,这种架构提供了服务端接口、Binder驱动、客户端接口三个模块。
Binder实现了IBinder接口,是ServiceManager连接各种Manager(如WindowManager、ActivityManager等)的桥梁。
Binder包含四个部分:服务端(Server),客户端(Client),Binder驱动,ServiceManager,运作过程是:
1. 服务端创建对应Binder实例对象,然后开启隐藏Binder线程,接收来自客户端的请求,同时,将自身的Binder注册到Service Manager,在Binder驱动创建mRemote对象。
2. 客户端想和服务端通信,通过Service Manager查找到服务端的Binder,然后Binder驱动将对应的mRemote对象返回
3. 至此,整个通信连接建立完毕
==============================================================================
Messenger:
通过Messenger可以在不同进程传递Message对象,在Message中放入需要传递数据即可。
Messenger是轻量级IPC方案,底层实现是AIDL。
服务端:创建Service和Handler并通过Handler创建Messenger对象,然后在Service的onBind()中返回Binder即可。
客户端:绑定服务端的Service后返回IBinder对象创建一个Messenger,通过这个Messenger就可向服务端发消息类型为Message。如需服务端回应客户端,客户端需创建Handler并创建一个新的Messenger把他通过Message的replyTo参数传给服务端,服务端通过replyTo参数即可回应。
进程、进程间通信:
一般情况下,一个应用程序就是一个进程,这个进程名称就是应用程序包名。我们知道进程是系统分配资源和调度的基本单位,所以每个进程都有自己独立的资源和内存空间,别的进程是不能任意访问其他进程的内存和资源的。
进程间通信4种方法:
对应4大组件Activity(Intent)、Content Provider(以Cursor对象返回)、Broadcast(sendBroadcast)和Service(用AIDL Service实现跨进程通信)。
保证进程不被杀死的方法:
1.Service设置成START_STICKY,kill后会被重启(等待5秒左右),重传Intent,保持与重启前一样
2.通过startForeground将进程设置为前台进程,做前台服务,优先级和前台应用一个级别除非内存非常紧缺,否则不会被kill
3.双进程Service:让2个进程互相保护,其中一个Service被清理后,另外没被清理的进程可以立即重启进程
4.QQ黑科技:在应用退到后台后,另起一个只有 1 像素的页面停留在桌面上,让自己保持前台状态,保护自己不被后台清理工具杀死
5.在已经root的设备下,修改相应的权限文件,将App伪装成系统级的应用(Android4.0系列的一个漏洞,已经确认可行)
并行与并发:
并发的关键是处理多个任务,不一定要同时。并行的关键是同时处理多个任务。