在Android中,一个进程通常无法访问另一个进程的内存。为了进程间的通信,进程需要将其对象分解成可供操作系统理解的语言,将其编组为可更操作的对象,编写执行该编组操作的代码较为繁琐,因此Android会使用AIDL为我们处理此问题。
白话
让某个Service与多个应用程序组件之间进行跨进程通信,从而实现多个应用程序共享同一个Service的功能
使用场景
AIDL:只有需要不同应用的客户端通过IPC方式访问服务,并且希望服务中进行多线程操作的
Binder:单应用多进程开发IPC,服务中进行多线程
Messenger:跨应用多进程IPC,不需要多线程
根据不同业务需求来使用相应的IPC方式。
如何使用
写两个应用 MsApplication 、MyApplacation。MsApplication 中启动这个将作为共享的服务 ,在MyApplacation中通过AIDL获得service中的内容
首先创建AIDL文件 文件位置存放
它的内容是这样的 划红线的部分是我自己添加的方法;basicTypes方法可以删掉。
MsApplication中MainActivity.java
public class MainActivity extends AppCompatActivity {
private ServiceConnection service = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
aidlInterface = IMyAidlInterface.Stub.asInterface(service);
try {
String string = aidlInterface.getString();
Log.e("", string);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
aidlInterface = null;
}
};
private IMyAidlInterface aidlInterface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.b).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, MainService.class);
bindService(intent, service, BIND_AUTO_CREATE);
}
});
}
}
MainService.java
public class MainService extends Service {
@Override
public void onCreate() {
super.onCreate();
Log.e("///", "创建");
}
@Override
public IBinder onBind(Intent intent) {
return new Mybind();
}
public synchronized ComponentName startForegroundServiceAsUser(Intent service, UserHandle user) {
return null;
}
class Mybind extends IMyAidlInterface.Stub {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public String getString() throws RemoteException {
String string = "我是从服务起返回的";
return string;
}
}
}
清单文件
<service android:name=".MainService">
<intent-filter>
<action android:name="com.example.msapplication.MainService" />
</intent-filter>
</service>
在这个Service中我们创建了内部类继承我们的AIDL文件IMyAidlInterface,需要.Stub。重写了两个方法,我们可以再getString中搞我们想要做的事情。这时是可以启动应用程序并且开启这个服务的,也可以得到我们通过getString方法放回字符串的,但是并没有实现跨进程通信。在来写My Application。这个应用中我同样要定义AIDL文件,且要和服务端的AIDL文件一致,就是和MsApplication的AIDL文件一致。剩下的就只需要通过Intent绑定到My Application的服务了。
My Application中MainActivity.java
public class MainActivity extends AppCompatActivity {
private IMyAidlInterface aidlInterface;
private ServiceConnection service = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//系统调用这个来传送在service的onBind()中返回的IBinder.
aidlInterface = IMyAidlInterface.Stub.asInterface(service);
try {
String string = aidlInterface.getString();
Log.e("", string);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
//service的连接意外丢失时调用这个.比如当service崩溃了或被强杀了.当客户端解除绑定时,这个方法不会被调用.
aidlInterface = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("com.example.msapplication.MainService");
intent.setPackage("com.example.msapplication");
bindService(intent, service, BIND_AUTO_CREATE);
}
});
findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
String string = aidlInterface.getString();
Log.d("///", string);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
}
结果验证:同时开启两个App 开启服务后 在另一个App中绑定服务,调用方法得到字符串