【非好文,写的不对之处欢迎指正。】
写在前面:
可能是执念在作怪,一直想要自己手写一个AIDL,翻阅网络上很多资料,介绍很多,可是就是在敲代码的时候遇到一些问题,实在没办法就去看文档敲,打算用极其简单的方式表达。让初学者能用最简单的方式完成一次不同进程间的通信。
介绍:
https://developer.android.google.cn/guide/components/aidl Developers开发文档
AIDL是什么?
官方文档是这么介绍的:AIDL(Android 接口定义语言)与您可能使用过的其他 IDL 类似。 您可以利用它定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口。
简单来讲就是不同进程进行通信的一种手段,在Android开发过程中,两个不同的进程是不可以互相通信的,那么我们就可以借助AIDL来实现两个进程通信。
说到这里那么我们会问,那么如何来编写呢?怎么去实现AIDL呢?
首先,我们准备两个端,一个客户端一个服务端,这个时候想要吐槽一下,网上有文章说要两个端的包名要一样,起初看到这里愣了很久。两个包名一样,怎么安装啊。。。。
其次创建AIDL文件
在服务端创建一个服务
在客户端创建服务器链接
以上四个步骤,完成一个简单的AIDL操作。
首先创建工程:
创建两个工程完成之后我们就开始来写服务端。
这个时候需要注意一点,AIDL能传递的参数
Java 编程语言中的所有原语类型(如
int
、long
、char
、boolean
等等)String
-
CharSequence
List
中的所有元素都必须是以上列表中支持的数据类型、其他 AIDL 生成的接口或您声明的可打包类型。 可选择将List
用作“通用”类(例如,List<String>
)。另一端实际接收的具体类始终是ArrayList
,但生成的方法使用的是List
接口。Map
中的所有元素都必须是以上列表中支持的数据类型、其他 AIDL 生成的接口或您声明的可打包类型。 不支持通用 Map(如Map<String,Integer>
形式的 Map)。 另一端实际接收的具体类始终是HashMap
,但生成的方法使用的是Map
接口。
这是文档上的原话。
另外还有一种方式就是实现Java的序列化:Parcelable
服务端编写
首先在项目工程中创建一个AIDL见下图
// 这个修改掉就好了,改成你想要的名字 ,还会生存一个模板方法,你不需要删掉就好了
// IRemoteServer.aidl
package com.xingge.server;
// Declare any non-default types here with import statements
interface IRemoteServer {
int handleNoThing(int s);
}
/**
我这里很简单,没有考虑到服务端和客户端进行通行,只是简单的客户端开启服务端
*/
#### 创建完毕之后记得点下AS上面的锤子,或者Build-> Make Project。
完成之后你会发现在server-Build->generated->source-> 生成一个aidl文件,内部有一个IRemoteServer接口 这里面有很多代码,这里就不做介绍了,想要看的童鞋,可以去看看,遇到好玩的或者有些坑都可以在下面留言一起进步.
接着写我们的服务代码
/**
* 佛曰:
* 写字楼里写字间,写字间里程序员;
* 程序人员写程序,又拿程序换酒钱。
* 酒醒只在网上坐,酒醉还来网下眠;
* 酒醉酒醒日复日,网上网下年复年。
* 但愿老死电脑间,不愿鞠躬老板前;
* 奔驰宝马贵者趣,公交自行程序员。
* 别人笑我忒疯癫,我笑自己命太贱;
* 不见满街漂亮妹,哪个归得程序员?
* ================================================
* 作 者:Yno (hxx)
* 版 本:
* 创建日期:2018/10/19 10:41
* 包 名: com.xingge.server
* 描 述:
* 修订历史:
* ================================================
*/
public class DDService extends Service {
@Override
public void onCreate() {
super.onCreate();
System.out.println("DDService onCreate........" + "Thread: " + Thread.currentThread().getName());
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(this, "服务器开启", Toast.LENGTH_SHORT).show();
System.out.println("服务器开启");
return mServer;
}
// 中间桥梁
private final IRemoteServer.Stub mServer = new IRemoteServer.Stub() {
@Override
public int handleNoThing(int s) throws RemoteException {
return s;
}
};
}
// 在AndroidManisfest.xml
<service
android:name=".DDService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="IRemoteServer" />
</intent-filter>
</service>
是不是很简单,服务端代码就写好了。 Activity里面不做任务操作。
客户端
上面完成服务端,下面我们就来完成下客户端代码。
再次之前,我们需要了解那些知识内容呢?
- Android两种启动服务的方式 // https://developer.android.google.cn/guide/components/bound-services#Binding
不了解的可以根据上面的地址详细的看下。
客户端同样的需要创建一个AIDL文件,要保证AIDL文件和服务端的AIDL相同,你也可以直接拷贝过去,不过需要注意一点。
加红标注的位子是你需要注意的,这个报名要注意更改。和当前项目的包名是一至的。到这一步和服务端创建的时候是相同的。没什么区别,就不在做详细的讲解了。
客户端代码
public class MainActivity extends AppCompatActivity {
private Button button;
// 获取进程桥梁对象
private IRemoteServer mServer;
// 创建服务链接
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Toast.makeText(MainActivity.this, "Service connected", Toast.LENGTH_SHORT).show();
// 初始化。
mServer = IRemoteServer.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Toast.makeText(MainActivity.this, "Service disconnected", Toast.LENGTH_SHORT).show();
// 服务关闭
mServer = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//
Intent intent = new Intent(IRemoteServer.class.getName());
intent.setClassName("com.xingge.server", "com.xingge.server.DDService");
// 进行绑定。
bindService(intent, mConnection, BIND_AUTO_CREATE);
}
});
}
}
这样一个简单的进程通信就完成了。
上面就是软件演示图了。。。OVER。