概述
文章目录
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原理感兴趣的朋友可以看看这篇文章。
最后
以上就是内向板凳为你收集整理的Android跨进程通信(二):AIDL使用教程2的全部内容,希望文章能够帮你解决Android跨进程通信(二):AIDL使用教程2所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复