通过bindService方法去获取服务端的代理对象,进而来调用aidl文件中定义的方法,其本质过程是binder对象的传递,通过AMS来把server端的binder对象传递给客户端
server端
IMathService.aidl
package com.sunday.aidl;
interface IMathService
{
long add(long a, long b);
}
在gen目录下会自动生成IMathService.java文件
MathService.java
package com.sunday.aidl;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class MathService extends Service
{
public class MathServiceImpl extends IMathService.Stub
{
@Override
public long add(long a, long b)
{
return a + b;
}
}
@Override
public IBinder onBind(Intent intent)
{
return new MathServiceImpl();
}
}
在AndroidManifest.xml中添加service记录
client端
MainActivity.java
public class MainActivity extends ActionBarActivity implements OnClickListener{
private myConnection serviceConnection = new myConnection();
private IMathService myService = null;
public class myConnection implements ServiceConnection
{
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
myService = IMathService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name)
{
}
}
@Override
public void onClick(View view)
{
try {
long ret = myService.add(2017, 1);
Toast.makeText(this,
"The result is " + ret, Toast.LENGTH_LONG).show();
} catch (Exception e) {
// TODO: handle exception
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService(new Intent("com.sunday.aidl.IMathService"),
serviceConnection, BIND_AUTO_CREATE);
Button aButton = (Button)findViewById(R.id.button1);
aButton.setOnClickListener(this);
}
查看进程
1|Unknown:/ # ps | grep aidl
u0_a103 28072 608 1771868 71060 SyS_epoll_ 792c011794 S com.example.aidlclient
u0_a102 28108 608 1715168 46232 SyS_epoll_ 792c011794 S com.sunday.aidl
每一步都是binder通信调用
开光理论
研究bindService的处理,验证开光理论
服务端获取到了user服务的IBinder对象,然后将其返回给客户端使用,客户端可以使用,这就是IBinder对象的传递。
myServer.cpp
#include <stdio.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <binder/IBinder.h>
#include <binder/Binder.h>
#include <binder/ProcessState.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
using namespace android;
//
sp<IBinder> aBinder = NULL;
class myBinder : public BBinder
{
public:
status_t dump(int fd, const Vector<String16>& args)
{
write(fd, "myBinder dump called ", 22);
return NO_ERROR;
}
status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t /*flags*/)
{
switch (code) {
case DUMP_TRANSACTION: {
printf("dump called\n");
int fd = data.readFileDescriptor();
int argc = data.readInt32();
Vector<String16> args;
for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
args.add(data.readString16());
}
return dump(fd, args);
}
case 2: {
int num = data.readInt32();
printf("onTransact called, case 2, num = %d\n", num);
reply->writeInt32(num * 2);
return NO_ERROR;
}
case 3:{
printf("onTransact called, case 3\n");
reply->writeStrongBinder(aBinder);
return NO_ERROR;
}
}
return NO_ERROR;
}
};
int main()
{
sp < ProcessState > proc(ProcessState::self());
sp < IServiceManager > sm = defaultServiceManager();
//get service
sp<IBinder> service = sm->checkService(String16("user"));
if (service != NULL) {
printf("get service\n");
aBinder = service;
}
sm->addService(String16("myService"), new myBinder());
printf("add myService\n");
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
myClient.cpp
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <binder/TextOutput.h>
#include <utils/Vector.h>
#include <binder/BpBinder.h>//
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
using namespace android;
int main(int argc, char* const argv[])
{
sp<IServiceManager> sm = defaultServiceManager();
fflush(stdout);
if (sm == NULL)
{
ALOGE("Unable to get default service manager!");
aerr << "dumpsys: Unable to get default service manager!" << endl;
return 20;
}
Vector<String16> args;
sp<IBinder> service = sm->checkService(String16("myService"));
int err = service->dump(STDOUT_FILENO, args);
if (err != 0) {
aerr << "Error dumping service info: (" << strerror(err)
<< ") " << endl;
}
if (argc <= 1)
{
// printf("argc <= 1\n");
return 1;
}
int num = atoi(argv[1]);
printf("num = %d\n", num);
Parcel data;
Parcel reply;
data.writeInt32(num);
err = service->transact(3, data, &reply, 0);
if (err == NO_ERROR)
{
// reply.setDataPosition(0);
printf("\nget reply \n");
sp<IBinder> sBinder = reply.readStrongBinder();
//会调用user服务的dump方法
sBinder->dump(STDOUT_FILENO, args);
}
return 0;
}
Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
myServer.cpp
LOCAL_SHARED_LIBRARIES := \
libbase \
libutils \
liblog \
libbinder
ifeq ($(TARGET_OS),linux)
LOCAL_CFLAGS += -DXP_UNIX
#LOCAL_SHARED_LIBRARIES += librt
endif
LOCAL_MODULE:= bServer
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
myClient.cpp
LOCAL_SHARED_LIBRARIES := \
libbase \
libutils \
liblog \
libbinder
ifeq ($(TARGET_OS),linux)
LOCAL_CFLAGS += -DXP_UNIX
#LOCAL_SHARED_LIBRARIES += librt
endif
LOCAL_MODULE:= bClient
include $(BUILD_EXECUTABLE)
测试
Unknown:/data/local/tmp # ./bServer
get service
add myService
dump called
onTransact called, case 3
Unknown:/data/local/tmp # ./bClient 0
myBinder dump called num = 0
get reply
Users:
UserInfo{0:null:13} serialNo=0
Created: <unknown>
Last logged in: +13d1h6m53s828ms ago
执行了user服务的dump方法