【Android基础】多媒体编程部分总结

一、MediaPlayer的使用

1)如何获得MediaPlayer实例:

可以使用直接new的方式:

MediaPlayer mp = new MediaPlayer();

也可以使用create的方式,如:

MediaPlayer mp = MediaPlayer.create(this, R.raw.test);//这时就不用调用setDataSource了

2) 如何设置要播放的文件:

MediaPlayer要播放的文件主要包括3个来源:

a. 用户在应用中事先自带的resource资源

例如:MediaPlayer.create(this, R.raw.test);

b. 存储在SD卡或其他文件路径下的媒体文件

例如:mp.setDataSource("/sdcard/test.mp3");

c. 网络上的媒体文件

例如:mp.setDataSource("http://www.citynorth.cn/music/confucius.mp3");

MediaPlayer的setDataSource一共四个方法:

setDataSource (String path)

setDataSource (FileDescriptor fd)

setDataSource (Context context, Uri uri)

setDataSource (FileDescriptor fd, long offset, long length)

其中使用FileDescriptor时,需要将文件放到与res文件夹平级的assets文件夹里,然后使用:

AssetFileDescriptor fileDescriptor = getAssets().openFd("rain.mp3");

m_mediaPlayer.setDataSource(fileDescriptor.getFileDescriptor(),fileDescriptor.getStartOffset(), fileDescriptor.getLength());

来设置datasource

3)对播放器的主要控制方法:

Android通过控制播放器的状态的方式来控制媒体文件的播放,其中:

prepare()和prepareAsync() 提供了同步和异步两种方式设置播放器进入prepare状态,需要注意的是,如果MediaPlayer实例是由create方法创建的,那么第一次启动播放前不需要再调用prepare()了,因为create方法里已经调用过了。

start()是真正启动文件播放的方法,

pause()和stop()比较简单,起到暂停和停止播放的作用,

seekTo()是定位方法,可以让播放器从指定的位置开始播放,需要注意的是该方法是个异步方法,也就是说该方法返回时并不意味着定位完成,尤其是播放的网络文件,真正定位完成时会触发OnSeekComplete.onSeekComplete(),如果需要是可以调用setOnSeekCompleteListener(OnSeekCompleteListener)设置监听器来处理的。

release()可以释放播放器占用的资源,一旦确定不再使用播放器时应当尽早调用它释放资源。

reset()可以使播放器从Error状态中恢复过来,重新会到Idle状态。

4)设置播放器的监听器:

MediaPlayer提供了一些设置不同监听器的方法来更好地对播放器的工作状态进行监听,以期及时处理各种情况,

如: setOnCompletionListener(MediaPlayer.OnCompletionListener listener)、

setOnErrorListener(MediaPlayer.OnErrorListener listener)等,设置播放器时需要考虑到播放器可能出现的情况设置好监听和处理逻辑,以保持播放器的健壮性。

二、Android中的soundpool小结

可以用soundpool,用soundpool可以播一些短的反应速度要求高的声音,

比如游戏中的爆破声,而mediaplayer适合播放长点的。

1. SoundPool载入音乐文件使用了独立的线程,不会阻塞UI主线程的操作。但是这里如果音效文件过大没有载入完成,我们调用play方法时可能产生严重的后果,这里Android SDK提供了一个SoundPool.OnLoadCompleteListener类来帮助我们了解媒体文件是否载入完成,我们重载 onLoadComplete(SoundPool soundPool, int sampleId, int status) 方法即可获得。

2. 从上面的onLoadComplete方法可以看出该类有很多参数,比如类似id,是的SoundPool在load时可以处理多个媒体一次初始化并放入内存中,这里效率比MediaPlayer高了很多。

3. SoundPool类支持同时播放多个音效,这对于游戏来说是十分必要的,而MediaPlayer类是同步执行的只能一个文件一个文件的播放。

使用方法:

1. 创建一个SoundPool

  public SoundPool(int maxStream, int streamType, int srcQuality)

  maxStream —— 同时播放的流的最大数量

  streamType —— 流的类型,一般为STREAM_MUSIC(具体在AudioManager类中列出)

  srcQuality —— 采样率转化质量,当前无效果,使用0作为默认值

  eg.

  SoundPool soundPool = new SoundPool(3, AudioManager.STREAM_MUSIC, 0);

  创建了一个最多支持3个流同时播放的,类型标记为音乐的SoundPool。

