先总结一下:cilent绑定服务时通过自己项目中的 .aidl找到 对应实现service中的 .aidl。然后拿到对应service的stub实体,调用对应service的stub中的实现方法。
1、创建 .aidl 文件,并在需要调用的应用中也添加(所有文件下的包名,内容必须一致,否则会报错)。
package com.example.aidlservice.aidl;
interface IPerson {
String greet(String someone);
}
此时在gen目录下会自动生成aidl对应的java文件:
期中Stub需要留意。接下来会用到
2、在service中实现stub
IPerson.Stub stub = new IPerson.Stub() {
@Override
public String greet(String someone) throws RemoteException {
Log.i(TAG, "greet:"+someone);
return " greet!!!"+someone ;
}
};
并在onbind时返回:
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
return stub;
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind");
return true;
}
3、接下里在minifest中声明:
4、cilent 客户端使用:先实现 ServiceConnection方法。复写 onServiceConnected
private IPerson person;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("ServiceConnection", "DDD onServiceDisconnected() called");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("ServiceConnection", "CCC onServiceConnected() called");
person = IPerson.Stub.asInterface(service);
}
};
5、绑定及调用
case R.id.bt1:
Log.i(TAG, "绑定!BT1 ");
Intent intent = new Intent("android.intent.action.AIDLService");
bindService(intent, conn, Context.BIND_AUTO_CREATE);
break;
case R.id.bt2:
Log.i(TAG, "服务!BT2 ");
try {
String putin = "hahaha";
String result = person.greet(putin);
Log.i(TAG, "绑定!输入:"+putin+" 结果:"+result);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
6、如果多个应用全部都实现了service。那么调用时会调用第一个安装过的。第一个卸载后会调用第二个安装的,以此类推。
接下来我们今天想分享的是,SecurityException: Not allowed to bind to service Intent崩溃错误。
我们在使用:
时,安卓只是正常绑定,不应该绑定导致 Not allowed to bind to service Intent,更甚至崩溃。
结果排查了很久 ,发现service在静态注册时,忽视了一个重要的属性:android:exported="true"
这个属性默认为false。false时,会禁止外部其它应用 绑定或者启动此服务。
因此问题很明显了,加上这句android:exported="true",解决问题。(建议绑定service和启动service时,都得try 一下:SecurityException异常)
对于android:exported="true"的定义是:android:exported 是Android中的四大组件 Activity,Service,Provider,Receiver 四大组件中都会有的一个属性。
总体来说它的主要作用是:是否支持其它应用调用当前组件。
默认值:如果包含有intent-filter 默认值为true; 没有intent-filter默认值为false。
那么你在遇到此类崩溃时,是否是忘记加了这条属性了呢?