版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第6章
多媒体开发CONTENTS目录02
BroadcastReceiver01
Service03
音
频04
视
频05
综合实例-多媒体播放器Service016.1.1Service的作用在Android系统中,Service不是一个单独的进程,除非特殊设定,否则它不会单独运行在自己的进程中,通常情况下它是作为启动应用程序的一部分与当前应用程序运行在同一个进程中。服务程序Service是一种可以在后台长时间运行并且不提供用户UI的程序。即使启动Service的应用程序被切换掉,其启动的Service也可以在后台正常运行。因此,Service经常被用来处理一些耗时比较长的程序,例如进行网络传输或播放音乐等。6.1.2Service的生命周期Android开发中,当需要创建在后台运行的程序的时候,就要用到Service。Service可以分为有无限生命和有限生命两种。需要特别注意的是,Service跟Activity是不同的。简单来说,可以理解为后台与前台的区别,Activity拥有UI,可以与用户交互,而Service则不能。当系统资源不足时,Activity可能会被系统销毁以释放资源,而Service不会。Service类中定义了一系列和自身生命周期相关的方法,在此不一一介绍,最经常使用的有以下三个方法:onCreate()当Service第一次被创建时,系统调用该方法。onStartCommand(Intentintent,intflags,intstartId)
当通过startService()方法启动Service时,该方法被调用。onDestroy()当Service不再使用时,系统调用该方法。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是设置绑定作业的选项,可以是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会被系统销毁。两种方式对Service生命周期的影响如图6.1所示。由图6.1不难看出,通过bindService()方法启动时和startService()方法一样,都会调用onCreate()方法来创建Service,但它不会调用onStartCommand()方法,而是调用onBind()方法返回客户端一个IBinder接口。这个IBinder就是在Service的生命周期回调方法onBind()中的返回值。服务运行后,与前者不同的是,不是服务终止,而是使用Context.unbindService()方法之后,Service的生命周期回调onUnbind()会被调用。如果所有bind过Service的组件都调用unbindService()方法,那么之后Service会被停止,其onDestroy()回调会被调用。图6.1
两种方式的比较BroadcastReceiver022.2.1JDK的安装
广播(Broadcast)是Android系统中应用程序间通信的手段。当有特定事件发生时,例如有来电、有短信、电池电量变化等事件发生时,Android系统都会产生特定的Intent对象并且自动进行广播,而针对特定事件注册的BroadcastReceiver会接收到这些广播,并获取Intent对象中的数据进行处理。在广播Intent对象时可以指定用户权限,以此限制仅有获得了相应权限的BroadcastReceiver才能接收并处理对应的广播。BroadcastReceiver有动态和静态两种注册方法。动态注册方法即使用Context.registerReceiver()方法进行注册,需要特别注意的是,动态注册方法在退出程序前要使用Context.unregisterReceiver()方法撤销注册。静态注册方法即在AndroidManifest.xml.文件中通过<receiver>标签进行注册。一个BroadcastReceiver对象只有在被调用onReceive(Context,Intent)时才有效,当从该函数返回后,该对象就已无效了,其生命周期结束。下面介绍如何使用动态注册来实现监听电池剩余电量。实例BatteryDemo演示了使用动态注册BroadcastReceiver对象并且接收系统电量改变事件并加以处理的过程,运行效果如图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的具体实现代码如下: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)动态注册receiver。intcurrent=intent.getExtras().getInt("level")获取当前电池的电量。inttotal=intent.getExtras().getInt("scale")获取总电量。unregisterReceiver(receiver)注销receiver注册。该应用程序若要使用静态注册,则需要在AndroidManifest.xml文件中添加如下代码:<receiverandroid:name="receiver"><intent-filter><actionandroid:name="ent.action.BATTERY_CHANGED"/></intent-filter></receiver>音
频03Android系统支持三种不同来源的音频播放:(1)本地资源存储在应用程序中的资源,例如存储在RAW文件夹下的媒体文件,只能被当前应用程序访问。(2)外部资源存储在文件系统中的标准媒体文件,例如存储在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="播放存储在文件系统的音乐"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类实现播放音频的功能,根据MediaPlayer-AudioActivity类通过Intent传递过来的不同的值,而实现三种不同的播放音频的方式。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("正在播放文件系统中的音乐"); 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指向要播放的音频文件的位置。本实例中,文件系统中的资源是放置在内部存储卡中的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; }以上几行代码是动态申请读取存储器上的音频文件的权限。实例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类实现对音频和视频进行录制的功能。MediaRecorder对象在运行过程中存在多种状态,其状态转化如图6.5所示。从图6.5中可以看到:(1)创建MediaRecorder对象后处于Initial状态,MediaRecorder对象会占用硬件资源,因此不再需要时,应该调用release()方法销毁。在其他状态调用reset()方法,可以使得MediaRecorder对象重新回到Initial状态,达到复用MediaRecorder对象的目的。(2)在Initial状态调用setVideoSource()或者setAudioSource()之后,MediaRecorder将进入Initialized状态。对于音频录制,目前OPhone平台支持从麦克风或者电话两个音频源录制数据。在Initialized状态的MediaRecorder还需要设置编码格式、文件数据路径、文件格式等信息,设置之后MediaRecorder进入DataSourceConfigured状态。(3)在DataSourceConfigured状态调用prepare()方法,MediaRecorder对象将进入Prepared状态,录制前的状态准备就绪。(4)在Prepared状态调用start()方法,MediaRecorder进入Recording状态,声音录制可能只需一段时间,这时MediaRecorder一直处于录制状态。(5)在Recording状态调用stop()方法,MediaRecorder将停止录制,并将录制内容输出到指定文件。MediaRecorder定义了两个内部接口OnErrorListener和OnInfoListener来监听录制过程中的错误信息。例如,当录制的时间长度达到了最大限制或者录制文件的大小达到了最大文件限制时,系统会回调已经注册的OnInfoListener接口的onInfo()方法。图6.5
MediaRecorder对象状态转化图使用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);
将录音器置于准备状态。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","创建临时文件失败");}
mRecorder=newMediaRecorder(this)
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025药械培训试题及答案
- 2025年护理核心制度专项测试题及答案
- 质量缺陷智能识别工艺
- 2026年传染病疫情信息报告管理培训考核试题及答案
- 护士职业技能2026年考试试题及答案
- 中级经济分析师考试试卷及答案2026年
- 2026年新版药店培训试题及答案
- 造纸厂主要负责人装卸作业安全操作规程
- 湖南大学钢结构考试选择题(含答案)
- 中外历史纲要(下) 选择性必修1 第15单元 第42讲 第1课时 中国古代官员的选拔与管理
- 完整版八年级物理浮力压强计算题(含答案)
- DB50T 703-2016 电梯无脚手架安装工艺安全操作规范
- 医院获得性肺炎预防与控制
- 消毒供应室专科护士培训汇报
- JJF(浙) 1135-2017 大量程电子数显千分表校准规范
- GD-C3-51939 机房供配电系统检验批质量验收记录
- GB/T 6829-2024剩余电流动作保护电器的一般安全要求
- 雷雨-剧本原文-高中语文雷雨剧本原文
- 初中数学因式分解练习题100题附详解
- 包装可回收评估报告
- 单招考试培训的时间安排和学习计划
评论
0/150
提交评论