2 一般把多个声音放到HashMap中去,比如

soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100);

soundPoolMap = new HashMap<Integer, Integer>();

soundPoolMap.put(1, soundPool.load(this, R.raw.dingdong, 1));

soundpool的加载:

int  load(Context context, int resId, int priority)  //从APK资源载入

int  load(FileDescriptor fd, long offset, long length, int priority)  //从FileDescriptor对象载入

int  load(AssetFileDescriptor afd, int priority)  //从Asset对象载入

int  load(String path, int priority)  //从完整文件路径名载入

最后一个参数为优先级。

3 播放

play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate) ,其中leftVolume和rightVolume表示左右音量,priority表示优先级,loop表示循环次数,rate表示速率,如

//速率最低0.5最高为2,1代表正常速度

sp.play(soundId, 1, 1, 0, 0, 1);

而停止则可以使用 pause(int streamID) 方法,这里的streamID和soundID均在构造SoundPool类的第一个参数中指明了总数量,而id从0开始。

三、Android三种播放视频的方式

1、使用其自带的播放器。指定Action为ACTION_VIEW,Data为Uri,Type为其MIME类型。

2、使用VideoView来播放。在布局文件中使用VideoView结合MediaController来实现对其控制。

3、使用MediaPlayer类和SurfaceView来实现,这种方式很灵活。

1、调用其自带的播放器

<span style="font-size:18px;">Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath()+"/Test_Movie.m4v");
//调用系统自带的播放器
    Intent intent = new Intent(Intent.ACTION_VIEW);
    Log.v("URI:::::::::", uri.toString());
    intent.setDataAndType(uri, "video/mp4");
    startActivity(intent);</span>

2、使用VideoView来实现:

<span style="font-size:18px;">Uri uri = Uri.parse(Environment.getExternalStorageDirectory().getPath()+"/Test_Movie.m4v");
VideoView videoView = (VideoView)this.findViewById(R.id.video_view);
videoView.setMediaController(new MediaController(this));
videoView.setVideoURI(uri);
videoView.start();
videoView.requestFocus();
</span>

3、使用MediaPlayer:

