首先介绍一下AIDL

AIDL简介

AIDL(AndRoid接口描述语言)是一种借口描述语言;编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的.如果需要在一个Activity中,访问另一个Service中的某个对象,需要先将对象转化成 AIDL可识别的参数(可能是多个参数),然后使用AIDL来传递这些参数,在消息的接收端,使用这些参数组装成自己需要的对象.

我的理解它和java中的RMI的概念差不多,在这里我就不相信讲解什么事AIDL 了。既然AIDL是既然是可以在不同进程间(IPC)进行操作。

下面我来通过一个简单的两个项目实例来讲解,一个是Server,一个是Client.

在Server客户端。

1.创建一个文件ITestService.aidl,如下所示:

package com.lifeblood; interface ITestService { int getAccountBalance(); void setOwnerNames(in List<String> names); int getCustomerList(in String branch, out String[] customerList); void showTest(); }

2.创建TestService.java类,该类继承Service类,实现public IBinder onBind(Intent intent)方法,

如下所示:

@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubmContext = this;return binder;//返回AIDL接口实例化对象}


同时在该类中,实例化ITestService.stub字柄

//实现AIDL接口中各个方法private ITestService.Stub binder = new Stub(){private String name = null;public int getAccountBalance() throws RemoteException {// TODO Auto-generated method stubreturn 100000;}public int getCustomerList(String branch, String[] customerList)throws RemoteException {// TODO Auto-generated method stubcustomerList[0] = name;System.out.println("Name:"+branch);return 0;}public void setOwnerNames(List<String> names) throws RemoteException {// TODO Auto-generated method stubname = names.get(0);System.out.println("Size:"+names.size()+"=="+names.get(0));}public void showTest() throws RemoteException {// TODO Auto-generated method stubIntent intent = new Intent(mContext, AidlTtest.class);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);startActivity(intent);}};

3.然后在Activity子类中进行测试,主要的工作就是开启上面实例化的Service子类

Intent service = new Intent(this, TestService.class); startService(service);


4.在AndroidManifest.xml注册该Service

<service android:name="TestService" android:process=":remote"> <intent-filter> <!-- AIDL完整路径名。必须指明,客户端能够通过AIDL类名查找到它的实现类 --> <action android:name="com.lifeblood.ITestService" /> </intent-filter></service>

(这样Server端的编码就结束了。然后就在Client类书写代码了。)

5.其实Aidl远程就相当于JAVA RMI 远程调用,也就是说也要在客户端书写一样的AIDL源文件。而且package包没有限制。可以写在任何你认为

合适的地方。此步略。


6.最后在Client端的Acitivty中写入,如下代码:

//创建远程调用对象private ServiceConnection connection = new ServiceConnection(){public void onServiceConnected(ComponentName name, IBinder service) {// TODO Auto-generated method stub//从远程service中获得AIDL实例化对象tService = ITestService.Stub.asInterface(service);System.out.println("Bind Success:"+tService);}public void onServiceDisconnected(ComponentName name) {// TODO Auto-generated method stubtService = null;}};................................public void onClick(View v) {// TODO Auto-generated method stubint viewId = v.getId();try{if (viewId == btn.getId()){Intent service = new Intent(ITestService.class.getName());//ITestService.class.getName()//绑定AIDLbindService(service, connection, BIND_AUTO_CREATE);}else if (viewId == btn1.getId()){text.setText("远程结果:"+tService.getAccountBalance());}else if (viewId == btn2.getId()){List<String> names = new ArrayList<String>();names.add("李彬彬");tService.setOwnerNames(names);}else if (viewId == btn3.getId()){String[] customerList = new String[1];tService.getCustomerList("向华", customerList);text.setText("远程结果:"+customerList[0]);}else if (viewId == btn4.getId()){tService.showTest();}}catch(RemoteException e){e.printStackTrace();}...............................@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();unbindService(connection);}

其中,

//创建远程调用对象

private ServiceConnection connection = new ServiceConnection(){
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
//从远程service中获得AIDL实例化对象

tService = ITestService.Stub.asInterface(service);

System.out.println("Bind Success:"+tService);
}

public void onServiceDisconnected(ComponentName name) {

// TODO Auto-generated method stub

tService = null;

}

};


用于实例化该private ITestService tService = null变量。 这样就可以通过点击事件来启动该服务中的方法.



