日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

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

發(fā)布時(shí)間:2023/12/9 Android 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 简单音乐播放实例的实现,Android Service AIDL 远程调用服务 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

Android Service是分為兩種:

  • 本地服務(wù)(Local Service): 同一個(gè)apk內(nèi)被調(diào)用
  • 遠(yuǎn)程服務(wù)(Remote Service):被另一個(gè)apk調(diào)用

遠(yuǎn)程服務(wù)需要借助AIDL來(lái)完成。

AIDL 是什么

AIDL (Android Interface Definition Language) 是一種IDL 語(yǔ)言,用于生成可以在Android設(shè)備上兩個(gè)進(jìn)程之間進(jìn)行進(jìn)程間通信(interprocess communication, IPC)的代碼。如果在一個(gè)進(jìn)程中(例如Activity)要調(diào)用另一個(gè)進(jìn)程中(例如Service)對(duì)象的操作,就可以使用AIDL生成可序列化的參數(shù)。

AIDL IPC機(jī)制是面向接口的,像COM或Corba一樣,但是更加輕量級(jí)。它是使用代理類在客戶端和實(shí)現(xiàn)端傳遞數(shù)據(jù)。

AIDL 的作用

由于每個(gè)應(yīng)用程序都運(yùn)行在自己的進(jìn)程空間,并且可以從應(yīng)用程序UI運(yùn)行另一個(gè)服務(wù)進(jìn)程,而且經(jīng)常會(huì)在不同的進(jìn)程間傳遞對(duì)象。在Android平臺(tái),一個(gè)進(jìn)程通常不能訪問(wèn)另一個(gè)進(jìn)程的內(nèi)存空間,所以要想對(duì)話,需要將對(duì)象分解成操作系統(tǒng)可以理解的基本單元,并且有序的通過(guò)進(jìn)程邊界。

  通過(guò)代碼來(lái)實(shí)現(xiàn)這個(gè)數(shù)據(jù)傳輸過(guò)程是冗長(zhǎng)乏味的,Android提供了AIDL工具來(lái)處理這項(xiàng)工作。

選擇AIDL的使用場(chǎng)合

官方文檔特別提醒我們何時(shí)使用AIDL是必要的:只有你允許客戶端從不同的應(yīng)用程序?yàn)榱诉M(jìn)程間的通信而去訪問(wèn)你的service,以及想在你的service處理多線程。

如果不需要進(jìn)行不同應(yīng)用程序間的并發(fā)通信(IPC),you should create your interface by implementing a Binder;或者你想進(jìn)行IPC,但不需要處理多線程的,則implement your interface using a Messenger。無(wú)論如何,在使用AIDL前,必須要理解如何綁定service——bindService。

下面用一個(gè)客戶端Activity操作服務(wù)端Service播放音樂(lè)的實(shí)例演示AIDL的使用。

開發(fā)工具: eclipse 3.7(indigo)+ android sdk 4.1+ adt 20.0.2

服務(wù)端代碼結(jié)構(gòu)

客戶端代碼結(jié)構(gòu)

被標(biāo)記的就是需要?jiǎng)邮值摹?

服務(wù)端

新建一個(gè)android application project,命名為PlayerServer。 在res下的raw文件夾里面放入一個(gè)音樂(lè)文件,我這里放入的是Delta Goodrem的《Lost Without You》片段。如果不存在raw這個(gè)文件夾就自己新建一個(gè),命名為raw。這個(gè)文件夾在raw文件夾下,與layout文件夾平級(jí)。raw中的文件遵守標(biāo)識(shí)符的命名規(guī)則,不要出現(xiàn)中文和空格,多個(gè)單詞可以用下劃線連接。

新建一個(gè)IRemoteServiice.aidl 文件,加入如下代碼:

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

可見(jiàn)aidl文件的代碼跟java的interface一樣,但是aidl中不能加public等修飾符。Ctrl + S 保存后 ADT 會(huì)根據(jù)這個(gè)IRemoteService.aidl文件自動(dòng)生成IRemoteService.java文件。如同R.java文件一樣在“gen/包名”下,代碼是自動(dòng)生成的,不要手動(dòng)修改。

接下來(lái)就是bound service(參考:官方文檔)的知識(shí)了。IRemoteService.java 中有一個(gè)Stub靜態(tài)抽象類extends Binder implements IRemoteService。自己動(dòng)手寫一個(gè)PlayerService 用來(lái)播放音樂(lè),播放音樂(lè)需要使用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;/*** 播放音樂(lè)的服務(wù)* @author Panda Fang* @date 2012-10-22 10:15:33*/public class PlayerService extends Service {public static final String TAG = "PlayerService";private MediaPlayer mplayer;// 實(shí)現(xiàn)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。// 如果前面實(shí)例化mplayer時(shí)使用方法一,則第一次play的時(shí)候直接start,不用prepare。// 但是stop一次之后,再次play就需要在start之前prepare了。// 前面使用方法二 這里就簡(jiǎn)便了, 不用判斷各種狀況mplayer.prepare();mplayer.start();} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}};@Overridepublic IBinder onBind(Intent intent) {Log.i(TAG,"service onbind");if(mplayer==null){// 方法一說(shuō)明// 此方法實(shí)例化播放器的同時(shí)指定音樂(lè)數(shù)據(jù)源 ,若用此方法在,mplayer.start() 之前不需再調(diào)用mplayer.prepare() // 官方文檔有說(shuō)明 :On success, prepare() will already have been called and must not be called again.// 譯文:一旦create成功,prepare已被調(diào)用,勿再調(diào)用 。查看源代碼可知create方法內(nèi)部已經(jīng)調(diào)用prepare方法。// 方法一開始// mplayer = MediaPlayer.create(this, R.raw.lost);// 方法一結(jié)束// 方法二說(shuō)明// 若用此方法,在mplayer.start() 之前需要調(diào)用mplayer.prepare() // 方法二開始mplayer = new MediaPlayer();try {FileDescriptor fd = getResources().openRawResourceFd(R.raw.lost).getFileDescriptor(); // 獲取音樂(lè)數(shù)據(jù)源mplayer.setDataSource(fd); // 設(shè)置數(shù)據(jù)源mplayer.setLooping(true); // 設(shè)為循環(huán)播放} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}// 方法二結(jié)束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);}}

服務(wù)編寫好以后,按照慣例在AndroidManifest.xml中加入聲明,代碼如下:

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

運(yùn)行服務(wù)端到設(shè)備上,準(zhǔn)備給客戶端調(diào)用。

客戶端

新建一個(gè)android application project,命名為PlayerClient。將服務(wù)端放有aidl文件的包直接copy到客戶端src目錄下,保留包中的aidl文件,其他刪除。

編輯 layout 下的 activity_main.xml 布局文件,加入兩個(gè)按鈕,代碼如下:

編寫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";// 服務(wù)端 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是根據(jù)向?qū)ё詣?dòng)生成的,不需要在AndroidManifest.xml中注冊(cè)聲明了。

運(yùn)行客戶端到設(shè)備,按下按鈕可以播放/停止 效果如圖:

源代碼下載:http://files.cnblogs.com/lonkiss/AIDLPlayer.zip

更多詳細(xì)請(qǐng)參考:http://www.baisoujs.com/detail_137434192972690.html

轉(zhuǎn)載于:https://my.oschina.net/u/1189001/blog/147443

總結(jié)

以上是生活随笔為你收集整理的简单音乐播放实例的实现,Android Service AIDL 远程调用服务的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。