<span style="font-size:18px;">public class VideoSurfaceDemo extends Activity implements OnCompletionListener,OnErrorListener,OnInfoListener,
    OnPreparedListener, OnSeekCompleteListener,OnVideoSizeChangedListener,SurfaceHolder.Callback{
    private Display currDisplay;
    private SurfaceView surfaceView;
    private SurfaceHolder holder;
    private MediaPlayer player;
    private int vWidth,vHeight;
    //private boolean readyToPlay = false; 

    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.video_surface); 

        surfaceView = (SurfaceView)this.findViewById(R.id.video_surface);
        //给SurfaceView添加CallBack监听
        holder = surfaceView.getHolder();
        holder.addCallback(this);
        //为了可以播放视频或者使用Camera预览,我们需要指定其Buffer类型
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 

        //下面开始实例化MediaPlayer对象
        player = new MediaPlayer();
        player.setOnCompletionListener(this);
        player.setOnErrorListener(this);
        player.setOnInfoListener(this);
        player.setOnPreparedListener(this);
        player.setOnSeekCompleteListener(this);
        player.setOnVideoSizeChangedListener(this);
        Log.v("Begin:::", "surfaceDestroyed called");
        //然后指定需要播放文件的路径,初始化MediaPlayer
        String dataPath = Environment.getExternalStorageDirectory().getPath()+"/Test_Movie.m4v";
        try {
            player.setDataSource(dataPath);
            Log.v("Next:::", "surfaceDestroyed called");
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //然后,我们取得当前Display对象
        currDisplay = this.getWindowManager().getDefaultDisplay();
    } 

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
        // 当Surface尺寸等参数改变时触发
        Log.v("Surface Change:::", "surfaceChanged called");
    }
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // 当SurfaceView中的Surface被创建的时候被调用
        //在这里我们指定MediaPlayer在当前的Surface中进行播放
        player.setDisplay(holder);
        //在指定了MediaPlayer播放的容器后,我们就可以使用prepare或者prepareAsync来准备播放了
        player.prepareAsync(); 

    }
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) { 

        Log.v("Surface Destory:::", "surfaceDestroyed called");
    }
    @Override
    public void onVideoSizeChanged(MediaPlayer arg0, int arg1, int arg2) {
        // 当video大小改变时触发
        //这个方法在设置player的source后至少触发一次
        Log.v("Video Size Change", "onVideoSizeChanged called"); 

    }
    @Override
    public void onSeekComplete(MediaPlayer arg0) {
        // seek操作完成时触发
        Log.v("Seek Completion", "onSeekComplete called"); 

    }
    @Override
    public void onPrepared(MediaPlayer player) {
        // 当prepare完成后,该方法触发,在这里我们播放视频 

        //首先取得video的宽和高
        vWidth = player.getVideoWidth();
        vHeight = player.getVideoHeight(); 

        if(vWidth > currDisplay.getWidth() || vHeight > currDisplay.getHeight()){
            //如果video的宽或者高超出了当前屏幕的大小,则要进行缩放
            float wRatio = (float)vWidth/(float)currDisplay.getWidth();
            float hRatio = (float)vHeight/(float)currDisplay.getHeight(); 

            //选择大的一个进行缩放
            float ratio = Math.max(wRatio, hRatio); 

            vWidth = (int)Math.ceil((float)vWidth/ratio);
            vHeight = (int)Math.ceil((float)vHeight/ratio); 

            //设置surfaceView的布局参数
            surfaceView.setLayoutParams(new LinearLayout.LayoutParams(vWidth, vHeight)); 

            //然后开始播放视频 

            player.start();
        }
    }
    @Override
    public boolean onInfo(MediaPlayer player, int whatInfo, int extra) {
        // 当一些特定信息出现或者警告时触发
        switch(whatInfo){
        case MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING:
            break;
        case MediaPlayer.MEDIA_INFO_METADATA_UPDATE:
            break;
        case MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING:
            break;
        case MediaPlayer.MEDIA_INFO_NOT_SEEKABLE:
            break;
        }
        return false;
    }
    @Override
    public boolean onError(MediaPlayer player, int whatError, int extra) {
        Log.v("Play Error:::", "onError called");
        switch (whatError) {
        case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
            Log.v("Play Error:::", "MEDIA_ERROR_SERVER_DIED");
            break;
        case MediaPlayer.MEDIA_ERROR_UNKNOWN:
            Log.v("Play Error:::", "MEDIA_ERROR_UNKNOWN");
            break;
        default:
            break;
        }
        return false;
    }
    @Override
    public void onCompletion(MediaPlayer player) {
        // 当MediaPlayer播放完成后触发
        Log.v("Play Over:::", "onComletion called");
        this.finish();
    }
}</span>
时间: 2024-10-13 14:04:02

【Android基础】多媒体编程部分总结的相关文章

Android的多媒体编程

多媒体编程 1.什么是多媒体? 多种媒体的综合. 图片.音乐.视频等: ##图片的常见格式: 1.bmp:以高质量保存所有类型的图片,并将其应用于计算机: 255 KB,255*340像素,24位深度 计算机表示图形的时候时候是使用像素点来表示的,每个像素点都有一个颜色,每个颜色都是使用6位16进制的数值来表示的,一个像素点使用24个bit表示. 图像大小的计算公式:分辨率的宽*高*位深度 + 头文件占用的数据大小=图形实际大小 ,颜色不会失真,图片的体积比较大. 2.jpg:36.4 KB,2

Android基础知识:Day09 多媒体编程