try{


if (viewId == btn.getId()){

Intent service = new Intent(ITestService.class.getName());


//ITestService.class.getName()

//绑定AIDL


bindService(service, connection, BIND_AUTO_CREATE);


}else if (viewId == btn1.getId()){

text.setText("远程结果:"+tService.getAccountBalance());


}else if (viewId == btn2.getId()){


List<String> names = new ArrayList<String>();

names.add("mingg");

tService.setOwnerNames(names);

}else if (viewId == btn3.getId()){

String[] customerList = new String[1];

tService.getCustomerList("向华", customerList);

text.setText("远程结果:"+customerList[0]);


}else if (viewId == btn4.getId()){


tService.showTest();

}


如果要退出程序,不要忘了在onDestroy方法中加入

@Override

protected void onDestroy() {


// TODO Auto-generated method stub

super.onDestroy();

unbindService(connection);

}

要注意以下几点:
  1. 使用getApplicationContext()所获取的上下文来绑定和解绑定服务,这个时候即使不用unbindService也是不会出错的。具体原因还未深究。
  2. 如果不想用getApplicationContext(),那么就必须在结束Activity时运行解绑定操作。
  3. 如果unbindService(conn)中的conn没有被绑定到服务端,将报java.lang.IllegalArgumentException: Service not registered这样的错误。证明了这个方法不宜调用第二次。
  4. 当以startService的方式打开服务,即使当前服务没有绑定的对象也不会停止服务,除非stopService才能停止。反之如果先运行的是bindService,那么,只要当前的绑定对象都失去连接,就会停止服务

    这里回过头来说明一些android中的service

    Service概念及用途:

    Android中的服务,它与Activity不同,它是不能与用户交互的,不能自己启动的,运行在后台的程序,如果我们退出应用时,Service进程并没有结束,它仍然在后台运行,那 我们什么时候会用到Service呢?比如我们播放音乐的时候,有可能想边听音乐边干些其他事情,当我们退出播放音乐的应用,如果不用Service,我 们就听不到歌了,所以这时候就得用到Service了,又比如当我们一个应用的数据是通过网络获取的,不同时间(一段时间)的数据是不同的这时候我们可以 用Service在后台定时更新,而不用每打开应用的时候在去获取。

    Service生命周期 :

    Android Service的生命周期并不像Activity那么复杂,它只继承了onCreate(),onStart(),onDestroy()三个方法,当我 们第一次启动Service时,先后调用了onCreate(),onStart()这两个方法,当停止Service时,则执行onDestroy() 方法,这里需要注意的是,如果Service已经启动了,当我们再次启动Service时,不会在执行onCreate()方法,而是直接执行 onStart()方法,具体的可以看下面的实例。

(我是参考一个实例,如一个博客日志写的)

下面我再举一个例子,这个例子是实现来电防火墙的功能,就是说,如果有指定的号码打入,电话会自动静音,并且会自动断开。

由于Android1.1以上版本已经屏蔽了一些断开电话接入的API,而采取了AIDL方式。

接下来讲解,我实现的过程和一些关键代码,如下所示:

package com.android.internal.telephony; interface ITelephony { boolean endCall(); void answerRingingCall(); }

为了显示所有细节,我将我写得所示关键代码写入:

package com.test.telephone; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import android.app.Activity; import android.app.Service; import android.content.Context; import android.media.AudioManager; import android.os.Bundle; import android.os.RemoteException; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Log; import android.widget.TextView; import com.android.internal.telephony.ITelephony; /*** * * 参考: * http://blog.csdn.net/chenzheng_java/archive/2011/03/20/6262578.aspx * @author mingg * */ public class ActivityMain extends Activity { private static final String TAG = "Telephony"; TextView view = null; TelephonyManager mTelephonyMgr; private ITelephony iTelephony; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mTelephonyMgr = (TelephonyManager) this .getSystemService(Context.TELEPHONY_SERVICE); mTelephonyMgr.listen(new TeleListener(), PhoneStateListener.LISTEN_CALL_STATE); view = new TextView(this); view.setText("listen the state of phone/n"); setContentView(view); } class TeleListener extends PhoneStateListener { @Override public void onCallStateChanged(int state, String incomingNumber) { super.onCallStateChanged(state, incomingNumber); switch (state) { case TelephonyManager.CALL_STATE_IDLE: { //待机状态 Log.e(TAG, "CALL_STATE_IDLE"); view.append("CALL_STATE_IDLE " + "/n"); //待机状态响铃正常 AudioManager audioManager=(AudioManager)getSystemService(Context.AUDIO_SERVICE); if(audioManager!=null){ /**设置响铃正常**、 * */ audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL); audioManager.getStreamVolume(AudioManager.STREAM_RING);//设置音量 } break; } case TelephonyManager.CALL_STATE_OFFHOOK: {//电话被挂起了 Log.e(TAG, "CALL_STATE_OFFHOOK"); view.append("CALL_STATE_OFFHOOK" + "/n"); break; } case TelephonyManager.CALL_STATE_RINGING: { //来电 /**有电话接入**、 * */ if(incomingNumber.equals("15915780893")){//黑名单电话号码 AudioManager audioManager=(AudioManager)getSystemService(Context.AUDIO_SERVICE); if(audioManager!=null){ /**设置为静音模式**/ audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT); //也可以改为震动模式 // audioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);// audioManager.setRingerMode(AudioManager.STREAM_RING); } getTelephony(); //初始化iTelephony try { iTelephony.endCall(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } Log.e(TAG, "CALL_STATE_RINGING"); view.append("CALL_STATE_RINGING" +incomingNumber+ "/n"); break; } default: break; } } } public void getTelephony() { TelephonyManager telMgr = (TelephonyManager)getSystemService(Service.TELEPHONY_SERVICE); Class <TelephonyManager> c = TelephonyManager.class; Method getITelephonyMethod = null; try { getITelephonyMethod = c.getDeclaredMethod("getITelephony", (Class[])null); getITelephonyMethod.setAccessible(true); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { iTelephony = (ITelephony) getITelephonyMethod.invoke(telMgr, (Object[])null); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }

代码分析:

TelephonyManager mTelephonyMgr;

mTelephonyMgr = (TelephonyManager) this
.getSystemService(Context.TELEPHONY_SERVICE);

mTelephonyMgr.listen(new TeleListener(),
PhoneStateListener.LISTEN_CALL_STATE);

这个就是电话管理器,电话有三种状态,可以对其进行监听。

class TeleListener extends PhoneStateListener {

@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE: { //待机状态


break;
}
case TelephonyManager.CALL_STATE_OFFHOOK: {//电话被挂起了

}
case TelephonyManager.CALL_STATE_RINGING: { //来电

/**有电话接入**、
*
*/

break;
}
default:
break;
}
}

}

这里我们来看来电时候的状态:TelephonyManager.CALL_STATE_RINGING

if(audioManager!=null){
/**设置为静音模式**/
audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
//也可以改为震动模式
// audioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);//
audioManager.setRingerMode(AudioManager.STREAM_RING);

}


getTelephony();
//初始化iTelephony
iTelephony.endCall();

//挂断电话。

这里我们没有使用Service子类实现,由于实现的功能简单,如果实现的逻辑比较复杂的话,我们一般希望加入Service,如第一个实例那样

封装Aidl。

注意:在getTelephony()方法中,我们使用JAVA反射机制。

TelephonyManager telMgr = (TelephonyManager)getSystemService(Service.TELEPHONY_SERVICE);

Class <TelephonyManager> c = TelephonyManager.class;
Method getITelephonyMethod = null;

getITelephonyMethod = c.getDeclaredMethod("getITelephony", (Class[])null);
getITelephonyMethod.setAccessible(true);

iTelephony = (ITelephony) getITelephonyMethod.invoke(telMgr, (Object[])null);

关于JAVA的反射机制,我将会在后续再次提到。

最后当然不要忘了在AndroidManifest.xml进行权限申请:

<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.CALL_PHONE" />







  

更多相关文章

  1. 【Android(安卓)开发】:TextView的几种使用方法
  2. Android之获取本地图片并压缩方法
  3. Android天气预报之基于HttpGet对象解析天气数据的方法
  4. 新思路_Android同时显示多个跑马灯
  5. Android(安卓)Service 通知Activity更新界面的方法研究
  6. Android(安卓)Service Messenger & AIDL 的跨进程通信例子
  7. Android(安卓)Fragment使用
  8. Android(安卓)UI 单线程模型的编程原则以及AsyncTask原理
  9. 深入浅析Android消息机制

随机推荐

  1. Android实现导航栏的左右滑动效果
  2. Cheatsheet: 2012 06.01 ~ 06.11
  3. Android——摇一摇
  4. 防止滑盖事件造成crash
  5. 【Android】 JNI入门 - NDK从入门到精通
  6. Android(安卓)原生项目集成React Native
  7. 短信监听,自动获短信取验证码
  8. Android(安卓)屏幕适配全攻略
  9. Android实现不同Active页面间的跳转
  10. 【MAC版】Android(安卓)ADB server didn'