IPC ,目标Service常驻后台。
应用层, binder驱动,binder
native层。
service_manager.c
binder.c
binder.h
2.IPC 进程间通信小示例
IPC,aidl,Binder驱动。
app之间通信的协议叫 aidl,app进程之间不共享,需要通信。
2.1 服务端
package com.tom.joke;
// Declare any non-default types here with import statements
interface UserAidl {
String getUserName();
String getUserPwd();
}
<!--隐式启动A应用调用B应用 service-->
<service android:name=".MessageService"
android:exported="true">
<intent-filter>
<action android:name="com.study.aidl.user"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
// 服务端。
public class MessageService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private final UserAidl.Stub mBinder = new UserAidl.Stub() {
@Override
public String getUserName() throws RemoteException {
return "Darren@163.com";
}
@Override
public String getUserPwd() throws RemoteException {
return "19940223";
}
};
}
// 启动一个服务,等待B应用来连接。调用
private void startServiceForB() {
startService(new Intent(this, MessageService.class));
}
2.2 Client端
// A应用端。client端。
public class MainActivity extends AppCompatActivity {
private ServiceConnection mServiceConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("Service", "onServiceConnected "+ name.getClassName());
// 连接好了
mUserAidl = UserAidl.Stub.asInterface(service);
Toast.makeText(MainActivity.this, "onServiceConnected:" , Toast.LENGTH_LONG).show();
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d("Service", "onServiceDisconnected "+ name.getClassName());
// 断开连接
Toast.makeText(MainActivity.this, "onServiceDisconnected:" , Toast.LENGTH_LONG).show();
}
};
// 客户端一定要获取aidl的实例,这个实例时服务端返回的。
private UserAidl mUserAidl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService();
}
@Override
protected void onDestroy() {
unBindService();
super.onDestroy();
}
private void bindService() {
Intent intent = new Intent();
intent.setAction("com.study.aidl.user");
// 5.0后,为了安全问题,禁止了隐式声明Intent来启动Service
// 也禁止使用 IntentFilter,否则就会抛异常。
intent.setPackage("com.tom.joke"); // 目标apk的包名
bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);
}
public void unBindService() {
if (mUserAidl != null) {
unbindService(mServiceConn);
}
}
// 获取用户名,获取密码
public void getUserName(View view) {
if (mUserAidl != null) {
try {
String name = mUserAidl.getUserName();
Toast.makeText(this, "userName:" + name, Toast.LENGTH_LONG).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
public void getPassword(View view) {
if (mUserAidl != null) {
try {
String password = mUserAidl.getUserPwd();
Toast.makeText(this, "password:" + password, Toast.LENGTH_LONG).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}
3.应用层具体的流程
C/S 每端都会有Stub 和 Proxy。中间有ServiceManager。
// Binder.java
/**
* Default implementation rewinds the parcels and calls onTransact. On
* the remote side, transact calls into the binder to do the IPC.
*/
public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,
int flags) throws RemoteException {
if (false) Log.v("Binder", "Transact: " + code + " to " + this);
if (data != null) {
data.setDataPosition(0);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
总结:client端调用 transact() 方法,最后调用服务端的onTransact()
3.1 bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);
就会调用进入 MessageService,绑定后 拿到mBinder对象。 mBinder 是 new UserAidl.Stub()
Stub 继承自 android.os.Binder
onServiceConnected 里面拿到的 IBinder,实际就是 MessageService里面的 mBinder。
mUserAidl = UserAidl.Stub.asInterface(service); // service就是服务端给我们的IBinder
return new com.tom.joke.UserAidl.Stub.Proxy(obj); // 最终拿到Proxy
// Client客户端
@Override public java.lang.String getUserName() throws android.os.RemoteException
{
_data.writeInterfaceToken(DESCRIPTOR);
// 1.调用的是 IBinder 服务端返回的实例 mRemote。 传入code值。
boolean _status = mRemote.transact(Stub.TRANSACTION_getUserName, _data, _reply, 0);
// 5. Service端onTransact,执行结束。可拿到_status状态。
_reply.readException();
// 6. 把值从_reply中读出来。读取用户名数据
_result = _reply.readString();
return _result; // 7. 将值返回。
}
// 8. 拿到步骤7 返回的值。用于打印。
// Server 服务端
// 上面的transact方法,就回来到服务端的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_getUserName:
{
data.enforceInterface(descriptor);
java.lang.String _result = this.getUserName(); // 2.拿到用户名,用于返回。
reply.writeNoException();
reply.writeString(_result); // 3.写入数据,将用户名数据写入到reply,这个reply是客户端传进来的。
return true; // 4.返回状态true。
}
网友评论