Android跨进程通信(二):AIDL使用教程2

文章目录

Android跨进程通信(一):AIDL使用教程1
Android跨进程通信(二):AIDL使用教程2
Android跨进程通信(三):Messenger使用教程
Android跨进程通信(四):AIDL源码解析
Android跨进程通信(五):Messenger源码解析

上一篇文章讲述如何编写服务端的代码,本篇文章讲解客户端代码的编写,并测试两程序的进程间通信。

编写客户端的AIDL代码

上篇文章也说过AIDL对包名要求很苛刻,因此在编写的时候要格外注意。

首先,切换为Project模式。
在这里插入图片描述
在main文件夹上创建一个新文件夹,一定要叫aidl。
在这里插入图片描述
按照下面这种方式创建一个aidl文件,然后不管它(这是为了解决Android Studio的一个"小"bug),这个步骤不能漏。
在这里插入图片描述
接着把服务端的aidl包一整个复制到客户端的aidl下。
在这里插入图片描述
复制后,客户端的aidl文件夹如下,注意此时的sensorapp文件夹是无效的,因为这个包名并不是完整的包名(这就是Android Studio的bug),完整的包名是com.pyjtlk.sensorapp,也就是服务端aidl文件的包名。
在这里插入图片描述
于是再在aidl下创建com.pyjtlk.sensorapp包,并把sensorapp的aidl文件复制进去,最终正确的结果如下。
在这里插入图片描述
把上面红色的零时包删掉,最后就在客户端上得到完整服务端包名的aidl。
在这里插入图片描述
通过同样的方法把服务端的SensorConfig.java文件也复制到客户端的java文件夹上(注意包名!)
在这里插入图片描述
至此,客户端的AIDL才算完成。先clean一下工程,再rebuild,如果没有错误提示,并生成对应的接口文件,那才算是真正的成功。

如果不成功,那就得仔细地核对服务端和客户端的aidl代码是否一致,通常是AIDL包名不一致导致错误的。

编写客户端Activity代码

相比于AIDL,java和xml就简单多了,先来看界面代码。很简单,就是一个文本框和三个按钮。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <TextView
        android:id="@+id/text_temp"
        android:layout_width="100dp"
        android:layout_height="50dp"/>

    <Button
        android:id="@+id/button_getTemp"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:text="getTemp"/>

    <Button
        android:id="@+id/button_open"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:text="open"/>

    <Button
        android:id="@+id/button_shut"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:text="shut"/>

</LinearLayout>

再来看看Activity的代码。在onServiceConnected方法中,客户端就能获取到服务端的Binder对象。

public class MainActivity extends AppCompatActivity {
    private TextView mTempText;
    private Button mGetButton;
    private Button mOpenButton;
    private Button mShutButton;

    private SensorServiceConnection mServiceConnection;
    private ISensorAidlInterface mSensorAidlInterface;

    private class SensorServiceConnection implements ServiceConnection{
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //得到来自服务端的Binder
            mSensorAidlInterface = ISensorAidlInterface.Stub.asInterface(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
        }
    }

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

        initView();
        bindService();
    }

    private void initView(){
        mTempText = findViewById(R.id.text_temp);
        mGetButton = findViewById(R.id.button_getTemp);
        mOpenButton = findViewById(R.id.button_open);
        mShutButton = findViewById(R.id.button_shut);

        mGetButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    //跨进程通信,获取服务端的传感器温度值
                    double temperature = mSensorAidlInterface.getTemperature();
                    mTempText.setText(temperature + "℃");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });

        mOpenButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    SensorConfig sensorConfig = new SensorConfig();
                    sensorConfig.setSensorName("TI Temperature Sensor");
                    sensorConfig.setCmd("open temperature sensor");
                    //跨进程发送对象
                    mSensorAidlInterface.setSensor(sensorConfig);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });

        mShutButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    SensorConfig sensorConfig = new SensorConfig();
                    sensorConfig.setSensorName("TI Temperature Sensor");
                    sensorConfig.setCmd("shut temperature sensor");
                    //跨进程发送对象
                    mSensorAidlInterface.setSensor(sensorConfig);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private void bindService(){
    	//这是隐式启动Service的方法,Android5.0开始就不支持了
		//Intent intent = new Intent("com.pyjtlk.sensorapp.SensorService"); 
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.pyjtlk.sensorapp","com.pyjtlk.sensorapp.SensorService"));

        mServiceConnection = new SensorServiceConnection();
		
        bindService(intent,mServiceConnection,BIND_AUTO_CREATE);
    }
}

终于写完了服务端和客户端的代码,接下来就进行测试。

测试

首先,通过debug模式启动服务端,不要退出。再启动客户端应用。

点击第一个按钮,客户端就获取到了服务端的温度值。
在这里插入图片描述
两个应用真的跨进程通信了吗?下面来做第二个测试。

打开服务端的代码在SensorService.java的setSensor方法上设一个断点。然后点击客户端App的第二个按钮。
在这里插入图片描述
如下图,服务端断点被拦截,说明客户端跨进程发送的对象确实被服务端收到了。
在这里插入图片描述

最后

服务端和客户端都放在Gitee代码仓库里了。

下一篇文章我们来看看如何使用Messenger来实现跨进程通信。对AIDL原理感兴趣的朋友可以看看这篇文章

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值