运行环境 小米-android 7.1.2。
首先,新建一个service project,然后new AIDL file。
直接默认,然后点击finish。
生成如下图所示函数,屏蔽掉,改成一个更加简单的函数。
改成
String getName();
然后点击Sync Project。
将android studio视图由Android模式切换成project模式,查看
app/build/generated/source/aidl目录下,IMyAidlInterface.aidl的同名文件IMyAidlInterface.java文件是否生成。若没有,请重新Sync Project。
下面开始新建service文件。切换回Android视图,在package目录下new service。
选择其默认设置,然后点击finish。
生成文件如下图所示。
定义内部类MyBinder并作为onBind的返回。具体如下:
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
//throw new UnsupportedOperationException("Not yet implemented");
return new MyBinder();
}
class MyBinder extends IMyAidlInterface.Stub{
@Override
public String getName() throws RemoteException {
return "test";
}
}
}
最后在manifest的service下增加
<intent-filter>
<action android:name="aidl.test.action">
<intent-filter>
至此,service就完成了。
下面新建一个client的project。然后将service目录下的aidl文件夹copy至client的main目录下(注意在project视图模式下完成此操作)。
这里要保证client和service中的aidl一致。
copy完后,Sync Project。要保证IMyAidlInterface.java文件生成。
然后修改MainActivity如下所示。
public class MainActivity extends AppCompatActivity {
private static final StringTAG ="MainActivity";
private IMyAidlInterface myAidlInterface;
private Button mButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = findViewById(R.id.button_test);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
Toast.makeText(MainActivity.this,
myAidlInterface.getName(),
Toast.LENGTH_SHORT).show();
}catch (RemoteException e) {
e.printStackTrace();
}
}
});
bindMyService();
}
private void bindMyService() {
Intent intent =new Intent();
intent.setPackage("com.demo.service");
intent.setAction("aidl.test.action");
bindService(intent,connection,BIND_AUTO_CREATE);
}
private ServiceConnection connection =new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name,
IBinder service) {
myAidlInterface = IMyAidlInterface.Stub.asInterface(service);
Log.d(TAG,"onServiceConnected" +myAidlInterface);
}
@Override
public void onServiceDisconnected(ComponentName name) {
myAidlInterface =null;
Log.d(TAG,"onServiceDisconnected");
}
};
}
然后就会Toast “test”。
如果是魅族手机的话需要修改一下bindMyService函数。
private void bindMyService() {
Intent intent =new Intent();
/*intent.setPackage("com.demo.service");
intent.setAction("aidl.test.action");*/
intent.setComponent(new ComponentName("com.demo.service",
"com.demo.service.MyService"));
startService(intent);
bindService(intent,connection,BIND_AUTO_CREATE);
}
下面来看aidl支持传递的参数类型,来给 String getName()加上参数。
String getName(byte aByte,int anInt,long aLong,
boolean aBoolean,float aFloat,double aDouble,char aChar,
String aString, CharSequence aCharSequence, inout List<String> aList,
inout byte[] bytes);
数组和List等类型前需要加上inout 才可以,不然sync project会报错,无法生产aidl的.java文件。
注意: 不支持short类型。
然后 如果需要从service中将数据回传至client,可以在service的 project中新建一个IMyAidlCallBack.aidl文件。然后将IMyAidlCallBack作为参数传入IMyAidlInterface中。
IMyAidlCallBack如下所示。写完后sync project。
package com.demo.service;
// Declare any non-default types here with import statements
interface IMyAidlCallBack {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void onCallBack(inout byte[] data);
}
IMyAidlInterface中如下所示:
package com.demo.service;
import com.demo.service.IMyAidlCallBack;
interface IMyAidlInterface {
String getName();
void setCallback(IMyAidlCallBack cb);
}
注意要手动写入import com.demo.service.IMyAidlCallBack;
//这个是sync project后生成IMyAidlCallBack.java文件。
然后在service中模拟增加一个产生数据的类(这里可以根据需求让service去做实际的事情,此处只是简单的模拟)。Data类中,模拟产生了byte[]数据,然后通过DataCallBackInterface传至MyBinder中,最后再传到Client端中。
public class Data {
private static final StringTAG ="Data";
private static Data mDataInstance;
private DataTask mDataTask;
private static DataCallBackInterface mDataCallBackInterface;
//如果不加static,在AsyncTask中会为null
public static Data getInstance(){
if (mDataInstance ==null){
return new Data();
}
return mDataInstance;
}
public void setDataCallBack(DataCallBackInterface dataCallBackInterface){
Log.d(TAG,"setDataCallBack");
mDataCallBackInterface = dataCallBackInterface;
}
public void createData(){
Log.d(TAG,"createData");
mDataTask =new DataTask();
mDataTask.
executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,0);
}
private class DataTaskextends AsyncTask {
@Override
protected String doInBackground(Integer... integers) {
Log.d(TAG,"doInBackground");
byte[] bytes = {0x1,0x2,0x3};
if (mDataCallBackInterface==null){
Log.d(TAG,"mDataCallBackInterface null" );
}else {
Log.d(TAG,"mDataCallBackInterface onCallBack" );
mDataCallBackInterface.onCallBack(bytes);
}
return null;
}
}
}
增加一个DataCallBackInterface。
public interface DataCallBackInterface {
void onCallBack(byte[] data);
}
再在IMyAidlInterface.aidl中增加一个函数void initData(),用于生成实际所需的数据。
MyService 中代码修改如下。
public class MyService extends Service {
...........
class MyBinder extends IMyAidlInterface.Stub{
............
@Override
public void setCallback(IMyAidlCallBack cb)throws RemoteException {
if (cb !=null){
Log.d(TAG,"setCallback");
mAidlCallbacks.register(cb);
}
}
@Override
public void initData() throws RemoteException {
if (mDataCallBackInterface ==null){
Log.d(TAG,"mDataCallBackInterface null");
}else {
Log.d(TAG,"mDataCallBackInterface setDataCallBack");
Data.getInstance().setDataCallBack(mDataCallBackInterface);
}
Data.getInstance().createData();
}
}
private DataCallBackInterface mDataCallBackInterface =
new DataCallBackInterface() {
@Override
public void onCallBack(byte[] data) {
sendDataToClientByAidlCallBack(data);
};
private void sendDataToClientByAidlCallBack(byte[] data) {
Log.d(TAG,"data length="+data.length);
final int N =mAidlCallbacks.beginBroadcast();
Log.d(TAG,"n is : " + N);
for (int i=0; i<N; i++) {
Log.d(TAG,"inner for");
try {
if(data.length>0){
Log.d(TAG," getBroadcastItem");
mAidlCallbacks.getBroadcastItem(i).onCallBack(data);
}
}catch (Exception e) {
e.printStackTrace();
}
}
mAidlCallbacks.finishBroadcast();
}
}
service 端到这里就修改完毕了。现在接着来改client端中的代码。
MainActivity中需增加一些代码。
public class MainActivity extends AppCompatActivity {
............
private IMyAidlCallBack mIMyAidlCallBack =new IMyAidlCallBack.Stub() {
@Override
public void onCallBack(byte[] data)throws RemoteException {
// AIDL传输的数据最终输出至client中的此处
Log.d(TAG,"IMyAidlCallBack onCallBack, data length = "+ data.length
+" data [0] = " + data[0] +" data [1] = " + data[1]);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
.....
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
Toast.makeText(MainActivity.this,
myAidlInterface.getName(),
Toast.LENGTH_SHORT).show();
myAidlInterface.setCallback(mIMyAidlCallBack);
myAidlInterface.initData();
}catch (RemoteException e) {
e.printStackTrace();
}
}
});
bindMyService();
}
..............
}
最后,运行client点击button时,打印log,有数据传回则表示成功。
IMyAidlCallBack onCallBack, data length = 3 data [0] = 1 data [1] = 2
————————————
完整代码地址:
https://github.com/VIVILL/AIDL
参考记录:
使用AIDL(二)传递数据
https://www.jianshu.com/p/f3789dd52092
你真的理解AIDL中的in,out,inout么?
https://www.jianshu.com/p/ddbb40c7a251
aidl的简单demo
https://blog.csdn.net/sinat_20059415/article/details/79770615
aidl中魅族无法绑定的坑
https://blog.csdn.net/cly19940419/article/details/79777881
AIDL的简单使用,涵盖5.0之后系统及魅族手机调用问题的解决
https://blog.csdn.net/wygsqsj/article/details/77894735