AIDL/IPC Android AIDL/IPC 进程通信机制——超详细讲解及用法案例剖析(播放器)

首先引申下AIDL,什么是AIDL呢?IPC? ------ Designing a Remote Interface Using AIDL

通常情况下,我们在同一进程内会使用Binder、BroadCastReciver让Service跟Activity进行通信,数据交互,数据共享,但是跨进程呢?

IPC:IPC接口,IPC接口本地代理  ------  Implementing IPC Using AIDL

AIDL意为:Android Interface Define Language 即 Android 接口描述语言

与J2ee的区别:Java中不允许跨进程内存共享,只传递对象,采用RMI方式,也可以通过序列化传递对象

Android AIDL: 采用AIDL方式,可以传递Bundle,实现起来稍微麻烦些

实现过程:在服务端定义AIDL文件,ADT插件编译器将其编译之后,会在R文件同级目录文件下生成.java文件,轻量级,使用代理类在客户端和实现层间传

递值

语法:可以申明接口和方法,参数和返回值不是任何类型,不需要申明import,String,charSequence等

AIDL使用起来也不是很麻烦,我个人感觉很实用!所以今天就说说关于AIDL的特性,很多朋友在自己的博客只是说它的理论而不是写一些实例来讲解,我个人感觉你只是说说他的

理论,一般人根本就看不懂,而且本来就是很抽象的东西,又摸不着,你们写了也是白写!

完全不顾新手的感受,应该是写一些小例子,让大家参与进来一起学习和探讨效果才最佳!而且也不是一大堆的文字,看起来也不会那么乏味,大家说是不?

下面就开始今天的AIDL/IPC讲解与学习吧~,概念都讲的差不多了,接下来就是实战,代码小例子给初学者细嚼慢咽

从服务端线程开始写,结构图:


EngineerJspRemoteService.aidl 写完之后保存,就会在gen文件自动创建一个.java文件


EngineerJspService.java

[java]  view plain  copy
  1. package com.example.engineerjspserver;  
  2. /** 
  3.  * AIDL/IPC  
  4.  * @author Engineer-Jsp 
  5.  * @date 2014.11.17 
  6.  * */  
  7. import java.io.FileDescriptor;  
  8. import android.app.Service;  
  9. import android.content.Intent;  
  10. import android.media.MediaPlayer;  
  11. import android.os.IBinder;  
  12. import android.os.RemoteException;  
  13. import android.util.Log;  
  14. public class EngineerJspService extends Service{  
  15.     private static final String TAG = "EngineerJspService";  
  16.     MediaPlayer player;  
  17.     @Override  
  18.     public IBinder onBind(Intent intent) {  
  19.         Log.d(TAG, "EngineerJspService is onBind..."+"\n来自客户端的绑定操作已经完成...");  
  20.         if(player==null){  
  21.             player = MediaPlayer.create(this, R.raw.music);  
  22.             player = new MediaPlayer();  
  23.             try {  
  24.                 FileDescriptor file = getResources().openRawResourceFd(R.raw.music).getFileDescriptor();  
  25.                 player.setDataSource(file);  
  26.                 player.setLooping(true);  
  27.             } catch (Exception e) {  
  28.                 Log.d(TAG, e.toString());  
  29.             }  
  30.             Log.d(TAG, "player is created..."+"\n服务端播放器已经实例化,准备就绪...");  
  31.         }  
  32.         return binder;  
  33.     }  
  34.     private IBinder binder = new EngineerJspRemoteService.Stub() {  
  35.           
  36.         @Override  
  37.         public void onStop() throws RemoteException {  
  38.             try {  
  39.                 if(player.isPlaying()){  
  40.                     Log.d(TAG, "客户端进程对服务端进程执行了暂停操作...");  
  41.                     player.stop();  
  42.                 }  
  43.             } catch (Exception e) {  
  44.                 Log.d(TAG, e.toString());  
  45.             }  
  46.         }  
  47.           
  48.         @Override  
  49.         public void onPause() throws RemoteException {  
  50.             try {  
  51.                 if(player.isPlaying()){  
  52.                     return;  
  53.                 }  
  54.                 Log.d(TAG, "客户端进程对服务端进程执行了开始操作...");  
  55.                 player.prepare();  
  56.                 player.start();  
  57.             } catch (Exception e) {  
  58.                 Log.d(TAG, e.toString());  
  59.             }  
  60.         }  
  61.     };  
  62.     public boolean onUnbind(Intent intent) {  
  63.         if(player!=null){  
  64.             player.release();  
  65.         }  
  66.         Log.d(TAG, "EngineerJspService is onUnBind..."+"\n客户端已经解绑断线,服务停止了...");  
  67.         return super.onUnbind(intent);  
  68.           
  69.     };  
  70.   
  71. }  
