Android开源项目之Music (二)--- AIDL实现IPC进程间通讯

2024-05-31 04:08

本文主要是介绍Android开源项目之Music (二)--- AIDL实现IPC进程间通讯,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

根据上一篇  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,写入以下代码.

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 TAGpublic static final String LogTAG = "com.example.aidlserver.MyMusicPlayerService";//android自带播放音乐类: android.media.MediaPlayerprivate MediaPlayer mPlayer = null;@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubif (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 blocke.printStackTrace();} catch (IllegalStateException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}return mBinder;}@Overridepublic boolean onUnbind(Intent intent) {// TODO Auto-generated method stubif (mPlayer != null){//释放资源mPlayer.release();}return super.onUnbind(intent);}/*** 实现了接口中的两个函数*/private IBinder mBinder = new IMyMusicPlayerService.Stub() {@Overridepublic void stop() throws RemoteException {// TODO Auto-generated method stubif (mPlayer.isPlaying()){//停止播放mPlayer.stop();}}@Overridepublic void play() throws RemoteException {// TODO Auto-generated method stubtry {if (!mPlayer.isPlaying()){mPlayer.prepare();mPlayer.start();}} catch (Exception e) {// TODO: handle exceptionLog.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 TAGpublic 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断开连接时,调用*/@Overridepublic void onServiceDisconnected(ComponentName name) {isBinded = false;mService = null;}/*Service连接时,调用*/@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mService = IMyMusicPlayerService.Stub.asInterface(service);isBinded = true;}};@Overrideprotected 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;}}@Overridepublic 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() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubswitch (v.getId()) {case R.id.play:{if (mService != null){try {mService.play();} catch (RemoteException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}break;case R.id.stop:{if (mService != null){try {mService.stop();} catch (RemoteException e) {// TODO Auto-generated catch blocke.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开源项目之Music (二)--- AIDL实现IPC进程间通讯的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1017357

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影