2019独角兽企业重金招聘Python工程师标准>>>

Android Service是分为两种:

  • 本地服务(Local Service): 同一个apk内被调用
  • 远程服务(Remote Service):被另一个apk调用

远程服务需要借助AIDL来完成。

AIDL 是什么

AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。

AIDL IPC机制是面向接口的,像COM或Corba一样,但是更加轻量级。它是使用代理类在客户端和实现端传递数据。

AIDL 的作用

由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI运行另一个服务进程,而且经常会在不同的进程间传递对象。在Android平台,一个进程通常不能访问另一个进程的内存空间,所以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界。

  通过代码来实现这个数据传输过程是冗长乏味的,Android提供了AIDL工具来处理这项工作。

选择AIDL的使用场合

官方文档特别提醒我们何时使用AIDL是必要的:只有你允许客户端从不同的应用程序为了进程间的通信而去访问你的service,以及想在你的service处理多线程。

如果不需要进行不同应用程序间的并发通信(IPC),you should create your interface by implementing a Binder;或者你想进行IPC,但不需要处理多线程的,则implement your interface using a Messenger。无论如何,在使用AIDL前,必须要理解如何绑定service——bindService。

下面用一个客户端Activity操作服务端Service播放音乐的实例演示AIDL的使用。

开发工具: eclipse 3.7(indigo)+ android sdk 4.1+ adt 20.0.2

服务端代码结构

客户端代码结构

被标记的就是需要动手的。

服务端

新建一个android application project,命名为PlayerServer。 在res下的raw文件夹里面放入一个音乐文件,我这里放入的是Delta Goodrem的《Lost Without You》片段。如果不存在raw这个文件夹就自己新建一个,命名为raw。这个文件夹在raw文件夹下,与layout文件夹平级。raw中的文件遵守标识符的命名规则,不要出现中文和空格,多个单词可以用下划线连接。

新建一个IRemoteServiice.aidl 文件,加入如下代码:

package pandafang.demo.playerserver;interface IRemoteService {void play();void stop();}

可见aidl文件的代码跟java的interface一样,但是aidl中不能加public等修饰符。Ctrl + S 保存后 ADT 会根据这个IRemoteService.aidl文件自动生成IRemoteService.java文件。如同R.java文件一样在“gen/包名”下,代码是自动生成的,不要手动修改。

接下来就是bound service(参考:官方文档)的知识了。IRemoteService.java 中有一个Stub静态抽象类extends Binder implements IRemoteService。自己动手写一个PlayerService 用来播放音乐,播放音乐需要使用android.media.MediaPlayer类。代码如下:

