Binder基本使用

Android开发中,Binder是一种跨进程通信方式,而使用AIDL可以实现Binder的工作。

如何使用它是了解它的第一步,本文章主要记录使用Binder的一些步骤。(代码思路参考《Android开发艺术探索》任玉刚 著)

1.创建两个activity

两个activity(OneActivity、TwoActivity),将OneActivity假设为服务端,TwoActivity假设为客户端,分别运行在不同进程中

在AndroidManifest.xml中,为TwoActivity设置进程,这样两个activity就分别运行在不同的进程中了

<activity android:name=".TwoActivity" android:process=":test"/>

2. 创建AIDL文件

在AIDL文件中声明客户端想要调用服务端的方法

interface IInfManager {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void setName(String name);

    String getName();
}

AIDL文件声明完,activity等文件并不能调用到IInfManager接口,需要在app的build.gradle文件中的android{}中添加

sourceSets{
    main{
        java.srcDirs = ['src/main/java', 'src/main/aidl']
    }
}

然后点击sync now按钮,activity文件就可以调用到IInfManager接口了,可以在app\build\generated\source\aidl\debug文件下找到自动生成的IInfManager.java文件。

3.创建Service

Service中创建Binder对象,在onBind方法中返回这个对象,Binder对象中具体实现了IInfManager接口中的方法。Service需要在AndroidManifest.xml中注册。

public class InfManageService extends Service{

    private String name;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        name = intent.getStringExtra("name");
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    private Binder binder = new IInfManager.Stub() {
        @Override
        public void setName(String mName) throws RemoteException {
            name = mName;
        }

        @Override
        public String getName() throws RemoteException {
            return name;
        }
    };
}

4.服务端OneActivity

OneActivity中设置按钮跳转至TwoActivity,这里为了简单,使用startService可以为InfManageService中name变量初始化"zhangsan"的值。也可以与客户端TwoActivity中一样,绑定service,建立连接,来设置name的值(具体参考下一步客户端的用法)。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_one);

    Intent intent = new Intent(OneActivity.this, InfManageService.class);
    intent.putExtra("name", "zhangsan");
    startService(intent);

    btn_one_gototwo = (Button) findViewById(R.id.btn_one_gototwo);

    btn_one_gototwo.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(OneActivity.this, TwoActivity.class);
            startActivity(intent);
        }
    });
}

5.客户端TwoActivity

首先绑定InfManageService服务,建立连接,连接成功后通过返回的IBinder对象可以获得IInfManager接口,可以通过这个接口去使用服务端的方法。

private TextView tv_two_name;
private Button btn_two_change;

private IInfManager iInfManager;

private ServiceConnection connection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        iInfManager = IInfManager.Stub.asInterface(service);
        try {
            tv_two_name.setText(iInfManager.getName());
            Log.i("TwoActivity","first:" + iInfManager.getName());
            iInfManager.setName("lisi");
            Log.i("TwoActivity","next:" + iInfManager.getName());
        }catch (RemoteException e){

        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
};

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_two);

    tv_two_name = (TextView) findViewById(R.id.tv_two_name);
    btn_two_change = (Button) findViewById(R.id.btn_two_change);

    Intent intent = new Intent(TwoActivity.this, InfManageService.class);
    bindService(intent, connection, Context.BIND_AUTO_CREATE);

    btn_two_change.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            try {
                iInfManager.setName("wangmazi");
                tv_two_name.setText(iInfManager.getName());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    });
}

@Override
protected void onDestroy() {
    super.onDestroy();
    unbindService(connection);
}

上面代码onServiceConnected方法中,首先在TwoActivity界面中显示了服务端的name变量内容"zhangsan"

然后通过setName修改name变量为"lisi"(在log日志中查看打印信息,需要选择进程,此例子需要选择后缀为.test的进程)

点击TwoActivity中内容改变按钮,可以看到服务端的name变量内容改为了"wangmazi"

 

 

