美文网首页android 集结号Android音视频android之路
Android音视频录制与播放功能简述

Android音视频录制与播放功能简述

作者: 闲庭 | 来源:发表于2017-05-05 17:23 被阅读2025次

    安卓平台和声音录制与播放相关的主要是4个类:MediaRecorderMediaPlayerSoundPool,AudioRecordAudioTrack

    1. MediaRecorder可以录制视频和音频到文件
    2. MediaPlayer可以播放视频和音频文件
    3. SoundPool用于播放比较短的音频片段
    4. AudioRecord可以提供接口读取音频流数据(byte数组或者short数组)
    5. AudioTrack提供接口用于播放音频流数据。

    其中MediaRecorder和AudioRecord用于声音录制,SoundPool、MediaPlayer和AudioTrack用于声音播放。AudioRecord和AudioTrack用于操作音频流数据,操作对象是byte数组(或者short数组),而MediaRecorder和MediaPlayer提供了经过更高层抽象和封装接口,直接对文件进行操作,而且他俩功能更丰富,同时支持音频和视频。

    一、MediaRecorder

    Paste_Image.png
    MediaRecorder的状态简述:

    Initial:初始化。也就是MediaRecorder 刚被创建的时候。在这个时候我们去设置音频或者视频的来源了,可能这个时候就有人问了 音频或者视频的来源是什么意思,举个例子吧,比如当我们在录音的时候,这个声音的来源就可以设置成手机的麦克风。
    Initialized:初始化完成。这里我们已经知道音频或者视频的来源了,在这里我们就可以设置一些输出的属性了,比如输出文件的保存格式,编码格式等。
    DataSourceConfigured:数据源配置改变。也就是我们改变了一些输出的属性,就会进入到这个状态。
    Prepered:处于这个状态就说明了我们的配置已经完成了,现在准备去录制了。
    Recordeing:录制中。
    Released:资源被释放了。
    Error:录制的时候发生了错误。

    主要方法:
     setAudioChannels(int numChannels) 设置录制的音频通道数
     setAudioEncoder(int audio_encoder) 设置audio的编码格式
     setAudioEncodingBitRate(int bitRate) 设置录制的音频编码比特率
     setAudioSamplingRate(int samplingRate) 设置录制的音频采样率
     setAudioSource(int audio_source) 设置用于录制的音源
     setAuxiliaryOutputFile(String path) 辅助时间的推移视频文件的路径传递
     setAuxiliaryOutputFile(FileDescriptor fd)在文件描述符传递的辅助时间的推移视频
     setCamera(Camera c) 设置一个recording的摄像头
     setCaptureRate(double fps) 设置视频帧的捕获率
     setMaxDuration(int max_duration_ms) 设置记录会话的最大持续时间(毫秒)
     setMaxFileSize(long max_filesize_bytes) 设置记录会话的最大大小(以字节为单位)
     setOutputFile(FileDescriptor fd) 传递要写入的文件的文件描述符
     setOutputFile(String path) 设置输出文件的路径
     setOutputFormat(int output_format) 设置在录制过程中产生的输出文件的格式
     setPreviewDisplay(Surface sv) 表面设置显示记录媒体(视频)的预览
     setVideoEncoder(int video_encoder) 设置视频编码器,用于录制
     setVideoEncodingBitRate(int bitRate) 设置录制的视频编码比特率
     setVideoFrameRate(int rate) 设置要捕获的视频帧速率
     setVideoSize(int width, int height) 设置要捕获的视频的宽度和高度
     setVideoSource(int video_source) 开始捕捉和编码数据到setOutputFile(指定的文件)
     setLocation(float latitude, float longitude) 设置并存储在输出文件中的地理数据(经度和纬度)
     setProfile(CamcorderProfile profile) 指定CamcorderProfile对象
     setOrientationHint(int degrees)设置输出的视频播放的方向提示
     setOnErrorListener(MediaRecorder.OnErrorListener l)注册一个用于记录录制时出现的错误的监听器
     setOnInfoListener(MediaRecorder.OnInfoListener listener)注册一个用于记录录制时出现的信息事件
     getMaxAmplitude() 获取在前一次调用此方法之后录音中出现的最大振幅
     prepare()准备录制。
     release()释放资源
     reset()将MediaRecorder设为空闲状态
     start()开始录制
     stop()停止录制
    
    MediaRecorder主要配置参数:
    1、视频编码格式MediaRecorder.VideoEncoder
        default,H263,H264,MPEG_4_SP,VP8
    2、音频编码格式MediaRecorder.AudioEncoder
        default,AAC,HE_AAC,AAC_ELD,AMR_NB,AMR_WB,VORBIS
    3、视频资源获取方式MediaRecorder.VideoSource
        default,CAMERA,SURFACE
    4、音频资源获取方式MediaRecorder.AudioSource
        defalut,camcorder,mic,voice_call,voice_communication,voice_downlink,voice_recognition, voice_uplink
    5、资源输出格式MediaRecorder.OutputFormat
        amr_nb,amr_wb,default,mpeg_4,raw_amr,three_gpp,aac_adif, aac_adts, output_format_rtp_avp, output_format_mpeg2ts ,webm
    
    实现录音的一般步骤:
    1、实例化MediaRecorder mr,调用构造方法 
    2、初始化mr:mr.setAudioSource(MIC)/setVideoSource(CAMERA) 
    3、配置DataSource:设置输出文件格式/路径,编码器等 
    4、准备录制:mr.prepare() 
    5、开始录制:mr.start() 
    6、停止录制:mr.stop() 
    7、释放资源:mr.release() 
    注:2,3不可调换顺序 
    添加权限: 
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 
    <uses-permission android:name="android.permission.RECORD_AUDIO"> 
    

    二、MediaPlayer

    Paste_Image.png
    1、当一个MediaPlayer对象被创建或者调用reset()方法之后,它处于空闲状态,调用release()方法后处于结束状态。
    • 一个MediaPlayer对象调用了reset()方法后,再调用其它方法可能会触发OnErrorListener.onError()事件,未调用reset()方法则不会触发。
    • 当Mediaplayer对象不再被使用时,最好调用release()方法对其进行释放,使其处于结束状态,此时它不能被使用
    • Mediaplayer对象被创建时(调用构造方法)处于空闲状态,若使用create()方法创建后则处于准备状态。
    2、 一般情况下,一些常用的播放控制操作可能因为音频、视频的格式不被支持或者质量较差以及流超时,也有可能由于开发者的疏忽使得Mediaplayer对象处于无效状态等而导致错误。此时可通过注册setOnErrorListener方法实现监控。如果发生了错误,Mediaplayer对象将处于多雾状态,可以使用reset()方法来回复错误。
    3、任何Mediaplayer对象都必须先处于准备状态,然后才开始播放
    4、要开始播放Mediaplayer对象都必须成功调用start()方法,可通过isPlaying()方法来检测是否正在播放
    5、当Mediaplayer对象在播放时,可以进行暂停和停止操作,pause()方法暂停播放,stop()方法停止播放。处于暂停暂停时可通过start()方法恢复播放,但是处于停止状态时则必须先调用prepare()方法使其处于准备状态,再调用start()方法。

    主要方法:

    1. 实例化方式
      使用直接new的方式:
      MediaPlayer mp = new MediaPlayer();
      使用create的方式:
      MediaPlayer mp = MediaPlayer.create(this, R.raw.test);
    2. 设置播放源
    setDataSource(String path)//指定装载path路径所代表的文件。
    setDataSource(Context context, Uri uri, Map<String, String headers)//指定装载uri所代表的文件。
    setDataSource(Context context, Uri uri)//指定装载uri所代表的文件。
    setDataSource(FileDescriptor fd, long offset, long length)//指定装载fd所代表的文件中从offset开始长度为length的文件内容。
    setDataSource(FileDescriptor fd)//指定装载fd所代表的文件。
    
    1. 配置播放参数
    setAudioStreamType(int streamtype)//设置音频流的类型。
    setDisplay(SurfaceHolder sh)//设置显示方式。
    setLooping(boolean looping)//设置是否循环播放。
    setNextMediaPlayer(MediaPlayer next)//设置当前流媒体播放完毕,下一个播放的MediaPlayer。
    setScreenOnWhilePlaying(boolean screenOn)//设置是否使用SurfaceHolder来显示。
    setSurface(Surface surface)//设置Surface。
    setVideoScalingMode(int mode)//设置视频缩放的模式。
    setVolume(float leftVolume, float rightVolume)//设置播放器的音量。
    setWakeMode(Context context, int mode)//为MediaPlayer设置低级电源管理行为。
    
    1. 播放控制函数
    start()//开始或恢复播放。
    stop()//停止播放。
    pause()//暂停播放。
    prepare()//准备播放(装载音频),调用此方法会使MediaPlayer进入Prepared状态。
    prepareAsync()//准备播放异步音频。
    release()//释放媒体资源
    reset()//重置MediaPlayer进入未初始化状态。
    seekTo(int msec)//指定的时间位置。
    
    1. 监听事件函数
    setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener listener)//注册一个回调函数,在网络视频流缓冲变化时调用。
    setOnCompletionListener(MediaPlayer.OnCompletionListener listener)//为Media Player的播放完成事件绑定事件监听器。
    setOnErrorListener(MediaPlayer.OnErrorListener listener)//为MediaPlayer的播放错误事件绑定事件监听器。
    setOnPreparedListener(MediaPlayer.OnPreparedListener listener)//当MediaPlayer调用prepare()方法时触发该监听器。
    setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener listener)//当MediaPlayer调用seek()方法时触发该监听器。
    setOnVideoSizeChangedListener(MediaPlayer.OnVideoSizeChangedListener listener)//注册一个用于监听视频大小改变的监听器。
    
    1. 获取参数函数
    getCurrentPosition()//获取当前播放的位置。
    getDuration()//获取音频的时长。
    getVideoHeight()//获取视频的高度。
    getVideoWidth()//获取视频的宽度。
    isLooping()//判断MediaPlayer是否正在循环播放。
    isPlaying()//判断MediaPlayer是否正在播放。
    

    三、AudioRecord

    1. AudioRecord 的工作流程
    (1) 配置参数,初始化内部的音频缓冲区
    (2) 开始采集
    (3) 需要一个线程,不断地从 AudioRecord 的缓冲区将音频数据“读”出来,注意,这个过程一定要及时,否则就会出现“overrun”的错误,该错误在音频开发中比较常见,意味着应用层没有及时地“取走”音频数据,导致内部的音频缓冲区溢出。
    (4) 停止采集,释放资源
    
    1. AudioRecord 的参数配置
    • audioSource
      该参数指的是音频采集的输入源,可选的值以常量的形式定义在 MediaRecorder.AudioSource 类中,常用的值包括:DEFAULT(默认),VOICE_RECOGNITION(用于语音识别,等同于DEFAULT),MIC(由手机麦克风输入),VOICE_COMMUNICATION(用于VoIP应用)等等。
    • sampleRateInHz
      采样率,注意,目前44100Hz是唯一可以保证兼容所有Android手机的采样率。
    • channelConfig
      通道数的配置,可选的值以常量的形式定义在 AudioFormat 类中,常用的是 CHANNEL_IN_MONO(单通道),CHANNEL_IN_STEREO(双通道)。
    • audioFormat
      这个参数是用来配置“数据位宽”的,可选的值也是以常量的形式定义在 AudioFormat 类中,常用的是 ENCODING_PCM_16BIT(16bit),ENCODING_PCM_8BIT(8bit),注意,前者是可以保证兼容所有Android手机的。

    四、AudioTrack

    1. ** AudioTrack 的工作流程**
    (1) 配置参数,初始化内部的音频播放缓冲区
    (2) 开始播放
    (3) 需要一个线程,不断地向 AudioTrack 的缓冲区“写入”音频数据,注意,这个过程一定要及时,否则就会出现“underrun”的错误,该错误在音频开发中比较常见,意味着应用层没有及时地“送入”音频数据,导致内部的音频播放缓冲区为空。
    (4) 停止播放,释放资源
    
    1. ** AudioTrack 的参数配置**
    • streamType
      这个参数代表着当前应用使用的哪一种音频管理策略,当系统有多个进程需要播放音频时,这个管理策略会决定最终的展现效果,该参数的可选的值以常量的形式定义在 AudioManager 类中,主要包括:
    STREAM_VOCIE_CALL:电话声音
    STREAM_SYSTEM:系统声音
    STREAM_RING:铃声
    STREAM_MUSCI:音乐声
    STREAM_ALARM:警告声
    STREAM_NOTIFICATION:通知声
    
    • sampleRateInHz
      采样率,从AudioTrack源码的“audioParamCheck”函数可以看到,这个采样率的取值范围必须在 4000Hz~192000Hz 之间。
    • mode
      AudioTrack 提供了两种播放模式,一种是 static 方式,一种是 streaming 方式,前者需要一次性将所有的数据都写入播放缓冲区,简单高效,通常用于播放铃声、系统提醒的音频片段; 后者则是按照一定的时间间隔不间断地写入音频数据,理论上它可用于任何音频播放的场景。
      可选的值以常量的形式定义在 AudioTrack 类中,一个是 MODE_STATIC,另一个是 MODE_STREAM,根据具体的应用传入对应的值即可。

    五、SoundPool

    soundlPool 用于播放比较短的音频片段,比如游戏声音、按键声、铃声片段等等,它可以同时播放多个音频。

    主要方法:

    1. 构造实例
      SoundPool(int maxStreams, int streamType, int srcQuality) 参数依次是:
      ①指定支持多少个声音,SoundPool对象中允许同时存在的最大流的数量,该值太大就会报错AudioFlinger could not create track, status: -12 ,就听不到声音
      ②指定声音类型,流类型可以分为STREAM_VOICE_CALL, STREAM_SYSTEM, STREAM_RING,STREAM_MUSIC 和STREAM_ALARM四种类型。在AudioManager中定义。
      ③指定声音品质(采样率变换质量),一般直接设置为0!
        在低版本中可以用上述构造方法,而API 21(Android 5.0)后这个构造方法就过时了! 而用到一个SoundPool.Builder的东东,我们要实例化SoundPool只需调用:
    SoundPool.Builder spb = new SoundPool.Builder();
    spb.setMaxStreams(10);
    spb.setAudioAttributes(null);    //转换音频格式
    SoundPool sp = spb.build();      //创建SoundPool对象
    
    1. 加载声音资源文件
    load(Context context, int resId, int priority) //从APK资源载入
    load(String path, int priority)
    load(FileDescriptor fd, long offset, long length, int priority)
    load(AssetFileDescriptor afd, int priority)
    

    参数介绍

    context:上下文
    resId:资源id,如从raw文件获取填写R.raw.xxx
    priority:没什么用的一个参数,建议设置为1,保持和未来的兼容性
    path:文件路径,文件的绝对路线,如存放在sd卡中的音频
    FileDescriptor:文件描述符
    AssetFileDescriptor:从asset目录读取某个资源文件,context.getAssets().openFd("xxx"),xxx表示文件名
    

    上述方法都会返回一个声音的ID,Integer类型,我们可以通过建立一个Map<Integer,Integer> 来存储和获取声音方法如下,

    Map<Integer,Integer> map=new HashMap<Integer, Integer>();
    map.put(1,soundPool.load(context.getAssets().openFd("FadeOut.ogg"),1));
    
    1. 播放音频文件
      play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate),其返回值为一个int类型的数字
      参数依次是:
    soundID:Load()返回的声音ID号,以上可以通过map.get(1)获取
    leftVolume:左声道音量设置  一般为0-1,默认填1
    rightVolume:右声道音量设置 一般为0-1,默认填1
    priority:指定播放声音的优先级,数值越高,优先级越大。默认填0
    loop:指定是否循环:-1表示无限循环,0表示不循环,其他值表示要重复播放的次数
    rate:指定播放速率:1.0的播放率可以使声音按照其原始频率,而2.0的播放速率,可以使声音按照其 原始频率的两倍播放。如果为0.5的播放率,则播放速率是原始频率的一半。播放速率的取值范围是0.5至2.0。
    

    如果SoundPool刚调完加载load函数之后,直接调用SoundPool的play函数可能出现error "sample 1 not READY",所以建议,调用加载资源函数load之后,实现资源加载结束的监听函数,在这个监听到资源加载结束之后,播放音频文件。

    soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
                @Override
                public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
                    soundPool.play(map.get(1),1,1,0,0,1);
                }
            });
    
    1. 去除音频或者停止播放重置资源
    soundPool.pause(int streamID)  暂停指定播放流的音效
    streamID:应通过play()返回
    soundPool.resume(int streamID)  继续播放指定播放流的音效
    streamID:应通过play()返回
    soundPool.stop(int streamID) 终止指定播放流的音效
    streamID:应通过play()返回
    soundPool.unload(int soundID) 卸载一个指定的音频资源.
    soundID:Load()返回的声音ID号,以上可以通过map.get(1)获取
     soundPool.release(); 释放SoundPool中的所有音频资源.
    

    注意:

    1. play()函数传递的是一个load()返回的soundID——指向一个被记载的音频资源 ,如果播放成功则返回一个非0的streamID——指向一个成功播放的流 ;同一个soundID 可以通过多次调用play()而获得多个不同的streamID (只要不超出同时播放的最大数量);
    2. pause()、resume()和stop()是针对播放流操作的,传递的是play()返回的streamID ;
    3. play()中的priority参数,只在同时播放的流的数量超过了预先设定的最大数量是起作用,管理器将自动终止优先级低的播放流。如果存在多个同样优先级的流,再进一步根据其创建事件来处理,新创建的流的年龄是最小的,将被终止;
    4. 无论如何,程序退出时,手动终止播放并释放资源是必要的。
    5. 如果你音效多,也不要指望unload方法来清除掉一些音效后再load新的进去,虽然unload后音效卸载了,但是前面分给它在SoundPool里面的Id可没有释放掉,也就是说这个时候你load新的进去只会在后面继续累加,然后累加多了就超过256了,然后就就听不到声音,然后就没有然后了。要想彻底清掉前面的音效请使用release方法,它会连内存中占用的资源一起释放掉。
    6. 其他还有点什么呢,load需要一点点时间,load后不要马上unload,load ---play--unload的做法并不可取,不要load太大的音效,它只会申请1M的内存空间。SoundPool出错后通常会看到return的值是0。

    五、MediaRecorder 和 AudioRecord的选择

    Android SDK 提供了两套音频采集的API,分别是:MediaRecorder 和 AudioRecord,前者是一个更加上层一点的API,它可以直接把手机麦克风录入的音频数据进行编码压缩(如AMR、MP3等)并存成文件,而后者则更接近底层,能够更加自由灵活地控制,可以得到原始的一帧帧PCM音频数据。

    如果想简单地做一个录音机,录制成音频文件,则推荐使用 MediaRecorder,而如果需要对音频做进一步的算法处理、或者采用第三方的编码库进行压缩、以及网络传输等应用,则建议使用 AudioRecord,其实 MediaRecorder 底层也是调用了 AudioRecord 与 Android Framework 层的 AudioFlinger 进行交互的。

    音频的开发,更广泛地应用不仅仅局限于本地录音,因此,我们需要重点掌握如何利用更加底层的 AudioRecord API 来采集音频数据(注意,使用它采集到的音频数据是原始的PCM格式,想压缩为mp3,aac等格式的话,还需要专门调用编码器进行编码)。

    六、MediaPlayer,SoundPool和AudioTrack的选择

    MediaPlayer 更加适合在后台长时间播放本地音乐文件或者在线的流式资源;
    SoundPool 则适合播放比较短的音频片段,比如游戏声音、按键声、铃声片段等等,它可以同时播放多个音频;
    而 AudioTrack 则更接近底层,提供了非常强大的控制能力,支持低延迟播放,适合流媒体和VoIP语音电话等场景。

    七、播放视频 VideoView

    主要方法:

    getBufferPercentage:得到缓冲的百分比 
    getCurrentPosition:得到当前播放位置 
    getDuration:得到视频文件的时间 
    resolveAdjustedSize:调整视频显示大小 
    setMediaController:设置播放控制器模式(播放进度条) 
    setOnCompletionListener:当视频文件播放完时触发事件 
    setVideoPath:设置视频源路径 
    setVideoURI:设置视频源地址 
    

    八、相机Camera

    Camera回调事件
    1. android.hardware.Camera.AutoFocusCallback
      当自动对焦时候调用,该接口具有一个void onAutoFocus(boolean success,Camera camera)函数;
    2. android.hardware.Camera.ErrorCallback
      摄像头出错的时候调用,这个接口具有一个void onError(int error,Camera camera)函数;前者表示数据类型,取值是Camera类中的常量CAMERA_ERROR_UNKNOWN或者是 CAMERA_ERROR_SERVICE_DIED;
      前者是不明错误,后者是表示服务已经关闭,在这种情况下需要释放当前的Camera对象,然后再初 始化一个。
    3. android.hardware.camera.PreviewCallback
      在图像预览时调用,这个接口有一个void onPreviewFrame(byte[] data,Camera camera);参数data为每帧图像的数据流。我们可以根据实际需要来实现这个接口。
    4. android.hardware.Camera.ShutterCallback
      在图像预览的时候调用,这个接口具有一个void onShutter();
      可以在改函数中通知用户快门已经关闭,例如播放一个声音。
    5. android.hardware.Camera.PictureCallback
      当拍摄相片的时候调用,该接口具有一个void onPictureTaken(byte[] data,Camera camera)函数;参数和预览的一样。在android中主要有三个类实现了这个接口,分别是PostViewPictureCallback、 RawPictureCallback、JepgPictureCallback。我们可以根据需要定义自己需要的类。
    6. 还提供了放大缩小的监听器android.hardware.Camera.OnZoomChangeListener
    private final class ZoomListener implements android.hardware.Camera.OnZoomChangeListener {
    public void onZoomChange(int value, boolean stopped, android.hardware.Camera camera) ;
    
    Camera.Parameters 相机的属性参数

    通过Camera.open(int cameraId)启动相机服务,然后通过Camera对象的getParameters()函数来得到一个android.hardware.Camera.Parameters 对象,Parameters提供了一些接口来设置Camera的属性:

    1. setPictureFormat(int pixel_format)
      设置图片的格式,其取值为ImageFormat.JPEG、ImageFormat.RGB_565或者ImageFormat.FLEX_RGB_888等格式。
    2. setPreviewFormat(int pixel_format)
      设置图片的预览格式,取值如上。
    3. setPictureSize(int width,int height)
      设置图片的高度和宽度,单位为像素。
    4. setPreviewSize(int width,int height)
      设置预览的高度和宽度,取值如上。
    5. setPreviewFrameRate(int fps)
      设置图片预览的帧速。
    6. setFocusMode(String value)
      设置聚焦模式,如Camera.Parameters.FOCUS_MODE_AUTO。
    Camera类的方法

    在设置好Camera的参数后,通过以下方法可执行相应操作。

    1. camera.startPreview()
      开始预览图像。
    2. camera.autoFocus(AutoFocusCallback cb)
      自动对焦。
    3. camera.takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg)
      执行拍照。
      注:takePicture方法要实现3个回调函数作为它的三个参数:Camera.ShutterCallback(快门回调接口),和两个Camera.Picture.Callback(原生图像数据接口和压缩格式图片数据接口)。
      需要许可
      <uses-permission android:name="android.permission.CAMERA" />
      若要将图片存储至sd卡中,则需要sd卡读写许可
    4. camera.stopPreview()
      停止预览 。
    5. camera.release()
      释放相机服务 。

    九、闹钟设置AlarmManager

    相关类:AlarmManager,它是专门用来设定在某个指定的时间去完成指定的事件。AlarmManager提供了访问系统警报的服务,只要在程序中设置了警报服务,AlarmManager就会通过onReceive()方法去执行这些事件,就算系统处于待机状态,同样不会影响运行。可通过Context.getSystemService(ALARM_SERVICE)方法来获得该服务。 
     方法说明: 
    cancel:    取消AlarmManager服务 
    set:    设置AlarmManager服务 
    setInexactRepeating:设置不精确周期 
    setRepeating:设置精确周期 
    setTimeZone:设置时区 
     注:需创建一个BroadcastReceiver的子类,并覆盖onReceive()方法 
     铃声设置 
     系统自带的铃声都放在/system/medio/audio/文件夹中 
     铃音类型: TYPE_RINGTONE(来电铃音),TYPE_ALARM,TYPE_NOTIFICATION 
    相关类:RingtoneManager 
    方法介绍: 
    getActualDefaultRingtoneUri:取得指定类型的铃声 
    getCursor:返回所有可用铃声的游标 
    getDefaultType:得到指定URI默认的铃声类型 
    getRingtone 
     getRingtonePosition:得到铃声位置 
    getRingtoneUri 
     getValidRingtoneUri:得到一个可用铃声的URI 
     isDefault:得到指定的Uri是否为默认的铃声 
    setActualDefaultRingtoneUri:设置默认的铃声 
    
     获取的Cursor共有4列,列名依次为:_id,title,”content://media/internal/audio/media”,title_key 
    

    相关文章

      网友评论

      本文标题:Android音视频录制与播放功能简述

      本文链接:https://www.haomeiwen.com/subject/rotfottx.html