安卓漫漫路之AIDL传递简单数据.

时间:2022-11-08 22:38:17

AIDL:Android Interface Define Language(Android接口定义语言),

主要用于服务端与客户端进程间通信(当然也可以多客户端);

大写的PS:  远离手机,没事就得多抬头.

二月二,龙抬头,天子耕地臣赶牛,春耕夏耘率天下,五谷丰登太平秋。
言归正传:Android中跨进程间通信方式有很多种方式: 比如 aidl, Messenger, 文件共享, 广播(BroadCast), ContentProvider,Socket(网络通信)  ,每种方式都有自己的使用场景和优缺点.

AIDL默认情况下只能传递基本类型、String、List、Map、CharSequence。下篇讲解传递复杂数据类型.

本章由我给您介绍使用Android Studio实现跨进程传递简单数据String类型(aidl);

--------------------------------------------------------

首先配上服务端的代码,也就是咱们的AppOne的代码:

第一步 : 创建AIDL文件.

步骤:File –> New –> AIDL –> AIDL File 完成创建之后(默认名称),

可以看到src/main的目录下生成了一个IMyAidlInterface.aidl文件.

不管他默认生成什么方法.咱们把他改成咱们想要的方法.例如:

package com.it.heima.;
interface IMyAidlInterface {
String getValue();
}




然后手动编译,clean | rebuild | make moudle "app";当然最后一个是最合适的,前者都太耗时.

然后怎么查看是否编译成功呢?

成功的话会在app/build/generated/sourse/aidl/debug/com.it.heima/下给咱们生成一个IMyAidlInterface接口.

第二步 : 创建远程服务Service.

package com.it.heima;
import com.it.heima.IMyAidlInterface;
public class MyService extends Service {
IMyAidlInterface.Stub stub = new IMyAidlInterface.Stub(){

@Override
public String getValue() throws RemoteException {
return "这是服务端返回的内容";
}
};
@Override
public IBinder onBind(Intent intent) {
return stub;
}
}



PS : IMyAidlInterface.Stub即为服务端AIDL文件的代理对象.

第三步 : 在AndroidMenifest.xml中的application标签中配置Service.

<!-- MyService -->
<service
android:name=".MyService"
android:process=":remote">
<intent-filter>
<action android:name="com.it.heima.MyService" />
</intent-filter>
</service>





Android系统最大的进程是com.android.phone.

process: 如果不自己指定的话此service默认运行在自己的包的进程中,也就是com.it.heima进程中.

如果自己指定的话会运行在com.it.heima:remote;

加不加冒号又分两种区别 : 

一,加冒号 : 表示该服务所在的进程是私有的.当客户端需要该service时,系统会自动创建新进程.

二,不加冒号,表示该服务所在的进程是共享的,当几个客户端都需要该service时,会共用一个进程.


至此服务端的配置完毕.

-----------------------------------------------------------------------------------------

配置客户端的代码,也就是咱们的AppTwo的代码:

第一步 : 需要将服务端的main/aidl包拷贝到客户端的app/main下.手动编译.查看是否成功.

第二步 : 客户端绑定服务端服务(远程服务).

package com.it.baima;
import com.it.heima.IMyAidlInterface;
public class MainActivity extends Activity implements View.OnClickListener {
private IMyAidlInterface mService;
private Button btn_bind, btn_get;
private TextView tv;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IMyAidlInterface.Stub.asInterface(service);
}

@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
};

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

private void init() {
btn_bind = (Button) findViewById(R.id.btn_bind);
btn_get = (Button) findViewById(R.id.btn_get);
tv = (TextView) findViewById(R.id.tv);

btn_bind.setOnClickListener(this);
btn_get.setOnClickListener(this);
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_bind:
Intent intent = new Intent();
intent.setAction("com.it.heima.MyService");
//从 Android 5.0开始 隐式Intent绑定服务的方式已不能使用,所以这里需要设置Service所在服务端的包名
intent.setPackage("com.it.heima");
bindService(intent, connection, Context.BIND_AUTO_CREATE);
break;
case R.id.btn_get:
try {
String str = mService.getValue();
tv.setText(str);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
}
}

@Override
protected void onDestroy() {
super.onDestroy();
if (serviceConnection != null) {
unbindService(connection);
}
}

}




就是一个简单的界面上方有两个Button(bindButton和getButton),和一个TextView.

首先点击bindButton后通过bindService绑定服务端的MyService.

通过 mService = IMyAidlInterface.Stub.asInterface(service)

可以获取到服务端的代理对象,从而可以通过回调方法从服务端获取到我们所需的数据从而展示到我们的客户端.


运行AppTwo,点击bindButton,好的已经绑定好了服务,再点击getButton通过回调方法获取到AppOne的数据.并且等待下方的TextView改变字体.我去,我裤子都脱了你给我看空指针异常?好吧,log指示getValue为空.怎么为空呢?咱们明明return了一个字符串啊.后来一想...AppOne都没有运行到咱们的手机上.从哪里访问服务呢?setAction,setPackage的操作都白做了,系统根本找不到啊.想让进程间通讯怎么只能运行一个进程呢?赶紧把咱们的AppOne先运行到手机上,这样两个进程都存在,才叫进程间通讯嘛.再运行一下看看咱们的AppTwo,好的,这回裤子没白脱.


传递复杂数据类型.请看大牛文章Android进程间通信之----Aidl传递对象




如有问题请多指正,您的指正使我更正确的前行.