Android移動應用開發(fā)(微課視頻版)課件 第6章 多媒體開發(fā)_第1頁
Android移動應用開發(fā)(微課視頻版)課件 第6章 多媒體開發(fā)_第2頁
Android移動應用開發(fā)(微課視頻版)課件 第6章 多媒體開發(fā)_第3頁
Android移動應用開發(fā)(微課視頻版)課件 第6章 多媒體開發(fā)_第4頁
Android移動應用開發(fā)(微課視頻版)課件 第6章 多媒體開發(fā)_第5頁
已閱讀5頁,還剩93頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第6章

多媒體開發(fā)CONTENTS目錄02

BroadcastReceiver01

Service03

頻04

頻05

綜合實例-多媒體播放器Service016.1.1Service的作用在Android系統(tǒng)中,Service不是一個單獨的進程,除非特殊設定,否則它不會單獨運行在自己的進程中,通常情況下它是作為啟動應用程序的一部分與當前應用程序運行在同一個進程中。服務程序Service是一種可以在后臺長時間運行并且不提供用戶UI的程序。即使啟動Service的應用程序被切換掉,其啟動的Service也可以在后臺正常運行。因此,Service經常被用來處理一些耗時比較長的程序,例如進行網絡傳輸或播放音樂等。6.1.2Service的生命周期Android開發(fā)中,當需要創(chuàng)建在后臺運行的程序的時候,就要用到Service。Service可以分為有無限生命和有限生命兩種。需要特別注意的是,Service跟Activity是不同的。簡單來說,可以理解為后臺與前臺的區(qū)別,Activity擁有UI,可以與用戶交互,而Service則不能。當系統(tǒng)資源不足時,Activity可能會被系統(tǒng)銷毀以釋放資源,而Service不會。Service類中定義了一系列和自身生命周期相關的方法,在此不一一介紹,最經常使用的有以下三個方法:onCreate()當Service第一次被創(chuàng)建時,系統(tǒng)調用該方法。onStartCommand(Intentintent,intflags,intstartId)

當通過startService()方法啟動Service時,該方法被調用。onDestroy()當Service不再使用時,系統(tǒng)調用該方法。6.1.3啟動Service要啟動服務程序Service,要先在應用程序的AndroidManifest.XML配置文件內聲明<service>標簽。例如,如果建立了一個ExampleService的Service,就要在配置文件中添加如下代碼:<serviceandroid:name=“.ExampleService”/>此外,<service>標簽可用含有<intent-filter>的標簽對該Service進行必要的說明。啟動Service有兩種方式:Context.startService()和Context.bindService()。publicabstractvoidstartService(Intentintent)。其中,參數intent是包含要啟動的服務程序信息的Intent。從Android5.0開始,Service已經不支持隱式Intent啟動。這意味著intent中必須包含要啟動的Service對象的名字。publicabstractbooleanbindService(Intentservice,ServiceConnectionconn,intflags)。其中,參數service是定義要綁定的服務程序的名稱;conn是當服務程序啟動和停止時,負責接收信息的接口程序;flags是設置綁定作業(yè)的選項,可以是0、BIND_AUTO_CREATE、BIND_DEBUG_UNBIND、BIND_NOT_FOREGROUND、BIND_ABOVE_CLIENT、BIND_ALLOW_OOM_MANAGEMENT或者BIND_WAIVE_PRIORITY。通過startService()來啟動Service,該方法會調用Service中的onCreate()和onStartCommand()方法來啟動一個后臺Service,當Service銷毀時直接調用onDestroy()方法。若通過bindService()方法啟動Service,則其生命周期受其綁定對象控制。一個Service可以同時綁定到多個對象上,當沒有任何對象綁定到Service上時,該Service會被系統(tǒng)銷毀。兩種方式對Service生命周期的影響如圖6.1所示。由圖6.1不難看出,通過bindService()方法啟動時和startService()方法一樣,都會調用onCreate()方法來創(chuàng)建Service,但它不會調用onStartCommand()方法,而是調用onBind()方法返回客戶端一個IBinder接口。這個IBinder就是在Service的生命周期回調方法onBind()中的返回值。服務運行后,與前者不同的是,不是服務終止,而是使用Context.unbindService()方法之后,Service的生命周期回調onUnbind()會被調用。如果所有bind過Service的組件都調用unbindService()方法,那么之后Service會被停止,其onDestroy()回調會被調用。圖6.1