配置文件:

[html]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.example.engineerjspserver"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk  
  8.         android:minSdkVersion="15"  
  9.         android:targetSdkVersion="18" />  
  10.   
  11.     <application  
  12.         android:allowBackup="true"  
  13.         android:icon="@drawable/ic_launcher"  
  14.         android:label="@string/app_name"  
  15.         android:theme="@style/AppTheme" >  
  16.               <activity  
  17.             android:name="com.example.engineerjspserver.MainAcivity"  
  18.             android:label="@string/app_name" >  
  19.             <intent-filter>  
  20.                 <action android:name="android.intent.action.MAIN" />  
  21.                 <category android:name="android.intent.category.LAUNCHER" />  
  22.             </intent-filter>  
  23.         </activity>  
  24.          <service android:name=".EngineerJspService" android:process=":remote">  
  25.             <intent-filter >  
  26.                 <action android:name="com.example.engineerjspserver.EngineerJspService"/>  
  27.             </intent-filter>  
  28.          </service>  
  29.     </application>  
  30.   
  31. </manifest>  

当完成上述操作之后,需要在res目录下导入测试文件,比如我的测试文件一个music.mp3,需要与layout文件同级


搞定服务端之后,接下来就是客户端线程编写,之后进行进程通信测试

把服务端的aidl文件所在的包全部拷贝到客户端的src下,把aidl文件除外的全部删掉


EngineerJspActivity.java

[java]  view plain  copy
  1. package com.example.engineerjspclient;  
  2. /** 
  3.  * AIDL/IPC 
  4.  * @author Engineer-Jsp 
  5.  * @date 2014.11.17 
  6.  * */  
  7. import com.example.engineerjspserver.EngineerJspRemoteService;  
  8.   
  9. import android.os.Bundle;  
  10. import android.os.IBinder;  
  11. import android.util.Log;  
  12. import android.view.View;  
  13. import android.view.View.OnClickListener;  
  14. import android.widget.Button;  
  15. import android.widget.Toast;  
  16. import android.app.Activity;  
  17. import android.content.ComponentName;  
  18. import android.content.Intent;  
  19. import android.content.ServiceConnection;  
  20. public class EngineerJspActivity extends Activity {  
  21.     private static final String TAG = "EngineerJspActivity";  
  22.     private static final String ACTION = "com.example.engineerjspserver.EngineerJspService";  
  23.     private EngineerJspRemoteService EJService;  
  24.     private boolean isBind = false;  
  25.     private Button onPause,onStart;  
  26.       
  27.     private ServiceConnection connection = new ServiceConnection() {  
  28.         @Override  
  29.         public void onServiceDisconnected(ComponentName name) {  
  30.             isBind = false;  
  31.             EJService = null;  
  32.             Log.d(TAG, "onServiceDisconnected" +  
  33.                     "————"+"包名:"+name.getPackageName()+" "+"类名: "+name.getClassName()+"\n当客户端线程断线操作,服务将被清空...");  
  34.         }  
  35.         @Override  
  36.         public void onServiceConnected(ComponentName name, IBinder ibinder) {  
  37.             EJService = EngineerJspRemoteService.Stub.asInterface(ibinder);  
  38.             isBind = true;  
  39.             Log.d(TAG, "onServiceConnected————"+"包名:"+name.getPackageName()+" "+"类名: "+name.getClassName()+" "+"ibinder对象: "+ibinder.toString()+"\n客户端线程与服务端线程连接中...");  
  40.         }  
  41.     };  
  42.     @Override  
  43.     protected void onCreate(Bundle savedInstanceState) {  
  44.         super.onCreate(savedInstanceState);  
  45.         setContentView(R.layout.activity_engineer_jsp);  
  46.         Log.d(TAG, "客户端线程Activity创建成功,初始化控件与绑定服务中...");  
  47.         Bind();  
  48.         intiView();  
  49.     }  
  50.     @Override  
  51.     protected void onDestroy() {  
  52.         UnBind();  
  53.         Log.d(TAG, "客户端线程被销毁,活动被解绑停止了...");  
  54.         super.onDestroy();  
  55.     }  
  56.     public void Bind(){  
  57.         Log.d(TAG, "Activity已经创建完成,执行绑定服务端线程活动中...");  
  58.         Intent intent = new Intent(ACTION);  
  59.         bindService(intent, connection, BIND_AUTO_CREATE);  
  60.     }  
  61.     public void UnBind(){  
  62.         if(isBind){  
  63.             Log.d(TAG, "Activity被销毁了,与服务端线程的通信将被解绑停止...");  
  64.             unbindService(connection);  
  65.             EJService = null;  
  66.             isBind = false;  
  67.         }  
  68.     }  
  69.     private void intiView(){  
  70.         onPause = (Button)findViewById(R.id.onPause);  
  71.         onStart = (Button)findViewById(R.id.onStop);  
  72.         onPause.setOnClickListener(listener);  
  73.         onStart.setOnClickListener(listener);  
  74.         Log.d(TAG, "服务端线程的组件初始化完毕...");  
  75.     }  
  76.     private OnClickListener listener = new OnClickListener(){  
  77.   
  78.         @Override  
  79.         public void onClick(View view) {  
  80.             if(view.getId()==R.id.onPause){  
  81.                 try {  
  82.                     EJService.onPause();  
  83.                     Log.d(TAG, "客户端线程对服务端线程执行了播放操作...");  
  84.                     Toast.makeText(EngineerJspActivity.this,"客户端线程对服务端线程执行了播放操作...", Toast.LENGTH_SHORT).show();  
  85.                 } catch (Exception e) {  
  86.                     Log.d(TAG, e.toString());  
  87.                 }  
  88.             }else{  
  89.                 try {  
  90.                     EJService.onStop();  
  91.                     Log.d(TAG, "客户端线程对服务端线程执行了暂停操作...");  
  92.                     Toast.makeText(EngineerJspActivity.this,"客户端线程对服务端线程执行了暂停操作...", Toast.LENGTH_SHORT).show();  
  93.                 } catch (Exception e) {  
  94.                     Log.d(TAG, e.toString());  
  95.                 }  
  96.             }  
  97.         }  
  98.           
  99.     };  
  100. }  

