Android开源项目之Music (二)--- AIDL实现IPC进程间通讯
2013-08-07 15:18
696 查看
根据上一篇 Android开源项目之Music
(一)--- MusicBrowserActivity 提到的,要继续往下分析源代码的话,需要具备AIDL的知识,如果有这方面知识的大神们请自行跳过,废话不多说,现在就进行AIDL的简单学习
一.什么是AIDL,AIDL的作用
AIDL
(Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。
由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI运行另一个服务进程,而且经常会在不同的进程间传递对象。在Android平台,一个进程通常不能访问另一个进程的内存空间,所以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界。
通过代码来实现这个数据传输过程是冗长乏味的,Android提供了AIDL工具来处理这项工作。
如果有做过C#方面开放的,我想做个比喻,个人觉得这个AIDL很像C#里面提到的dll, 在“服务器”端有一份,在“客户端”也有一份,然后就可以调用了
(不知道这种比喻对不对,勿喷!)
二.AIDL的工作原理解析(直接写个demo)
1.居然要写远程服务进行进程间通信的话,那我们先在workspace下面建立两个工程,分别为AIDLServer和AIDLClient
2.在AIDLServer的包com.example.aidlserver下new一个文件IMyMusicPlayerService.aidl,写入以下代码.
Ctrl + S 保存后 ADT 会根据这个IMyMusicPlayerService.aidl文件自动生成IMyMusicPlayerService.java文件。如同R.java文件一样在“gen/包名”下,代码是自动生成的,不要手动修改这个文件
3.由于我们要分析的是Music项目源码,所以我们搞一个专门用于播放音乐的Service吧.
这里首先需要有点Service和Binder的知识,在生成的.java文件中有个静态类
/** Local-side IPC implementation stub class. */public static abstract class Stubextends android.os.Binderimplementscom.example.aidlserver.IMyMusicPlayerService
Sub类它继承于Binder,引用了IMyMusicPlayerService接口,一个类继承了Binder,如果远程进程获得了
这个类的对象,那么它的对象就可以被远程的进程使用。
4.在res文件夹下,建立一个raw文件夹,下面放一首.mp3歌曲。接下来让我们编写这个Service类,MyMusicPlayerService
并在AndroidManifest.xml文件中进行注册
android:process=":remote",代表在应用程序里,当需要该service时,会自动创建新的进程。而如果是android:process="remote",没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。(详细:http://galin.blog.sohu.com/170489657.html)
而intent-filter中这个action属性不可少,原因大家可以去看我之前的一篇博文:
浅谈Activity之启动方式(5种启动方式和隐式启动)
5.这样服务器端所要做的就做完了,现在编写客户端,客户端的话,需要得到服务器端的aidl文件,当然这个aidl所在的包是不能被改变的,也就是说我们需要把整个aidl放在一个包名依旧为com.example.aidlserver的包下才可以.
布局文件就写两个“Button”按钮,我就不发上来了,下面看看这个AIDLClientActivity.java文件
总结一下所有的步骤:
建立AIDL服务要比建立普通的服务复杂一些,具体步骤如下:
(1)在Eclipse Android工程的Java包目录中建立一个扩展名为aidl的文件。该文件的语法类似于Java代码,但会稍有不同。
(2)如果aidl文件的内容是正确的,ADT会自动生成一个Java接口文件(*.java)。
(3)建立一个服务类(Service的子类)。
(4)实现由aidl文件生成的Java接口。
(5)在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类的参数值。
注意:Client调用的Server里面的类,因此这两个程序都需要在你的手机中安装,才可以实现调用
demo源码下载地址:
http://download.csdn.net/detail/u011133213/5885661
(一)--- MusicBrowserActivity 提到的,要继续往下分析源代码的话,需要具备AIDL的知识,如果有这方面知识的大神们请自行跳过,废话不多说,现在就进行AIDL的简单学习
一.什么是AIDL,AIDL的作用
AIDL
(Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。
由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI运行另一个服务进程,而且经常会在不同的进程间传递对象。在Android平台,一个进程通常不能访问另一个进程的内存空间,所以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界。
通过代码来实现这个数据传输过程是冗长乏味的,Android提供了AIDL工具来处理这项工作。
如果有做过C#方面开放的,我想做个比喻,个人觉得这个AIDL很像C#里面提到的dll, 在“服务器”端有一份,在“客户端”也有一份,然后就可以调用了
(不知道这种比喻对不对,勿喷!)
二.AIDL的工作原理解析(直接写个demo)
1.居然要写远程服务进行进程间通信的话,那我们先在workspace下面建立两个工程,分别为AIDLServer和AIDLClient
2.在AIDLServer的包com.example.aidlserver下new一个文件IMyMusicPlayerService.aidl,写入以下代码.
package com.example.aidlserver;//注意一定要加入这个包名 interface IMyMusicPlayerService {//这个aidl的写法就是写一个interface一样,但是不需要加入修饰符public什么的 void play();//播放音乐 void stop();}
Ctrl + S 保存后 ADT 会根据这个IMyMusicPlayerService.aidl文件自动生成IMyMusicPlayerService.java文件。如同R.java文件一样在“gen/包名”下,代码是自动生成的,不要手动修改这个文件
3.由于我们要分析的是Music项目源码,所以我们搞一个专门用于播放音乐的Service吧.
这里首先需要有点Service和Binder的知识,在生成的.java文件中有个静态类
/** Local-side IPC implementation stub class. */public static abstract class Stubextends android.os.Binderimplementscom.example.aidlserver.IMyMusicPlayerService
Sub类它继承于Binder,引用了IMyMusicPlayerService接口,一个类继承了Binder,如果远程进程获得了
这个类的对象,那么它的对象就可以被远程的进程使用。
4.在res文件夹下,建立一个raw文件夹,下面放一首.mp3歌曲。接下来让我们编写这个Service类,MyMusicPlayerService
package com.example.aidlserver; import java.io.FileDescriptor; import java.io.IOException; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; /* * 播放音乐服务类 * 2013年8月7日14:20:27 * Author: 胖虎 * http://blog.csdn.net/ljphhj * */ public class MyMusicPlayerService extends Service{ //Logger TAG public static final String LogTAG = "com.example.aidlserver.MyMusicPlayerService"; //android自带播放音乐类: android.media.MediaPlayer private MediaPlayer mPlayer = null; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub if (mPlayer == null) { mPlayer = new MediaPlayer(); //得到音乐资源 FileDescriptor fildDescriptor = getResources().openRawResourceFd(R.raw.love).getFileDescriptor(); try { //设置数据源 mPlayer.setDataSource(fildDescriptor); //设置是否循环播放 mPlayer.setLooping(true); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return mBinder; } @Override public boolean onUnbind(Intent intent) { // TODO Auto-generated method stub if (mPlayer != null) { //释放资源 mPlayer.release(); } return super.onUnbind(intent); } /** * 实现了接口中的两个函数 */ private IBinder mBinder = new IMyMusicPlayerService.Stub() { @Override public void stop() throws RemoteException { // TODO Auto-generated method stub if (mPlayer.isPlaying()) { //停止播放 mPlayer.stop(); } } @Override public void play() throws RemoteException { // TODO Auto-generated method stub try { if (!mPlayer.isPlaying()) { mPlayer.prepare(); mPlayer.start(); } } catch (Exception e) { // TODO: handle exception Log.i(LogTAG, "play函数出现异常"); } } }; }
并在AndroidManifest.xml文件中进行注册
<service android:name="com.example.aidlserver.MyMusicPlayerService" android:process=":remote" > <intent-filter > <action android:name="com.example.aidlserver.MyMusicPlayerService"/> </intent-filter> </service>
android:process=":remote",代表在应用程序里,当需要该service时,会自动创建新的进程。而如果是android:process="remote",没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。(详细:http://galin.blog.sohu.com/170489657.html)
而intent-filter中这个action属性不可少,原因大家可以去看我之前的一篇博文:
浅谈Activity之启动方式(5种启动方式和隐式启动)
5.这样服务器端所要做的就做完了,现在编写客户端,客户端的话,需要得到服务器端的aidl文件,当然这个aidl所在的包是不能被改变的,也就是说我们需要把整个aidl放在一个包名依旧为com.example.aidlserver的包下才可以.
布局文件就写两个“Button”按钮,我就不发上来了,下面看看这个AIDLClientActivity.java文件
package com.example.aidlclient; import com.example.aidlserver.IMyMusicPlayerService; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; /** * AIDL demo 客户端 * @author 胖虎 * */ public class AIDLClientActivity extends Activity { //Logger TAG public static final String LogTAG = "com.example.aidlclient.AIDLClientActivity"; // 服务端 AndroidManifest.xml中的service中intent-filter的action声明的字符串 public static final String ACTION = "com.example.aidlserver.MyMusicPlayerService"; private Button playButton = null; private Button stopButton = null; private IMyMusicPlayerService mService = null; private boolean isBinded = false; private ServiceConnection serviceConnection = new ServiceConnection() { /*Service断开连接时,调用*/ @Override public void onServiceDisconnected(ComponentName name) { isBinded = false; mService = null; } /*Service连接时,调用*/ @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = IMyMusicPlayerService.Stub.asInterface(service); isBinded = true; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_aidlclient); /*service绑定的知识,不了解的可以网上找找*/ Intent intent = new Intent(ACTION); bindService(intent, serviceConnection, BIND_AUTO_CREATE); /*初始化View*/ initComponent(); } /*解除Service绑定(此demo中没调用)*/ public void unBind() { if (isBinded) { unbindService(serviceConnection); mService = null; isBinded = false; } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.aidlclient, menu); return true; } private void initComponent() { playButton = (Button) findViewById(R.id.play); stopButton = (Button) findViewById(R.id.stop); playButton.setOnClickListener(buttonClickListener); stopButton.setOnClickListener(buttonClickListener); } private OnClickListener buttonClickListener = new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.play: { if (mService != null) { try { mService.play(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } break; case R.id.stop: { if (mService != null) { try { mService.stop(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } break; default: break; } } }; }
总结一下所有的步骤:
建立AIDL服务要比建立普通的服务复杂一些,具体步骤如下:
(1)在Eclipse Android工程的Java包目录中建立一个扩展名为aidl的文件。该文件的语法类似于Java代码,但会稍有不同。
(2)如果aidl文件的内容是正确的,ADT会自动生成一个Java接口文件(*.java)。
(3)建立一个服务类(Service的子类)。
(4)实现由aidl文件生成的Java接口。
(5)在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类的参数值。
注意:Client调用的Server里面的类,因此这两个程序都需要在你的手机中安装,才可以实现调用
demo源码下载地址:
http://download.csdn.net/detail/u011133213/5885661
相关文章推荐
- android使用AIDL实现跨进程通讯(IPC)
- android使用AIDL实现跨进程通讯(IPC)
- 示例:Android使用AIDL实现跨进程通讯(IPC)
- Android应用中通过AIDL机制实现进程间的通讯实例
- Android开发中实现跨进程通讯的AIDL接口
- android 不同进程间的调用 AIDL 实现通讯服务
- Android开发中实现跨进程通讯的AIDL接口
- Android应用中通过AIDL机制实现进程间的通讯实例
- Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用
- Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用
- Android应用中通过AIDL机制实现进程间的通讯实例
- Android应用中通过AIDL机制实现进程间的通讯实例
- Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用
- Android应用中通过AIDL机制实现进程间的通讯实例
- Android应用中通过AIDL机制实现进程间的通讯实例
- Android应用中通过AIDL机制实现进程间的通讯实例
- Android查缺补漏(IPC篇)-- 进程间通讯之AIDL详解
- Android进程间通讯之初见(IPC,RPC,LPC,BINDER,AIDL..)
- Android内存共享、进程间高性能IO、手动实现 Binder IPC、Aidl例子
- Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用