【Android】binder对象传送的例子

通过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方法

 

猜你喜欢

转载自blog.csdn.net/aaajj/article/details/105870608