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

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

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中注册声明了。

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

Android Service AIDL 远程调用服务 - 简单音乐播放实例

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/293108.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# 使用int.TryParse,Convert.ToInt32,(int)将浮点类型转换整数时的区别

int.TryParse,Convert.ToInt32,(int) 这几种类型在将浮点类型转换整数时是有差别Convert.ToInt32则会进行四舍五入int.TryParse只能转换整数,即浮点类型全部会返回0(int)不会进行四舍五入,只取整数部分,小数点部分完全舍弃using System;public class DoubleToInt{public …

每个女孩子起床后做的第一件事......

1 假如你暴富了(素材来源网络,侵删)▼2 当客服到底有多难?(素材来源网络,侵删)▼3 挺好的(素材来源网络,侵删)▼4 每个女孩子起床后做的第一件事&#xff…

java之InetAddress类和InetSocketAddress的使用

一、简介 InetAddress是Java对IP地址的封装,代表互联网协议(IP)地址;InetAddress对象的获取只能通过静态方法,比如根据主机名获取主机的ip地址封装对象: InetAddress addInetAddress.getByName("BOPZ…

国产知名老牌 PDF 工具正式开源

文 | Travis出品 | OSC开源社区(ID:oschina2013)「PDF 补丁丁」是开发者 wmjordan 所开发的一款适用于 Windows 系统的多功能 PDF 文档工具箱,开发者最早于 2009 年开始了该程序的开发,如今已有十二年历史,…

.net Repeater知识知多少

&#xff08;一&#xff09;.net中使用Repeater绑定数据&#xff0c;并使用repeater循环出的两个值&#xff0c;赋给repeater中的div的value值。详细如下&#xff1a; 前端.net代码&#xff1a; <div class"wytz_xmlb_nr clear"><asp:Repeater ID"RpBi…

Centos Missing Library: QtWebKit.so.4

/*********************************************************************   Centos Missing Library: QtWebKit.so.4* 说明&#xff1a;* 这是测试在Centos上运行烧机程序时遇到的问题&#xff0c;记录一下解决办法。* * 2016-9…

目瞪口呆!137亿年的宇宙演化,竟然如此震撼!简直颠覆想象....

▲ 点击查看1968年圣诞节&#xff0c;阿波罗8号在环月球轨道上拍摄了一张照片。这是地球拥有的第一张自拍。也让人类第一次感受到&#xff0c;原来在广阔无垠的宇宙中&#xff0c;地球不过是一个美丽而又珍贵的孤岛。1990年&#xff0c;旅行者1号完成了所有的观测使命&#xff…

python数字从大到小排列_Python练习题 005:三个数字由大到小排序输出

【Python练习题 005】输入三个整数x,y,z&#xff0c;请把这三个数由小到大输出。 ----------------------------------------------------------------------- 这题想想应该比较容易&#xff1a;无非是先获取3个数字&#xff0c;然后比大小&#xff0c;按顺序输出即可。不过在写…

Android之运行的错误:java.lang.UnsatisfiedLinkError: Couldn‘t find cibloger.so

原因&#xff1a; 因为没有找到相遇的so文件 解决办法&#xff1a; 在eclipse里面的lib文件夹里面的armeabi文件夹加上相应的so文件就可以了

Martin Fowler:数字化时代,远程与本地协同工作孰优孰劣?| IDCF

作者&#xff1a;Martin Fowler译者&#xff1a;冬哥原文&#xff1a;https://martinfowler.com/articles/remote-or-co-located.html远程工作与同地工作之间不是简单的二分法&#xff0c;相反&#xff0c;团队有多种分布模式&#xff0c;每种模式都有不同的权衡和适合的有效技…

android:自己实现能播放网络视频url的播放器

2019独角兽企业重金招聘Python工程师标准>>> android原生自带的播放器一般只能播放本地视频&#xff0c;而没有播放url的功能。不过android系统中有一个VideoView的控件可以实现这一功能。 简单实现如下&#xff1a; public class MyVideoPlay extends Activity i…

Ant 学习

到了新公司&#xff0c;发现公司使用ant 来代码生成。本来学习后写下来。在网上找到一篇教程&#xff0c;实在是非常给力。。。 就把连接记下来吧&#xff1a;http://www.blogjava.net/amigoxie/archive/2007/11/09/159413.html 可以一起学习。转载于:https://www.cnblogs.com/…

iOS调用系统相册、相机 显示中文标题

2019独角兽企业重金招聘Python工程师标准>>> 最终在info.plist设置解决问题 发现在项目的info.plist里面添加Localized resources can be mixed 设置为&#xff1a; YES&#xff08;表示是否允许应用程序获取框架库内语言&#xff09;即可解决这个问题。 转载于:htt…

linux之nl命令

nl命令在linux系统中用来计算文件中行号。nl 可以将输出的文件内容自动的加上行号&#xff01;其默认的结果与 cat -n 有点不太一样&#xff0c; nl 可以将行号做比较多的显示设计&#xff0c;包括位数与是否自动补齐 0 等等的功能。 1&#xff0e;命令格式&#xff1a; nl […

使用云原生应用和开源技术的创新攻略

Kubernetes 和云原生应用的增长以及普及是现象级的。根据 IDC 的数据&#xff0c;到2025年&#xff0c;90%以上的新应用程序将是云原生的。许多客户已受益于云原生设计模型&#xff0c;让新一代应用程序更加敏捷、可靠、可扩展&#xff0c;还兼顾了安全。说到服务的开发&#x…

SVM支持向量机原理及核函数

原文链接&#xff1a;SVM支持向量机原理及核函数 转载请注明出处 支持向量机原理 大距离分类算法 1、名词解释&#xff1a; 分割超平面&#xff1a;如下图所示&#xff0c;构造一个分割线把圆形的点和方形的点分开&#xff0c;这个线称为分割超平面。支持向量&#xff1a;…

SQL对Xml字段的操作

转&#xff1a;http://www.cnblogs.com/youring2/archive/2008/11/27/1342288.html T-Sql操作Xml数据 一、前言 SQL Server 2005 引入了一种称为 XML 的本机数据类型。用户可以创建这样的表&#xff0c;它在关系列之外还有一个或多个 XML 类型的列&#xff1b;此外&#xff0c;…

URL 路径长度限制(错误:指定的文件或文件夹名称太长)

本节讨论 URL 的构成、SharePoint 2010 构建 URL 的方式、URL 的编码和加长以及作为其他 URL 中的参数传递的方式。 SharePoint URL 的构成 SharePoint URL 的总长度等于文件夹或文件路径的长度&#xff0c;包括协议和服务器名称和文件夹或文件名称&#xff0c;以及作为 URL 的…

linux之less 命令

less 工具也是对文件或其它输出进行分页显示的工具&#xff0c;应该说是linux正统查看文件内容的工具&#xff0c;功能极其强大。less 的用法比起 more 更加的有弹性。在 more 的时候&#xff0c;我们并没有办法向前面翻&#xff0c; 只能往后面看&#xff0c;但若使用了 less …