AIDL进程间通信;AIDL(Android Interface Design Language)
▲№aidl接口语法:
1、支持package 和 import等关键字
支持void interface等关键字
2、不支持访问修饰符
3、接口中不能定义常量只能定义方法
4、参数类型或返回类型:
a、基本类型
b、CharSequence
c、String
d、List
e、Map
f、Parcelable 可打包对象
5、基本类型、CharSequence、String、List和Map在使用时不需要导包,除此之外的所有类型,使用时必须import,即便该类型与接口定义在同一包中也如此
★№[匿名内部类 class A{new B(){},new C(){}},B和C和引用名称为:A.$1,A.$2;]
★№AIDL实现跨进程通信原理:在服务端Service和客户端(另一个进程的Activity)共用一个公用的接口,该接口使用AIDL定义,Android系统将该接口实现IInterface的方法并会自动生成该接口的跨进程实现类,
public static abstract class Stub extends Binder implements
com.fanfan.aidl.musicplay.MusicPlayControllor{ ... }
生成的Stub类继承了Binder即可通过进程边界进行跨进程通信,而又实现了AIDL定义的接口,则可实现该接口下的所有方法。
在客户端定义相同的AIDL接口(包名相同),同样会生成该接口的跨进程实现类Stu;但系统会进行判断,该客户端是否是在同一进程内,若不在同一进程内,则会生成Stu类的代理Stu.Proxy(obj);
●内部代码为:
public static com.fanfan.aidl.musicplay.MusicPlayControllor asInterface(android.os.IBinder obj)
{
if (((iin!=null)&&(iin instanceof com.fanfan.aidl.musicplay.MusicPlayControllor))) {
return ((com.fanfan.aidl.musicplay.MusicPlayControllor)iin);
}
return new com.fanfan.aidl.musicplay.MusicPlayControllor.Stub.Proxy(obj);
}
另外一个进程的客户端通过该代理,扩展该代理Stu.Proxy(obj);即可调用服务端下的所有方法。
▲☆实现步骤:
§服务端
1、在服务端定义 ***.aidl文件(定AIDL接口)
2、在Service中的onBind方法返回AIDL.Stub类的对象
3、在注册Service时,指定一个隐式意图;
<action android:name="com.fanfan.action.MUSIC_PLAYER_SERVICE"/>
▲☆客户端:
1、创建与服务端一样的AIDL接口,包名必须一样。
2、创建ServiceConnection对象,在其onServiceConnected方法中将参数IBinder对象传入到AIDL接口.Stub.asInterface方法中作参数获得一个AIDL接口对象,如
1、创建与服务端一样的AIDL接口,包名必须一样。
2、创建ServiceConnection对象,在其onServiceConnected方法中将参数IBinder对象传入到AIDL接口.Stub.asInterface方法中作参数获得一个AIDL接口对象,如 : controllor = MusicPlayControllor.Stub.asInterface(binder);
3 、 用service注册时的action创建要绑定的Service:
Intent intent = new Intent("com.fanfan.action.MUSIC_PLAYER_SERVICE");
4、调用bindService方法绑定到Service: bindService(intent, conn, BIND_AUTO_CREATE);
5、通过AIDL接口对象去调用服务端的方法
6、在onDestroy方法中解除绑定:unbindService(conn);
◆电话操作:
通话记录管理:
相关表:
calls : _id number duration date type(对应的 有:Calls.INCOMING_TYPE、Calls.MISSED_TYPE、Calls.OUTGOING_TYPE)
★ 相关的API: CallLog Calls
▲呼出电话的监听
当电话呼出时,会发送一个系统广播Intent.ACTION_NEW_OUTGOING_CALL
可以在广播中获取呼出号码的信息。
1)getResultData()
2)intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
★☆无法使用abortBroadcast()取消通话,但可使用setResultData(null)取消,也可用setResultData("18545006310")将呼出电话进行更改;
使用权限:android.permission.PROCESS_OUTGOING_CALLS
在真机上还需权限:android:name="android.permission.READ_CONTACTS"
▲呼入电话的监听:
1、获取TelephoneManager实例:tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
2、可通过tm获得关于手机许多信息:
tm.getCallState()); //通话状态 空闲(TelephonyManager.CALL_STATE_IDLE) 摘机(占线) TelephonyManager.CALL_STATE_OFFHOOK、响铃TelephonyManager.CALL_STATE_RINGING;
tm.getCellLocation());// 通话位置,开了gps可获取精确位置,否则是模糊位置
tm.getDeviceId());//设备ID
tm.getDeviceSoftwareVersion());
tm.getLine1Number()); // 本机号码;
tm.getNetworkCountryIso());//
tm.getNetworkOperator());// 手机运营商
tm.getNetworkOperatorName());//运营商名
tm.getPhoneType());//手机电话类型,GSM/CDMA
tm.getSimCountryIso());// sim卡信息
tm.getSimSerialNumber());// sim卡序列号;
tm.getSubscriberId());// sim卡识别序列码子码
tm.isNetworkRoaming());// 是否支持漫游
tm.getNetworkType());// 网络类型;
tm.getVoiceMailAlphaTag());//信箱类型
tm.getVoiceMailNumber());// 音量
★№ 要监听呼入电话
可在一个Service中创建一个电话监听器: listener = new PhoneStateListener() {} 包含许多可回调的方法,若只监听通话状态,可重写onCallStateChanged(..)方法;
利用电话管理器对电话进行监听:tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);//第二个参数为要监听的状态
必须在onDestroy方法中取消该监听,否则会出现内存泄露:
tm.listen(listener, PhoneStateListener.LISTEN_NONE);
//参数为NONE时表示什么都不监听,即可取消监听器。
★☆ 挂断:需要取出系统类ITelephony,该类包含对呼入电话的许多方法,但在系统被标记为{@hide},即被隐藏,若需要获取此实例,须导入相关的AIDL接口文件,并利用反射机制获得相关方法;
Method method = Class.forName("android.os.ServiceMananger")// 需要要加载的类名.getDeclaredMethod("getService",String.class);//需要调用方法名和需要的参数
IBinder binder = (IBinder) method.invoke(null,TELEPHONY_SERVICE);// 参数分别为接收的对象和参数名
ITelephony tle = ITelephony.Stub.asInterface(binder); // 通过AIDL获得Service为本地代理 // 调用ITelePhony下的方法 // tle.call(number); //拨打电话,需要root // tle.answerRingingCall();//接听电话,需要root
tle.endCall();// 挂断电话,可用于防骚扰;
博客地址:Android学习笔记(七)