<think>好的,我现在需要回答用户关于AndroidBinder机制使用示例的问题。用户之前已经询问过Binder机制,现在他们需要具体的示例。首先,我需要回顾Binder机制的基本概念,确保自己理解正确。BinderAndroid中用于进程间通信(IPC)的核心机制,允许不同进程之间的组件进行交互,比如Activity与Service之间的通信。 接下来,我需要考虑用户可能需要的示例类型。通常,使用Binder的场景包括跨进程调用Service、AIDL(Android接口定义语言)的使用,以及Messenger的实现。这些都是常见的Binder应用案例。因此,我应该准备这些方面的示例。 首先想到的是AIDL,因为这是Android开发中直接使用Binder的典型方式。AIDL允许开发者定义接口,然后系统会自动生成对应的Binder代码。需要详细描述创建AIDL文件的步骤,以及如何在Service中实现该接口,客户端如何绑定并调用方法。同时,要注意代码示例的正确性,确保语法正确,比如在Java中使用Stub和asInterface方法。 另一个例子是使用Messenger进行进程间通信。Messenger基于AIDL实现,但更简化,适合消息队列的通信方式。这里需要说明如何创建Service端的Messenger,处理消息,以及客户端如何发送消息。代码示例应包括Handler的实现和Messenger的发送机制。 还需要考虑直接继承Binder类的情况,适用于同一进程内的通信。这种情况下,Service直接返回Binder对象,客户端通过它调用方法。这个例子相对简单,但能帮助用户理解Binder的基础使用。 在整理这些示例时,要确保每个步骤清晰,代码格式正确,并符合用户之前提到的系统级指令,比如使用$...$和$$...$$格式。同时,引用之前提供的参考资料,特别是引用[3]中提到的Binder如何支持系统设计的灵活性,可以在适当的地方加入引用标识。 可能还需要验证每个示例的正确性,比如检查AIDL生成的代码是否符合预期,Messenger是否正确地处理消息。此外,要提醒用户注意跨进程通信的权限问题和线程安全,因为Binder调用默认是在主线程执行的,长时间操作可能导致ANR,建议使用子线程处理。 最后,生成相关问题,帮助用户进一步探索,比如性能优化、Binder传输数据限制等。这些问题应该与用户的当前问题相关,并引导他们深入了解Binder机制的其他方面。 总结一下,回答需要结构清晰,分点说明不同使用示例,提供代码片段,并引用相关资料。同时,确保语言简洁,符合中文表达习惯,避免技术术语使用不当。</think>### Android Binder机制使用示例 Binder机制在Android系统中主要用于**跨进程通信(IPC)**,以下是三种典型使用场景的代码示例和说明: --- #### 1. **通过AIDL实现跨进程通信** **步骤说明**: 1. **定义AIDL接口**:创建文件`IMyService.aidl` ```aidl interface IMyService { int add(int a, int b); } ``` 系统会自动生成对应的Java接口(如`IMyService.Stub`)[^3]。 2. **实现Service**: ```java public class MyService extends Service { private final IMyService.Stub binder = new IMyService.Stub() { @Override public int add(int a, int b) { return a + b; } }; @Override public IBinder onBind(Intent intent) { return binder; } } ``` 3. **客户端调用**: ```java ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { IMyService myService = IMyService.Stub.asInterface(service); int result = myService.add(3, 5); // 跨进程调用 } }; bindService(new Intent(this, MyService.class), connection, BIND_AUTO_CREATE); ``` --- #### 2. **使用Messenger进行进程间通信** **场景**:适合基于消息的简单通信(如Activity与后台Service交互)。 1. **Service端实现**: ```java public class MessengerService extends Service { static final int MSG_SAY_HELLO = 1; class IncomingHandler extends Handler { @Override public void handleMessage(Message msg) { if (msg.what == MSG_SAY_HELLO) { // 处理消息并回复 Messenger client = msg.replyTo; Message reply = Message.obtain(null, MSG_SAY_HELLO); try { client.send(reply); } catch (RemoteException e) { /*...*/ } } } } final Messenger messenger = new Messenger(new IncomingHandler()); @Override public IBinder onBind(Intent intent) { return messenger.getBinder(); // 返回Binder对象 } } ``` 2. **客户端发送消息**: ```java ServiceConnection connection = new ServiceConnection() { private Messenger serviceMessenger; @Override public void onServiceConnected(ComponentName name, IBinder binder) { serviceMessenger = new Messenger(binder); Message msg = Message.obtain(null, MSG_SAY_HELLO); msg.replyTo = clientMessenger; // 设置回复Messenger serviceMessenger.send(msg); } }; ``` --- #### 3. **直接继承Binder类(同进程通信)** **场景**:同一进程内组件绑定(如Activity绑定本地Service)。 1. **Service实现**: ```java public class LocalService extends Service { private final IBinder binder = new LocalBinder(); public class LocalBinder extends Binder { LocalService getService() { return LocalService.this; } } @Override public IBinder onBind(Intent intent) { return binder; // 返回Binder实例 } public void customMethod() { /*...*/ } } ``` 2. **客户端调用**: ```java LocalService service; ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder binder) { LocalService.LocalBinder localBinder = (LocalService.LocalBinder) binder; service = localBinder.getService(); service.customMethod(); // 直接调用Service方法 } }; ``` --- ### 关键注意事项 1. **线程模型**:Binder调用默认在主线程执行,耗时操作需异步处理。 2. **数据序列化**:跨进程传输对象需实现`Parcelable`接口,如: ```java public class MyData implements Parcelable { private int value; // Parcelable实现代码... } ``` 3. **权限控制**:可通过`<permission>`标签声明跨进程访问权限。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值