package pandafang.demo.playerserver;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;/*** 播放音乐的服务* @author Panda Fang* @date 2012-10-22 10:15:33*/public class PlayerService extends Service {public static final String TAG = "PlayerService";private MediaPlayer mplayer;// 实现aidl文件中定义的接口private IBinder mBinder = new IRemoteService.Stub() {@Overridepublic void stop() throws RemoteException {try {if (mplayer.isPlaying()) {mplayer.stop();}} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}@Overridepublic void play() throws RemoteException {try {if (mplayer.isPlaying()) {return;}// start之前需要prepare。// 如果前面实例化mplayer时使用方法一,则第一次play的时候直接start,不用prepare。// 但是stop一次之后,再次play就需要在start之前prepare了。// 前面使用方法二 这里就简便了, 不用判断各种状况mplayer.prepare();mplayer.start();} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}};@Overridepublic IBinder onBind(Intent intent) {Log.i(TAG,"service onbind");if(mplayer==null){// 方法一说明// 此方法实例化播放器的同时指定音乐数据源 ,若用此方法在,mplayer.start() 之前不需再调用mplayer.prepare() // 官方文档有说明 :On success, prepare() will already have been called and must not be called again.// 译文:一旦create成功,prepare已被调用,勿再调用 。查看源代码可知create方法内部已经调用prepare方法。// 方法一开始// mplayer = MediaPlayer.create(this, R.raw.lost);// 方法一结束// 方法二说明// 若用此方法,在mplayer.start() 之前需要调用mplayer.prepare() // 方法二开始mplayer = new MediaPlayer();try {FileDescriptor fd = getResources().openRawResourceFd(R.raw.lost).getFileDescriptor(); // 获取音乐数据源mplayer.setDataSource(fd); // 设置数据源mplayer.setLooping(true); // 设为循环播放} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}// 方法二结束Log.i(TAG,"player created");}return mBinder;}@Overridepublic boolean onUnbind(Intent intent) {if (mplayer != null) {mplayer.release();}Log.i(TAG,"service onUnbind");return super.onUnbind(intent);}}

服务编写好以后,按照惯例在AndroidManifest.xml中加入声明,代码如下:

需要加入的只是...那段,要注意的是 android:process=":remote" 和 intent-filter 。

运行服务端到设备上,准备给客户端调用。

客户端

新建一个android application project,命名为PlayerClient。将服务端放有aidl文件的包直接copy到客户端src目录下,保留包中的aidl文件,其他删除。

编辑 layout 下的 activity_main.xml 布局文件,加入两个按钮,代码如下:

编写MainActivity.java 代码如下:

package pandafang.demo.playerclient;import pandafang.demo.playerserver.IRemoteService;import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;import android.view.Menu;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;/*** 客户端控制界面* @author Panda Fang* @date 2012-10-22 10:36:44*/public class MainActivity extends Activity {public static final String TAG = "MainActivity";// 服务端 AndroidManifest.xml中的intent-filter action声明的字符串public static final String ACTION = "com.example.playerserver.PlayerService";private Button playbtn, stopbtn;private IRemoteService mService;private boolean isBinded = false;private ServiceConnection conn = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {isBinded = false;mService = null;}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mService = IRemoteService.Stub.asInterface(service);isBinded = true;}};@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);doBind();initViews();}private void initViews() {playbtn = (Button) findViewById(R.id.button1);stopbtn = (Button) findViewById(R.id.button2);playbtn.setOnClickListener(clickListener);stopbtn.setOnClickListener(clickListener);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.activity_main, menu);return true;}@Overrideprotected void onDestroy() {doUnbind();super.onDestroy();}public void doBind() {Intent intent = new Intent(ACTION);bindService(intent, conn, Context.BIND_AUTO_CREATE);}public void doUnbind() {if (isBinded) {unbindService(conn);mService = null;isBinded = false;}}private OnClickListener clickListener = new OnClickListener() {@Overridepublic void onClick(View v) {if (v.getId() == playbtn.getId()) {// playLog.i(TAG,"play button clicked");try {mService.play();} catch (RemoteException e) {// TODO Auto-generated catch blocke.printStackTrace();}} else {// stopLog.i(TAG,"stop button clicked");try {mService.stop();} catch (RemoteException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}};}

MainActivity是根据向导自动生成的,不需要在AndroidManifest.xml中注册声明了。

运行客户端到设备,按下按钮可以播放/停止 效果如图:

源代码下载:http://files.cnblogs.com/lonkiss/AIDLPlayer.zip

更多详细请参考:http://www.baisoujs.com/detail_137434192972690.html

转载于:https://my.oschina.net/u/1189001/blog/147443

简单音乐播放实例的实现,Android Service AIDL 远程调用服务相关推荐

  1. Android Service AIDL 远程调用服务 【简单音乐播放实例】

    Android Service是分为两种: 本地服务(Local Service): 同一个apk内被调用 远程服务(Remote Service):被另一个apk调用 远程服务需要借助AIDL来完成 ...

  2. Android Service使用方法--简单音乐播放实例

    Service翻译成中文是服务,熟悉Windows 系统的同学一定很熟悉了.Android里的Service跟Windows里的Service功能差不多,就是一个不可见的进程在后台执行. Androi ...

  3. android调用系统音频播放器,Android使用Service实现简单音乐播放实例

    Service翻译成中文是服务,熟悉Windows 系统的同学一定很熟悉了.Android里的Service跟Windows里的Service功能差不多,就是一个不可见的进程在后台执行. Androi ...

  4. android音乐播放器实现,Android实现简单音乐播放器(MediaPlayer)

    Android实现简单音乐播放器(MediaPlayer),供大家参考,具体内容如下 开发工具:Andorid Studio 1.3 运行环境:Android 4.4 KitKat 工程内容 实现一个 ...

  5. Android复习02(ListView具体操作[很详细]、简单音乐播放器)

    2020年 3月24日 星期二 Android录播回放 笔记[腾讯课堂] https://ke.qq.com/webcourse/index.html#cid=989760&term_id=1 ...

  6. Android:简单音乐播放器,实现歌曲列表显示,播放暂停,切歌等功能

    效果截图(大作业不建议用,太简单了) 源码下载 简单音乐播放器

  7. 安卓java音乐播放器下一曲_Android实现简单音乐播放器(MediaPlayer)

    Android实现简单音乐播放器(MediaPlayer),供大家参考,具体内容如下 开发工具:Andorid Studio 1.3 运行环境:Android 4.4 KitKat 工程内容 实现一个 ...

  8. 音乐播放器类的Android项目源码

    收集了很多音乐播放器类的Android项目源码,非常不错的开源项目,会让你事半功倍,希望大家补充...谢谢! Android基于经纬度切歌的冲绳音乐播放器源码 http://neast.cn/foru ...

  9. 收集了很多音乐播放器类的Android项目源码,非常不错的开源项目

    JieCaoVideoPlayer立志成为Android平台使用最广泛的视频播放控件 http://neast.cn/forum.php?mod=viewthread&tid=61610&am ...

最新文章

  1. 中兴同美司法部和解协议获准:罚12亿美元
  2. Centos7下 Redis的安装、配置开机自启动、开放远程连接
  3. VTK:图片之ImageEllipsoidSource
  4. python xlrd读取文件报错_python中xlrd库如何实现文件读取?
  5. [LeetCode] Inorder Successor in BST 二叉搜索树中的中序后继节点
  6. 1215课后练习----判断字符串位置
  7. uni-app 自定义loading 自定义toast 兼容小程序APP
  8. Ubuntu Server 16.04服务器版配置图解教程14 - 安装PHP7.1.11(源码包安装)
  9. linux 微信机器人,开源Linux操作系统的机器人(组图)
  10. 基于iOS11的HEVC(H.265)硬编码/硬解码功能开发指南
  11. Latex各种箭头符号总结
  12. Html+Css+Js轮播图实现
  13. 【团队管理系列】团队管理方面的量化数据
  14. 深度学习论文精读05——用于乳腺癌组织病理学图像分类的深度特征
  15. C++面试题,阿里、百度、腾讯、华为、小米100道C++面试题目及答案
  16. 【How2Pwn】DreamHack x64下的ROP问题
  17. 2019-12-3 《网络安全法》学习
  18. 同济版高等数学复习笔记(上册第五、六章)
  19. 时间复杂度和空间复杂度简介
  20. 2016计算机应用试题答案,2017年计算机应用基础模拟试题「答案」

热门文章

  1. JavaScript操作表格进行拖拽排序
  2. 开心网分析,师从“中国缘”
  3. Password Creator(HTA)
  4. C语言中指针的地址和内容
  5. sql 2008找不到服务器,sql server 2005 数据库迁移问题总结——错误 ‘80004005’ 在 sys.servers 中找不到服务器 ‘XXX’...
  6. Linux中xml导入数据库,XML数据库 BaseX
  7. 17 张程序员壁纸(赶快挑一张吧)
  8. 手机技巧:是否应该一次性给手机充电到100%?看完你就明白了!
  9. 计算机基础:存储系统知识笔记(一)
  10. 程序员偷偷深爱的9个不良编程习惯