兩種方式的比較BroadcastReceiver022.2.1JDK的安裝

廣播(Broadcast)是Android系統(tǒng)中應用程序間通信的手段。當有特定事件發(fā)生時,例如有來電、有短信、電池電量變化等事件發(fā)生時,Android系統(tǒng)都會產生特定的Intent對象并且自動進行廣播,而針對特定事件注冊的BroadcastReceiver會接收到這些廣播,并獲取Intent對象中的數據進行處理。在廣播Intent對象時可以指定用戶權限,以此限制僅有獲得了相應權限的BroadcastReceiver才能接收并處理對應的廣播。BroadcastReceiver有動態(tài)和靜態(tài)兩種注冊方法。動態(tài)注冊方法即使用Context.registerReceiver()方法進行注冊,需要特別注意的是,動態(tài)注冊方法在退出程序前要使用Context.unregisterReceiver()方法撤銷注冊。靜態(tài)注冊方法即在AndroidManifest.xml.文件中通過<receiver>標簽進行注冊。一個BroadcastReceiver對象只有在被調用onReceive(Context,Intent)時才有效,當從該函數返回后,該對象就已無效了,其生命周期結束。下面介紹如何使用動態(tài)注冊來實現(xiàn)監(jiān)聽電池剩余電量。實例BatteryDemo演示了使用動態(tài)注冊BroadcastReceiver對象并且接收系統(tǒng)電量改變事件并加以處理的過程,運行效果如圖6.2所示。圖6.2BatteryDemo的運行效果實例BatteryDemo中main.xml的代碼如下:<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical">

<ToggleButtonandroid:id="@+id/button"android:textOn="檢測當前手機電量"android:textOff="停止檢測"android:layout_width="fill_parent"android:layout_height="wrap_content"/>

<TextViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:id="@+id/text"/></LinearLayout>實例BatteryDemo中AndroidManifest.xml的代碼如下:<?xmlversion="1.0"encoding="utf-8"?><manifestxmlns:android="/apk/res/android"package="introduction.android.batteryDemo"android:versionCode="1"android:versionName="1.0"><uses-sdkandroid:minSdkVersion="14"/><applicationandroid:icon="@drawable/ic_launcher"android:label="@string/app_name"><activityandroid:name="introduction.android.batteryDemo.BatteryDemoActivity"android:label="@string/app_name"><intent-filter><actionandroid:name="ent.action.MAIN"/><categoryandroid:name="ent.category.LAUNCHER"/></intent-filter></activity></application></manifest>實例BatteryDemo中BatteryDemoActivity.java的具體實現(xiàn)代碼如下:packageintroduction.android.batteryDemo;importintroduction.android.batteryDemo.R;importandroid.app.Activity;importandroid.content.BroadcastReceiver;importandroid.content.Context;importandroid.content.Intent;importandroid.content.IntentFilter;importandroid.os.Bundle;importandroid.widget.CompoundButton;importandroid.widget.CompoundButton.OnCheckedChangeListener;importandroid.widget.TextView;importandroid.widget.ToggleButton;publicclassBatteryDemoActivityextendsActivity{ /**Calledwhentheactivityisfirstcreated.*/ privateToggleButtonbutton; privateTextViewtext; BroadcastReceiverreceiver=null; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); button=(ToggleButton)findViewById(R.id.button); text=(TextView)findViewById(R.id.text);finalBroadcastReceiverreceiver=newBroadcastReceiver(){ @Override publicvoidonReceive(Contextcontext,Intentintent){ //TODOAuto-generatedmethodstub Stringaction=intent.getAction(); if(Intent.ACTION_BATTERY_CHANGED.equals(action)){ intcurrent=intent.getExtras().getInt("level");//獲取當前電量 inttotal=intent.getExtras().getInt("scale");//獲取總電量 intvalue=current*100/total; text.setText("當前電量是"+value+"%"+""); } } }; button.setOnCheckedChangeListener(newOnCheckedChangeListener(){ publicvoidonCheckedChanged(CompoundButtonbuttonView, booleanisChecked){ //TODOAuto-generatedmethodstub if(isChecked){ IntentFilterfilter=newIntentFilter( Intent.ACTION_BATTERY_CHANGED); registerReceiver(receiver,filter); }else{ unregisterReceiver(receiver); text.setText(""); } } }); }}其中,Intent.ACTION_BATTERY_CHANGED為當電池電量變化時產生的Intent對象中攜帶的Action信息。IntentFilterfilter=newIntentFilter(Intent.ACTION_BATTERY_CHANGED)

;用于確定當前BroadcastReceiver對象接收的Intent對象的類型。registerReceiver(receiver,filter)動態(tài)注冊receiver。intcurrent=intent.getExtras().getInt("level")獲取當前電池的電量。inttotal=intent.getExtras().getInt("scale")獲取總電量。unregisterReceiver(receiver)注銷receiver注冊。該應用程序若要使用靜態(tài)注冊,則需要在AndroidManifest.xml文件中添加如下代碼:<receiverandroid:name="receiver"><intent-filter><actionandroid:name="ent.action.BATTERY_CHANGED"/></intent-filter></receiver>音

頻03Android系統(tǒng)支持三種不同來源的音頻播放:(1)本地資源存儲在應用程序中的資源,例如存儲在RAW文件夾下的媒體文件,只能被當前應用程序訪問。(2)外部資源存儲在文件系統(tǒng)中的標準媒體文件,例如存儲在SD卡中的文件,可以被所有應用程序訪問。(3)網絡資源通過網絡地址取得的數據流(URL),例如“/classic/007.mp3”,可以被所有應用程序訪問。6.3.1Android16支持的音頻格式Android16支持的音頻格式如表6.1所示。格式

/編碼支持的文件類型AACLC/LTP3GPP(.3gp)MPEG-4(.mp4,.m4a)ADTSrawAACMPEG-TS(.ts,notseekable,Android3.0+)

HE-AACv1(AAC+)HE-AACv2(enhancedAAC+)AMR-NB3GPP(.3gp)AMR-WB3GPP(.3gp)FLACFLAC(.flac)onlyMP3MP3(.mp3)MIDIType0and1(.mid,.xmf,.mxmf)RTTTL/RTX(.rtttl,.rtx)OTA(.ota)iMelody(.imy)VorbisOgg(.ogg)MatroskaPCM/WAVEWAVE(.wav)6.3.2音頻播放器

實例MediaPlayerAudioDemo演示了分別播放三種類型的資源的方法。該實例中MediaPlayerAudioActivity向Intent對象中傳入要載入的資源類型,并通過該Intent啟動用于播放音樂的Activity:PlayAudio。PlayAudio根據傳入的參數分別獲取對應的音樂資源并且播放。實例MediaPlayerAudioDemo的運行效果如圖6.3所示。AndroidStudio的AVD可以通過View|ToolWindows|DeviceExplorer菜單瀏覽AVD的文件結構,把相關音樂文件放置到對應文件夾下。圖6.3

MediaPlayerAudioDemo的運行效果實例MediaPlayerAudioDemo中的main.xml代碼如下:<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res/android"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:text="播放存儲在文件系統(tǒng)的音樂"android:id="@+id/button01"

/><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:text="播放網絡中的音樂"android:id="@+id/button02"

/><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:text="播放本地資源的音樂"android:id="@+id/button03"

/></LinearLayout>實例MediaPlayerAudioDemo中MediaPlayerAudioActivity.java文件的代碼如下:packageintroduction.android.mediaplayer;importandroid.app.Activity;importandroid.content.Intent;importandroid.os.Bundle;importandroid.view.View;importandroid.view.View.OnClickListener;importandroid.widget.Button;publicclassMediaPlayerAudioActivityextendsActivityimplementsOnClickListener{/**Calledwhentheactivityisfirstcreated.*/ privateButtonbutton01,button02,button03; privateStringPLAY="play"; privateintLocal=1; privateintStream=2; privateintResources=3;@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);button01=(Button)findViewById(R.id.button01);button02=(Button)findViewById(R.id.button02);button03=(Button)findViewById(R.id.button03);button01.setOnClickListener(this);button02.setOnClickListener(this);button03.setOnClickListener(this);} @Override publicvoidonClick(Viewv){ //TODOAuto-generatedmethodstub Intentintent=newIntent(MediaPlayerAudioActivity.this,PlayAudio.class); if(v==button01){ intent.putExtra(PLAY,Local); } if(v==button02){ intent.putExtra(PLAY,Stream); } if(v==button03){ intent.putExtra(PLAY,Resources); } MediaPlayerAudioActivity.this.startActivity(intent); }}實例MediaPlayerAudioDemo中PlayAudio類實現(xiàn)播放音頻的功能,根據MediaPlayer-AudioActivity類通過Intent傳遞過來的不同的值,而實現(xiàn)三種不同的播放音頻的方式。PlayAudio.java文件的代碼如下:packageroduction.mediaplayeraudiodemo;importandroid.Manifest;importandroid.app.Activity;importandroid.content.pm.PackageManager;importandroid.media.MediaPlayer;importandroid.os.Build;importandroid.os.Bundle;importandroid.os.Environment;importandroid.widget.TextView;importandroid.widget.Toast;importandroidx.annotation.NonNull;publicclassPlayAudioextendsActivity{ privateTextViewtextview; privateStringPLAY="play"; privateMediaPlayermidiaplayer; privateStringpath; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.other); textview=(TextView)findViewById(R.id.textview); Bundleextras=getIntent().getExtras(); playAudio(extras.getInt(PLAY)); } privatevoidplayAudio(intplay){ try{ switch(play){ case1: checkStoragePermission(); path="/storage/emulated/0/Music/music.mp3"; midiaplayer=newMediaPlayer(); midiaplayer.setDataSource(path); midiaplayer.prepare(); midiaplayer.start(); textview.setText("正在播放文件系統(tǒng)中的音樂"); break;case2: path="/classic/007.mp3"; midiaplayer=newMediaPlayer(); midiaplayer.setDataSource(path); midiaplayer.prepare(); midiaplayer.start(); textview.setText("正在播放網絡中的音樂"); break; case3: midiaplayer=MediaPlayer.create(this,R.raw.music); midiaplayer.start(); textview.setText("正在播放本地資源中的音樂"); break; } }catch(Exceptione){ Toast.makeText(this,"播放錯誤:"+e.getMessage(),Toast.LENGTH_LONG).show(); e.printStackTrace(); } } //checkandrequestpermission privatebooleancheckStoragePermission(){ if(checkSelfPermission(Manifest.permission.READ_MEDIA_AUDIO) !=PackageManager.PERMISSION_GRANTED){ requestPermissions(newString[]{Manifest.permission.READ_MEDIA_AUDIO}, REQUEST_CODE_STORAGE_PERMISSION); returnfalse; } returntrue; }privatestaticfinalintREQUEST_CODE_STORAGE_PERMISSION=100; //Handlepermissionresult @Override publicvoidonRequestPermissionsResult(intrequestCode,@NonNullString[]permissions, @NonNullint[]grantResults){ super.onRequestPermissionsResult(requestCode,permissions,grantResults); if(requestCode==REQUEST_CODE_STORAGE_PERMISSION){ if(grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){ //Permissiongranted,retryplayingaudio Toast.makeText(this,"Permissiongranted",Toast.LENGTH_SHORT).show(); Bundleextras=getIntent().getExtras(); playAudio(extras.getInt(PLAY)); }else{ Toast.makeText(this,"Permissiondenied",Toast.LENGTH_SHORT).show(); } } } @Override protectedvoidonDestroy(){ super.onDestroy(); if(midiaplayer!=null){ midiaplayer.release(); midiaplayer=null; } }}其中,path指向要播放的音頻文件的位置。本實例中,文件系統(tǒng)中的資源是放置在內部存儲卡中的Music目錄下的music.mp3;網絡資源使用的是/classic/007.mp3;本地資源使用的是raw目錄下的music.mp3文件。if(checkSelfPermission(Manifest.permission.READ_MEDIA_AUDIO) !=PackageManager.PERMISSION_GRANTED){ requestPermissions(newString[]{Manifest.permission.READ_MEDIA_AUDIO}, REQUEST_CODE_STORAGE_PERMISSION); returnfalse; }以上幾行代碼是動態(tài)申請讀取存儲器上的音頻文件的權限。實例MediaPlayerAudioDemo中AndroidManifest.xml文件的代碼如下:<?xmlversion="1.0"encoding="utf-8"?><manifestxmlns:android="/apk/res/android"xmlns:tools="/tools"><uses-permissionandroid:name="android.permission.READ_MEDIA_AUDIO"/><applicationandroid:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.MediaPlayerAudioDemo"tools:targetApi="31"><activityandroid:name=".MediaPlayerAudioActivity"android:exported="true"android:label="@string/app_name"><intent-filter><actionandroid:name="ent.action.MAIN"/><categoryandroid:name="ent.category.LAUNCHER"/></intent-filter></activity><activityandroid:name="PlayAudio"></activity></application></manifest>該實例需要聲明讀取音頻的權限:<uses-permissionandroid:name="android.permission.READ_MEDIA_AUDIO"/>在該實例中,每次播放音頻文件時都會從MediaPlayerAudioActivity跳轉到一個新的Activity,即PlayAudio。當返回MediaPlayerAudioActivity時,由于PlayAudio對象被釋放掉,因此播放的音樂也隨之停止,不再播放。若想在返回MediaPlayerAudioActivity時音樂不停止,則需要使用Service在后臺播放音頻文件。6.3.3后臺播放音頻實例AudioServiceDemo演示了如何在后臺播放音頻。該實例的運行效果如圖6.4所示。當用戶單擊“啟動Service”按鈕時,當前Activity結束,應用程序界面消失,返回Android應用程序列表,同時后臺啟動Service,播放視頻文件。圖6.4

AudioServiceDemo的運行效果該實例界面簡單,僅兩個按鈕,第一個按鍵啟動Service播放音樂,第二個按鍵停止Service。布局文件main.xml的代碼如下:<?xmlversion="1.0"encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="/apk/res/android"xmlns:app="/apk/res-auto"xmlns:tools="/tools"android:id="@+id/linearLayout"android:layout_width="fill_parent"android:layout_height="fill_parent"><Buttonandroid:id="@+id/button1"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_marginTop="100dp"android:text="@string/button"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"/><Buttonandroid:id="@+id/button2"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_marginTop="100dp"android:text="@string/button2"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="@+id/button1"/></androidx.constraintlayout.widget.ConstraintLayout>實例AudioServiceDemo中Activity文件AudioServiceDemoActivity.java的代碼如下:packageroduction.audioservicedemo;importandroid.Manifest;importandroid.app.Activity;importandroid.content.Intent;importandroid.content.pm.PackageManager;importandroid.os.Bundle;importandroid.view.View;importandroid.widget.Button;publicclassAudioServiceDemoActivityextendsActivity{privatestaticfinalintREQUEST_CODE_STORAGE_PERMISSION=100;/**Calledwhentheactivityisfirstcreated.*/ privateButtonbtn,btn2;@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);btn=(Button)findViewById(R.id.button1);btn.setOnClickListener(newView.OnClickListener(){ @Override publicvoidonClick(Viewv){ //TODOAuto-generatedmethodstubcheckStoragePermission();Intentintent=newIntent(AudioServiceDemoActivity.this,MyAudioService.class);startService(intent); } });btn2=(Button)findViewById(R.id.button2);btn2.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewv){//TODOAuto-generatedmethodstubcheckStoragePermission();Intentintent=newIntent(AudioServiceDemoActivity.this,MyAudioService.class);stopService(intent);}});}privatebooleancheckStoragePermission(){if(checkSelfPermission(Manifest.permission.READ_MEDIA_AUDIO)!=PackageManager.PERMISSION_GRANTED){requestPermissions(newString[]{Manifest.permission.READ_MEDIA_AUDIO},REQUEST_CODE_STORAGE_PERMISSION);returnfalse;}returntrue;}}AudioServiceDemoActivity在第一個按鈕被單擊后使用startService()方法啟動了播放音樂的服務MyAudioService。在第二個按鍵被單擊后使用stopService()方法停止了該服務。該服務需要在AndroidManifest.xml文件中進行聲明。AndroidManifest.xml的代碼如下:<?xmlversion="1.0"encoding="utf-8"?><manifestxmlns:android="/apk/res/android"xmlns:tools="/tools"><uses-permissionandroid:name="android.permission.READ_MEDIA_AUDIO"/><applicationandroid:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.AudioServiceDemo"tools:targetApi="36"><activityandroid:name=".AudioServiceDemoActivity"android:exported="true"android:label="@string/app_name"><intent-filter><actionandroid:name="ent.action.MAIN"/><categoryandroid:name="ent.category.LAUNCHER"/></intent-filter></activity><serviceandroid:name="MyAudioService"android:exported="true"/></application></manifest>其中:<serviceandroid:name="MyAudioService"android:exported="true"/>定義了名為MyAudioService的Service。實例AudioServiceDemo中MyAudioService.java的代碼如下:packageroduction.audioservicedemo;importjava.io.IOException;importandroid.app.Service;importandroid.content.Intent;importandroid.media.MediaPlayer;importandroid.os.IBinder;importandroid.util.Log;publicclassMyAudioServiceextendsService{ privateMediaPlayermediaplayer; @Override publicIBinderonBind(Intentarg0){ //TODOAuto-generatedmethodstub returnnull; } @Override publicvoidonDestroy(){ //TODOAuto-generatedmethodstub super.onDestroy(); if(mediaplayer!=null) { mediaplayer.release(); mediaplayer=null; } } @Override publicintonStartCommand(Intentintent,intflags,intstartId){ Stringpath="/storage/emulated/0/Music/music.mp3"; mediaplayer=newMediaPlayer(); try{ mediaplayer.setDataSource(path); mediaplayer.prepare(); mediaplayer.start(); }catch(IOExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } returnsuper.onStartCommand(intent,flags,startId); }}該服務啟動Mediaplayer,并播放存放于內部存儲卡中的“/storage/emulated/0/Music/music.mp3”文件。6.3.4錄音程序

AndroidSDK提供了使用MediaRecorder類實現(xiàn)對音頻和視頻進行錄制的功能。MediaRecorder對象在運行過程中存在多種狀態(tài),其狀態(tài)轉化如圖6.5所示。從圖6.5中可以看到:(1)創(chuàng)建MediaRecorder對象后處于Initial狀態(tài),MediaRecorder對象會占用硬件資源,因此不再需要時,應該調用release()方法銷毀。在其他狀態(tài)調用reset()方法,可以使得MediaRecorder對象重新回到Initial狀態(tài),達到復用MediaRecorder對象的目的。(2)在Initial狀態(tài)調用setVideoSource()或者setAudioSource()之后,MediaRecorder將進入Initialized狀態(tài)。對于音頻錄制,目前OPhone平臺支持從麥克風或者電話兩個音頻源錄制數據。在Initialized狀態(tài)的MediaRecorder還需要設置編碼格式、文件數據路徑、文件格式等信息,設置之后MediaRecorder進入DataSourceConfigured狀態(tài)。(3)在DataSourceConfigured狀態(tài)調用prepare()方法,MediaRecorder對象將進入Prepared狀態(tài),錄制前的狀態(tài)準備就緒。(4)在Prepared狀態(tài)調用start()方法,MediaRecorder進入Recording狀態(tài),聲音錄制可能只需一段時間,這時MediaRecorder一直處于錄制狀態(tài)。(5)在Recording狀態(tài)調用stop()方法,MediaRecorder將停止錄制,并將錄制內容輸出到指定文件。MediaRecorder定義了兩個內部接口OnErrorListener和OnInfoListener來監(jiān)聽錄制過程中的錯誤信息。例如,當錄制的時間長度達到了最大限制或者錄制文件的大小達到了最大文件限制時,系統(tǒng)會回調已經注冊的OnInfoListener接口的onInfo()方法。圖6.5

MediaRecorder對象狀態(tài)轉化圖使用MediaRecorder類進行音頻錄制的基本步驟如下:

建立MediaRecorder類的對象。MediaRecorderrecorder=newMediaRecorder(this);

設置音頻來源。recorder.setAudioSource(MediaRecorder.AudioSource.MIC);

設置音頻輸出格式。recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);

設置音頻編碼方式。recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

設置音頻文件的保存位置及文件名。recorder.setOutputFile(PATH_NAME);

將錄音器置于準備狀態(tài)。recorder.prepare();

啟動錄音器。recorder.start();

音頻錄制。

音頻錄制完成,停止錄音器。recorder.stop();

釋放錄音器對象。recorder.release();實例AudioRecord演示了使用MediaRecorder類對音頻進行錄制的過程,運行效果如圖6.6所示。圖6.6

AudioRecord的運行效果該運行效果對應的布局文件main.xml的代碼如下:<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical"><TextViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_marginLeft="70dp"android:layout_marginTop="30dp"android:text="@string/hello"/><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_marginTop="30dp"android:orientation="horizontal"><ImageButtonandroid:id="@+id/st"android:layout_width="40dp"android:layout_height="80dp"android:layout_marginLeft="20dp"android:contentDescription="開始錄音"android:layout_weight="1"android:scaleType="fitXY"android:src="@drawable/open"/><ImageButtonandroid:id="@+id/stop"android:layout_width="40dp"android:layout_height="80dp"android:layout_marginLeft="30dp"android:contentDescription="停止錄音"android:layout_weight="1"android:scaleType="fitXY"android:src="@drawable/close"/></LinearLayout><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="81dp"android:text="@string/start"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="143dp"android:text="@string/stop"/></LinearLayout><TextViewandroid:id="@+id/sttext"android:layout_width="fill_parent"android:layout_height="wrap_content"/></LinearLayout>實例AudioRecord中AndroidManifest.xml文件的代碼如下:<?xmlversion="1.0"encoding="utf-8"?><manifestxmlns:android="/apk/res/android"xmlns:tools="/tools"><uses-permissionandroid:name="android.permission.RECORD_AUDIO"/><applicationandroid:allowBackup="true"android:dataExtractionRules="@xml/data_extraction_rules"android:fullBackupContent="@xml/backup_rules"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.AudioRecord"tools:targetApi="31"><activityandroid:name=".AudioRecordDemo"android:exported="true"android:label="@string/app_name"><intent-filter><actionandroid:name="ent.action.MAIN"/><categoryandroid:name="ent.category.LAUNCHER"/></intent-filter></activity></application></manifest>其中:<uses-permissionandroid:name="android.permission.RECORD_AUDIO"/>表明進行音頻錄制的用戶權限。實例AudioRecord中AudioRecordDemo.java的代碼如下:packageroduction.audiorecord;importjava.io.File;importjava.io.IOException;importandroid.Manifest;importandroid.app.Activity;importandroid.content.pm.PackageManager;importandroid.media.MediaRecorder;importandroid.os.Bundle;importandroid.os.Environment;importandroid.util.Log;importandroid.view.View;importandroid.view.View.OnClickListener;importandroid.widget.ImageButton;importandroid.widget.TextView;importandroid.widget.Toast;importandroidx.core.app.ActivityCompat;publicclassAudioRecordDemoextendsActivityimplementsOnClickListener{/**Calledwhentheactivityisfirstcreated.*/ privateImageButtonst,stop; privateTextViewsttext; privateMediaRecordermRecorder; privateFilerecordPath; privateFilerecordFile;intREQUEST_RECORD_AUDIO_PERMISSION=100;@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);recordPath=newFile("/storage/emulated/0/Recordings/");st=(ImageButton)findViewById(R.id.st);stop=(ImageButton)findViewById(R.id.stop);sttext=(TextView)findViewById(R.id.sttext);st.setOnClickListener(this);stop.setOnClickListener(this);}publicvoidstart(){try{ recordFile=File.createTempFile(String.valueOf("myrecord_"),".amr",recordPath);}catch(IOExceptione){Log.d("audioRecorder","創(chuàng)建臨時文件失敗");}

mRecorder=newMediaRecorder(this)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論