Day09 多媒体编程 一.对话框 1. 确定取消对话框 创建对话框构建器对象,类似工厂模式 AlertDialog.Builder builder = new Builder(this); 设置标题和正文 builder.setTitle("警告"); builder.setMessage("若练此功,必先自宫"); 设置确定和取消按钮 builder.setPositiveButton("现在自宫", new OnClickListener(

android基础(五)网络编程

android 的网络编程一般可以分为两种:基于Socket的,基于Http的. 一.socket与Http socket封装了TCP/IP协议,TPC/IP协议是传输层协议,主要解决数据如何在网络中传输.socket通信方式是当服务器端与客户端建立起了socket连接后,服务器端可以直接将数据传输到客户端.(建立socket连接:建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket .套接字之间的连接过

2015年最新Android基础入门教程目录(完结版)

2015年最新Android基础入门教程目录(完结版) 标签(空格分隔): Android基础入门教程 前言: 关于<2015年最新Android基础入门教程目录>终于在今天落下了帷幕,全套教程 共148节已编写完毕,附上目录,关于教程的由来,笔者的情况和自学心得,资源分享 以及一些疑问等可戳:<2015最新Android基础入门教程>完结散花~ 下面是本系列教程的完整目录: 第一章:环境搭建与开发相关(已完结 10/10) Android基础入门教程--1.1 背景相关与系统架构

《2015最新Android基础入门教程》完结散花~

<2015最新Android基础入门教程>完结散花~ 标签(空格分隔): 反思小结 引言: 从六月底就开始编写这套教程,历时将近五个多月,今天终于写完了,全套教程正文部分148篇, 十大章,从基本UI控件到四大组件,Intent,Fragment,事件处理,数据存储,网络编程,绘图与动画, 多媒体,系统服务等都进行了详细的讲解!代码都是都是在Android Studio上进行编写的,全文 采用Markdown,行文结构清晰,还结合了实际开发中一些常见的问题进行了剖析-由于个人能力的局限, 虽然

2015年最新Android基础入门教程目录(临时版)

2015年最新Android基础入门教程目录(临时版) 标签(空格分隔): Android基础入门教程 前言: 嗯,昨晚又给人盗号了,博客上被发表了十几篇黄贴-然后目录给管理误删了,再发一次 后来协商后发现实被设密保问题了,建议各位用csdn的朋友密保自己设置一波~ 密保问题已修改回来了,应该不会再被盗号了-人怕出名猪怕壮哈~下次如果发现博客被封 告知下小猪,如何很急的话可以先到w3c鸟巢菜鸟教程上看Android基础入门教程 经过站长FK进行排版的,可能阅读体验会比csdn好很多!内容基本是同

Android基础-10

Android基础-10 多媒体编程 图片.音乐.视频等: 多媒体:多种综合: 01_计算机表示图形的形式 .jpg 36.4 KB 255*340像素,位深度24. jpg这种工业图形的压缩算法,类似rar,把人言无法识别的颜色值压缩掉了,会使用相邻空间内的颜色表示同一种颜色.文件体积变小,失真. .png 203 KB 255*340像素,位深度32. png这种工业图形的压缩算法,使用类似map的数据结构来存储图形的数据.图片体积变小,不会失真. .bmp 255 KB 255*340像素

Android基础入门教程——4.2.3 Service精通

Android基础入门教程--4.2.3 Service精通 标签(空格分隔): Android基础入门教程 本节引言: 本节,我们继续来研究Service(服务)组件,本节将会学习下Android中的AIDL跨进程通信的一些 概念,并不深入到源码层次,暂时知道是什么,会用即可!开始本节内容~ 本节对应官方文档:Binder 1.Binder机制初涉 1)IBinder和Binder是什么鬼? 我们来看看官方文档怎么说: 中文翻译: IBinder是远程对象的基本接口,是饿了高性能而设计的轻量级

Android基础入门教程——1.1 背景相关与系统架构分析

Android基础入门教程--1.1 背景相关与系统架构分析 1.Android背景与当前的状况 Android系统是由Andy Rubin创建的,后来被Google收购了:最早的版本是:Android 1.1版本 而现在最新的版本是今年5.28,Google I/O大会上推出的Android M,有趣的是Android系统的命名都是以点心来命名的,下述表是15个Android版本名称,对应API号以及发布时间! 系统版本名称 API版本号 发布时间 Android 1.5:Cupcake:纸杯

Android基础知识(6)—数据持久化之数据存储

阅读前,请浏览此处上方目录. Android基础知识(6)-数据持久化之数据存储 本章内容为个人笔记,参考书籍有:<疯狂的android>第3版.<第一行代码> 首先,我们要知道什么是数据持久化. 数据持久化就是指那些内存中的瞬时数据保存到存储设备中,保证即使手机在关机的情况下,这些数据不会丢失.保存在内存中的数据是处于瞬时状态,保存在存储设备中的数据是处于持久状态.持久化技术则是提供了一种机制可以让数据在瞬时状态和持久状态之间进行转换. Android系统主要提供了三种方式用于简