`

Android平台下SeeJoPlayer视频播放器(第二部分 源码解析)

 
阅读更多

转载请注明出处:http://www.blogjava.net/zh-weir/archive/2010/01/24/310617.html

    SeeJoPlayer是我利用业余时间开发的一款免费的视频播放器。主要是现在在网上似乎找不到一个Android平台下的界面美观一点的视频播放器。 而作为智能手机操作系统的Android,没有一个像样一点的视频播放器,岂不糗大了。所以,我就写了这么一个砖头并开出源码,希望能引出高手们的美玉来 吧!



 


第二部分:源码解析

    SeeJoPlayer不是一个完美的作品,可以说,它在很多地方都不尽如人意。当然一个完美的作品,也不是我写这款播放器的目的。我只是希望以此为引,结合大家共同的智慧开发出一款真正完美强大的Android平台下的国产视频播放器出来。

    SeeJoPlayer有许多不足之处,例如,它只支持系统默认的视频格式,因为它使用系统默认的解码器。这,一方面是因为如果通过软解码的话,播放视频 的效率会很受影响,另外最主要的原因当然还是个人水平、精力有限,没办法接着往下做了。如果大家觉得这份代码还多少有些参考价值的话,不妨拿去用。只是希 望当你们以此为参考,开发出真正强大的播放器出来的时候,别忘了如果能开放源码的话,一定开放出来。毕竟开源软件就好比能够进化的物种,提供你的DNA出 来,让我们共同的软件变得越来越完美吧!

    好了,废话不说了。播放器的全部源码本文中已经提供了下载地址。下面,我就其中我觉得可能值得关注的地方做一些解释。

    一、VideoView与视频比例缩放:

    以前在论坛上也看到有人问过如何实现视频按比例缩放的问题。的确,如果仅仅使用VideoView可能达不到我们想要达到的效果。这就需要我们对 VideoView做一些改动,简单的说就是另外写一个类似VideoView的类出来(庆幸Android是开源的)。

    我们可以很方便的获得VideoView的源代码,最简单的方法是直接在GoogleCodeSearch 上 找“VideoView.java”。所以重写VideoView的过程其实只是在原来的基础上进行一些修改而已,并非一个很麻烦的工作。为什么 Android自带的VideoView会保持视频的长宽比而不能让我们很方便的自定义比例呢?我猜想可能Google做Android也是一个很仓促的 工程,许多代码并没有考虑得太成熟。

    VideoView的源码中有这样一段代码:

1    @Override
2    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
3        //Log.i("@@@@", "onMeasure");
4        int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
5        int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
6        if (mVideoWidth > 0 && mVideoHeight > 0) {
7            if ( mVideoWidth * height  > width * mVideoHeight ) {
8                //Log.i("@@@", "image too tall, correcting");
9                height = width * mVideoHeight / mVideoWidth;
10            } else if ( mVideoWidth * height  < width * mVideoHeight ) {
11                //Log.i("@@@", "image too wide, correcting");
12                width = height * mVideoWidth / mVideoHeight;
13            } else {
14                //Log.i("@@@", "aspect ratio is correct: " +
15                        //width+"/"+height+"="+
16                        //mVideoWidth+"/"+mVideoHeight);
17            }
18        }
19        //Log.i("@@@@@@@@@@", "setting size: " + width + 'x' + height);
20        setMeasuredDimension(width, height);
21    }
22

    这就是为什么长宽比不能改变的原因了。因为在OnMeasure的时候,就对这个长宽比进行了处理。

    我们把其中处理的代码屏蔽掉,视频大小就可以随着VideoView的长宽改变而改变了。

1    @Override
2    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
3        //Log.i("@@@@", "onMeasure");
4        int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
5        int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
6        /**//*if (mVideoWidth > 0 && mVideoHeight > 0) {
7            if ( mVideoWidth * height  > width * mVideoHeight ) {
8                //Log.i("@@@", "image too tall, correcting");
9                height = width * mVideoHeight / mVideoWidth;
10            } else if ( mVideoWidth * height  < width * mVideoHeight ) {
11                //Log.i("@@@", "image too wide, correcting");
12                width = height * mVideoWidth / mVideoHeight;
13            } else {
14                //Log.i("@@@", "aspect ratio is correct: " +
15                        //width+"/"+height+"="+
16                        //mVideoWidth+"/"+mVideoHeight);
17            }
18        }*/
19        //Log.i("@@@@@@@@@@", "setting size: " + width + 'x' + height);
20        setMeasuredDimension(width,height);
21    }


    二、视频控制菜单与播放界面的层次问题:

    看到过一些别人写的视频播放器,其中有一些朋友老是简简单单的将VideoView和控制界面放在一个LinearLayout中。这样随着控制界面的出 现与否,VideoView会随之改变长宽,给人的体验并不很好。所以,我认为VideoView和控制界面最好不要放在同一个层次上。不要偷懒,使用一 个FrameLayout或者PopupWindow就可以解决这个问题。例如,我就简简单单地使用了PopupWindow,这个具体实现上,就百花争 鸣吧。

    三、视频文件扫描:

    视频文件的扫描,现在想来主要有两种方式:

    第一种就是直接读取媒体库中的视频文件数据库。当Android启动的时候,系统会自动扫描sdcard,并为媒体文件建立(或者更新)数据库。我们可以通过对应的URI来访问数据库,从而得到视频文件的列表:

1    private Uri videoListUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
2
3
4
5    Cursor cursor = getContentResolver().query(videoListUri, new String[]{"_display_name","_data"}, null, null, null);
6        int n = cursor.getCount();
7        cursor.moveToFirst();
8        LinkedList<MovieInfo> playList2 = new LinkedList<MovieInfo>();
9        for(int i = 0 ; i != n ; ++i){
10            MovieInfo mInfo = new MovieInfo();
11            mInfo.displayName = cursor.getString(cursor.getColumnIndex("_display_name"));
12            mInfo.path = cursor.getString(cursor.getColumnIndex("_data"));
13            playList2.add(mInfo);
14            cursor.moveToNext();
15        }  

    这种方法可能是最有效率的了,不过不知为何,媒体库中似乎没有扫描进本身支持的3GP视频格式(也可能我这里是一个特例) 。不过,正是因为这个原因,我才想到有可能需要另外一种最基本的扫描文件系统的方法来扫描视频文件。这就是文件系统的遍历:

1    private void getVideoFile(final LinkedList<MovieInfo> list,File file){
2        
3        file.listFiles(new FileFilter(){
4
5            @Override
6            public boolean accept(File file) {
7                // TODO Auto-generated method stub
8                String name = file.getName();
9                int i = name.indexOf('.');
10                if(i != -1){
11                    name = name.substring(i);
12                    if(name.equalsIgnoreCase(".mp4")||name.equalsIgnoreCase(".3gp")){
13                        
14                        MovieInfo mi = new MovieInfo();
15                        mi.displayName = file.getName();
16                        mi.path = file.getAbsolutePath();
17                        list.add(mi);
18                        return true;
19                    }
20                }else if(file.isDirectory()){
21                    getVideoFile(list, file);
22                }
23                return false;
24            }
25        });
26    }

    当然,随着Android平台下的硬件设备越来越多,越来越强大。我们有理由相信,它以后将不仅仅只支持MP4和3GP格式的视频文件,所以我们必须使用两种方式结合的方法来获得最大的视频集合作为我们的视频列表。

    四、播放过程中进度条progress的设定:

    视频开始播放了,那么一个小麻烦出现了:什么时候设定进度条才更有效率?我这里有一种方法供大家参考,那就是通过Handler自己给自己发消息来达到不断设置进度条的目的。

1    Handler myHandler = new Handler(){
2   
3        @Override
4        public void handleMessage(Message msg) {
5            // TODO Auto-generated method stub
6            
7            switch(msg.what){
8            
9                case PROGRESS_CHANGED:
10                    
11                    int i = vv.getCurrentPosition();
12                    seekBar.setProgress(i);
13                    
14                    i/=1000;
15                    int minute = i/60;
16                    int hour = minute/60;
17                    int second = i%60;
18                    minute %= 60;
19                    playedTextView.setText(String.format("%02d:%02d:%02d", hour,minute,second));
20                    
21                    sendEmptyMessage(PROGRESS_CHANGED);
22                    break;
23

   
    当然,这种方法,需要首先发送一个初始消息来启动。

    五、全屏与非全屏:

    大家都知道,一般一个Activity设置全屏的方法有两种,一是在OnCreate中:

1    @Override   
2    public void onCreate(Bundle icicle) {   
3    super.onCreate(icicle);   
4      
5    requestWindowFeature(Window.FEATURE_NO_TITLE);           
6    Window win = getWindow();   
7    win.setFlags(WindowManager.LayoutParams.NO_STATUS_BAR_FLAG,   
8            WindowManager.LayoutParams.NO_STATUS_BAR_FLAG);   
9      
10    setContentView(R.layout.mylayout);  
11
12
13

    二是在AndroidManifest.xml中:

1 < activity android:name = " .MyActivity "
2           android:label = ""
3           android:theme = " @android:style/Theme.NoTitleBar.Fullscreen " >


    然而,这两种方法都不能达到我们在视频播放过程中设置全屏与否的目的。因为它们都只能在初始化的时候决定全屏与否。那么我现在要说的就是第三种方法:

1 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

1 getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

    这种方法就可以在Activity运行过程中,动态地改变全屏与否。

    六、音量调节:

    音量调节的方法其实很简单,不过有人问到,我就在这里顺便说下:

1         AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
2         setIndex(am.getStreamVolume(AudioManager.STREAM_MUSIC));


    好了,就写这些了吧。可能这些知识有人知道,或者还有些盲点我没有讲到。欢迎大家与我联系,大家一起多多讨论交流,并且整个源码都开放出来了,大家一定可 以把来龙去脉弄得一清二楚的!最后,多谢大家听我罗嗦,欢迎使用SeeJoPlayer,欢迎阅读其源码!本文也欢迎大家转载,不过转载请注明出处:http://www.blogjava.net/zh-weir/archive/2010/01/24/310617.html

  • 大小: 97.5 KB
分享到:
评论

相关推荐

    Android开发-SeeJoPlayer视频播放器源码解析.pdf

    SeeJoPlayer是一款针对Android平台开发的视频播放器应用,其主要特点是提供美观的用户界面和便捷的操作体验。在源码解析部分,我们可以深入理解SeeJoPlayer如何实现这些特性。 首先,SeeJoPlayer支持多种Android...

    SeeJoPlayer播放器有源码

    SeeJoPlayer播放器支持删减返回等必备功能,解码能力也不错,值得学习

    安卓Android源码——SeeJoPlayer视频播放器.zip

    SeeJoPlayer是一款针对Android平台开发的视频播放器应用,其源码分析可以帮助我们深入了解Android多媒体框架、音视频解码以及自定义控件等关键技术。本文将深入探讨SeeJoPlayer的源码,揭示其在Android视频播放领域...

    Android-SeeJoPlayer视频播放器(源码).zip

    Android-SeeJoPlayer视频播放器(源码).zip

    安卓Android源码——SeeJoPlayer视频播放器.rar

    SeeJoPlayer是一款针对Android平台开发的视频播放器应用,其源码分析可以帮助开发者深入了解Android多媒体框架、音视频解码以及自定义控件等关键技术。本文将深入探讨SeeJoPlayer在Android开发中的重要知识点。 ...

    Android应用源码SeeJoPlayer视频播放器-IT计算机-毕业设计.zip

    SeeJoPlayer是一款基于Android平台的视频播放器应用源码,非常适合于计算机专业的学生进行毕业设计学习。这个项目涵盖了Android应用开发中的多个重要知识点,对于理解Android应用架构、多媒体处理以及用户界面设计等...

    Android-SeeJoPlayer视频播放器.zip

    Android-SeeJoPlayer视频播放器.zip

    安卓Android源码——SeeJoPlayer(播放器).zip

    SeeJoPlayer是一款基于Android平台的开源视频播放器项目。它为开发者提供了自定义播放器功能,可以帮助用户实现个性化和高级的视频播放体验。通过分析SeeJoPlayer的源码,我们可以深入理解Android系统的多媒体处理...

    SeeJoPlayer视频播放器.rar

    SeeJoPlayer是一款专为Android平台设计的视频播放器应用,其源码的提供对于开发者来说是一份宝贵的资源,可以深入理解视频播放技术以及Android应用程序的开发。在这个压缩包中,包含的是SeeJoPlayer的全部源代码,...

    安卓Android源码——SeeJoPlayer(视频播放器).zip

    【Android源码解析——SeeJoPlayer视频播放器】 在安卓应用开发中,视频播放功能是不可或缺的一部分,尤其是在娱乐、教育和新闻类应用中。SeeJoPlayer是一款专为Android平台设计的自定义视频播放器,其源码为我们...

    SeeJoPlayer视频播放器.zip

    SeeJoPlayer是一款针对Android平台设计的视频播放器应用。它具备了丰富的功能和优化的性能,使得用户在移动设备上可以流畅地观看各种格式的视频内容。作为一个专业的IT大师,我将详细介绍SeeJoPlayer视频播放器的...

    应用源码SeeJoPlayer视频播放器.zip

    【标题】"应用源码SeeJoPlayer视频播放器"是一个Android平台上的开源视频播放器项目,主要用于学习和参考。这个项目可能包含了一整套实现视频播放功能的代码,包括视频解码、渲染、控制界面以及播放器的定制化设置等...

    Android SeeJoPlayer(播放器).zip源码资源下载

    SeeJoPlayer是一款基于Android平台的开源视频播放器应用,它为开发者提供了自定义和扩展视频播放功能的机会。这款播放器可能使用了Java编程语言,并且可能依赖于Apache相关的开源库来实现其高级特性。在分析这个项目...

    SeeJoPlayer视频播放器_Android.rar

    SeeJoPlayer是一款针对Android平台设计的专业视频播放器应用。它具备强大的视频解码能力,能够支持多种视频格式,为用户提供流畅、高清的观影体验。在分析这个压缩包文件"SeeJoPlayer视频播放器_Android.rar"时,...

Global site tag (gtag.js) - Google Analytics