activity_engineer_jsp.xml

[html]  view plain  copy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:paddingBottom="@dimen/activity_vertical_margin"  
  6.     android:paddingLeft="@dimen/activity_horizontal_margin"  
  7.     android:paddingRight="@dimen/activity_horizontal_margin"  
  8.     android:paddingTop="@dimen/activity_vertical_margin"  
  9.     tools:context=".EngineerJspActivity" >  
  10.   
  11.     <Button  
  12.         android:id="@+id/onStop"  
  13.         android:layout_width="wrap_content"  
  14.         android:layout_height="wrap_content"  
  15.         android:layout_alignParentLeft="true"  
  16.         android:layout_alignParentRight="true"  
  17.         android:layout_below="@+id/button1"  
  18.         android:layout_marginTop="42dp"  
  19.         android:text="onStop" />  
  20.   
  21.     <Button  
  22.         android:id="@+id/onPause"  
  23.         android:layout_width="wrap_content"  
  24.         android:layout_height="wrap_content"  
  25.         android:layout_alignLeft="@+id/onStop"  
  26.         android:layout_alignParentRight="true"  
  27.         android:layout_below="@+id/onStop"  
  28.         android:text="onPause" />  
  29.   
  30. </RelativeLayout>  
配置文件:

[html]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.example.engineerjspclient"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk  
  8.         android:minSdkVersion="15"  
  9.         android:targetSdkVersion="18" />  
  10.   
  11.     <application  
  12.         android:allowBackup="true"  
  13.         android:icon="@drawable/ic_launcher"  
  14.         android:label="@string/app_name"  
  15.         android:theme="@style/AppTheme" >  
  16.         <activity  
  17.             android:name="com.example.engineerjspclient.EngineerJspActivity"  
  18.             android:label="@string/app_name" >  
  19.             <intent-filter>  
  20.                 <action android:name="android.intent.action.MAIN" />  
  21.   
  22.                 <category android:name="android.intent.category.LAUNCHER" />  
  23.             </intent-filter>  
  24.         </activity>  
  25.     </application>  
  26.   
  27. </manifest>  

启动服务端进程与客户端进程(不在同一个进程内,也就是不在同一个APK程序之内),在DDMS里进行进程和堆栈查看


当服务端进程开启之后,会等待客户端进程接入与操作,类似c/s模式,Socket,客户端进程开启之后,服务端测试数据如下


客户端测试数据:


服务测试:

客户端进程对服务端进程执行了播放操作:



客户端进程对服务端进程执行了暂停操作:




两个进程项目图结构:


AIDL这个小实例内容就这么多,概念也说得差不多了,你们好好看看,消化消化~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值