To build a better world !

          Android平臺下SeeJoPlayer視頻播放器(功能介紹及源碼解析,附源碼)


              轉(zhuǎn)載請注明出處:http://www.aygfsteel.com/zh-weir/archive/2010/01/24/310617.html


              2010.03.27    SeeJoPlayer v1.2.0 beta版:  

               下載SeeJoPlayer v1.2.0 beta     下載SeeJoPlayer v1.2.0 beta源碼


              更新說明:

              1、完美支持android1.5、android1.6、android2.0、android2.01、android2.1平臺;
              2、完美支持320×480、480×800、480×854等各種分辨率(自適應(yīng)屏幕分辨率);
              3、支持在線音視頻播放,支持URL input和從瀏覽器調(diào)用SeeJoPlayer播放器播放在線音視頻;
              4、自動轉(zhuǎn)為橫屏播放,為用戶提供更好的觀看體驗(yàn);
              5、修改了沒有SD卡程序出錯的Bug;
              6、美化了視頻播放列表和操作說明的界面。

              補(bǔ)充圖片:
              




          URL輸入功能

              




          瀏覽器中調(diào)用SeeJoPlayer播放


              感謝大家對SeeJoPlayer的大力支持!希望新版本能帶給大家更好的體驗(yàn)!


              2010.01.24    SeeJoPlayer v1.0.0版: 

              SeeJoPlayer是我利用業(yè)余時(shí)間開發(fā)的一款免費(fèi)的視頻播放器。主要是現(xiàn)在在網(wǎng)上似乎找不到一個(gè)Android平臺下的界面美觀一點(diǎn)的視頻播放器。而作為智能手機(jī)操作系統(tǒng)的Android,沒有一個(gè)像樣一點(diǎn)的視頻播放器,豈不糗大了。所以,我就寫了這么一個(gè)磚頭并開出源碼,希望能引出高手們的美玉來吧!


                   下載APK程序         下載源代碼         轉(zhuǎn)到eoeMarket發(fā)布頁

              



           第一部分:功能介紹


              SeeJoPlayer的優(yōu)點(diǎn)主要在相對還算美觀的界面和便捷的交互操作上。先說操作吧,它支持:

              1、全屏切換:       雙擊屏幕
              2、播放/暫停:     長按屏幕
              3、靜音/恢復(fù):     長按音量按鈕
              4、播放列表:       控制面板最右邊的按鈕(暫不支持編輯功能)
              5、音量調(diào)節(jié):       單擊音量按鈕,在彈出的音量顯示區(qū)域觸摸改變音量
           

              這些操作和PC上的播放器較為類似,希望大家能用得習(xí)慣。

              至于界面的話,多說無益,直接上圖吧:



          橫屏



          豎屏



          全屏



          非全屏



          播放列表



          介紹說明

              好了。功能介紹部分到此為止了。如果您覺得這個(gè)軟件還行的話,歡迎下載使用!


                   下載APK程序         下載源代碼         轉(zhuǎn)到eoeMarket發(fā)布頁



          第二部分:源碼解析
           

              SeeJoPlayer不是一個(gè)完美的作品,可以說,它在很多地方都不盡如人意。當(dāng)然一個(gè)完美的作品,也不是我寫這款播放器的目的。我只是希望以此為引,結(jié)合大家共同的智慧開發(fā)出一款真正完美強(qiáng)大的Android平臺下的國產(chǎn)視頻播放器出來。

              SeeJoPlayer有許多不足之處,例如,它只支持系統(tǒng)默認(rèn)的視頻格式,因?yàn)樗褂孟到y(tǒng)默認(rèn)的解碼器。這,一方面是因?yàn)槿绻ㄟ^軟解碼的話,播放視頻的效率會很受影響,另外最主要的原因當(dāng)然還是個(gè)人水平、精力有限,沒辦法接著往下做了。如果大家覺得這份代碼還多少有些參考價(jià)值的話,不妨拿去用。只是希望當(dāng)你們以此為參考,開發(fā)出真正強(qiáng)大的播放器出來的時(shí)候,別忘了如果能開放源碼的話,一定開放出來。畢竟開源軟件就好比能夠進(jìn)化的物種,提供你的DNA出來,讓我們共同的軟件變得越來越完美吧!

              好了,廢話不說了。播放器的全部源碼本文中已經(jīng)提供了下載地址。下面,我就其中我覺得可能值得關(guān)注的地方做一些解釋。

              一、VideoView與視頻比例縮放:

              以前在論壇上也看到有人問過如何實(shí)現(xiàn)視頻按比例縮放的問題。的確,如果僅僅使用VideoView可能達(dá)不到我們想要達(dá)到的效果。這就需要我們對VideoView做一些改動,簡單的說就是另外寫一個(gè)類似VideoView的類出來(慶幸Android是開源的)。

              我們可以很方便的獲得VideoView的源代碼,最簡單的方法是直接在GoogleCodeSearch上找“VideoView.java”。所以重寫VideoView的過程其實(shí)只是在原來的基礎(chǔ)上進(jìn)行一些修改而已,并非一個(gè)很麻煩的工作。為什么Android自帶的VideoView會保持視頻的長寬比而不能讓我們很方便的自定義比例呢?我猜想可能Google做Android也是一個(gè)很倉促的工程,許多代碼并沒有考慮得太成熟。

              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

              這就是為什么長寬比不能改變的原因了。因?yàn)樵贠nMeasure的時(shí)候,就對這個(gè)長寬比進(jìn)行了處理。

              我們把其中處理的代碼屏蔽掉,視頻大小就可以隨著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和控制界面放在一個(gè)LinearLayout中。這樣隨著控制界面的出現(xiàn)與否,VideoView會隨之改變長寬,給人的體驗(yàn)并不很好。所以,我認(rèn)為VideoView和控制界面最好不要放在同一個(gè)層次上。不要偷懶,使用一個(gè)FrameLayout或者PopupWindow就可以解決這個(gè)問題。例如,我就簡簡單單地使用了PopupWindow,這個(gè)具體實(shí)現(xiàn)上,就百花爭鳴吧。

              三、視頻文件掃描:

              視頻文件的掃描,現(xiàn)在想來主要有兩種方式:

              第一種就是直接讀取媒體庫中的視頻文件數(shù)據(jù)庫。當(dāng)Android啟動的時(shí)候,系統(tǒng)會自動掃描sdcard,并為媒體文件建立(或者更新)數(shù)據(jù)庫。我們可以通過對應(yīng)的URI來訪問數(shù)據(jù)庫,從而得到視頻文件的列表:
            
           1private Uri videoListUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
           2
           3
           4
           5Cursor cursor = getContentResolver().query(videoListUri, new String[]{"_display_name","_data"}nullnullnull);
           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        }


              這種方法可能是最有效率的了,不過不知為何,媒體庫中似乎沒有掃描進(jìn)本身支持的3GP視頻格式(也可能我這里是一個(gè)特例) 。不過,正是因?yàn)檫@個(gè)原因,我才想到有可能需要另外一種最基本的掃描文件系統(tǒng)的方法來掃描視頻文件。這就是文件系統(tǒng)的遍歷:

           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    }

              當(dāng)然,隨著Android平臺下的硬件設(shè)備越來越多,越來越強(qiáng)大。我們有理由相信,它以后將不僅僅只支持MP4和3GP格式的視頻文件,所以我們必須使用兩種方式結(jié)合的方法來獲得最大的視頻集合作為我們的視頻列表。

              四、播放過程中進(jìn)度條progress的設(shè)定:

              視頻開始播放了,那么一個(gè)小麻煩出現(xiàn)了:什么時(shí)候設(shè)定進(jìn)度條才更有效率?我這里有一種方法供大家參考,那就是通過Handler自己給自己發(fā)消息來達(dá)到不斷設(shè)置進(jìn)度條的目的。

           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
          24
          25
          26   
              
              當(dāng)然,這種方法,需要首先發(fā)送一個(gè)初始消息來啟動。

              五、全屏與非全屏:

              大家都知道,一般一個(gè)Activity設(shè)置全屏的方法有兩種,一是在OnCreate中:

           1@Override   
           2public 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">

              然而,這兩種方法都不能達(dá)到我們在視頻播放過程中設(shè)置全屏與否的目的。因?yàn)樗鼈兌贾荒茉诔跏蓟臅r(shí)候決定全屏與否。那么我現(xiàn)在要說的就是第三種方法:

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

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

              這種方法就可以在Activity運(yùn)行過程中,動態(tài)地改變?nèi)僚c否。

              六、音量調(diào)節(jié):

              音量調(diào)節(jié)的方法其實(shí)很簡單,不過有人問到,我就在這里順便說下:

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

              好了,就寫這些了吧。可能這些知識有人知道,或者還有些盲點(diǎn)我沒有講到。歡迎大家與我聯(lián)系,大家一起多多討論交流,并且整個(gè)源碼都開放出來了,大家一定可以把來龍去脈弄得一清二楚的!最后,多謝大家聽我羅嗦,歡迎使用SeeJoPlayer,歡迎閱讀其源碼!本文也歡迎大家轉(zhuǎn)載,不過轉(zhuǎn)載請注明出處:http://www.aygfsteel.com/zh-weir/archive/2010/01/24/310617.html


                   下載APK程序         下載源代碼         轉(zhuǎn)到eoeMarket發(fā)布頁



              
              

          posted on 2010-01-24 17:20 zh.weir 閱讀(61991) 評論(104)  編輯  收藏 所屬分類: Android項(xiàng)目源碼

          評論共2頁: 上一頁 1 2 

          評論

          # re: Android平臺下SeeJoPlayer視頻播放器(功能介紹及源碼解析,附源碼)[未登錄] 2010-01-24 18:10 L

          不知道支持的視頻格式有哪些??  回復(fù)  更多評論   

          # re: Android平臺下SeeJoPlayer視頻播放器(功能介紹及源碼解析,附源碼) 2010-01-24 18:25 zh.weir

          @L
          SeeJoPlayer采用的是系統(tǒng)默認(rèn)的解碼方式,因此對于G1來說,它應(yīng)該只支持MP4和3GP。但是如果你的系統(tǒng)本身支持更多格式,那么只要媒體庫里有的格式,它原理上都支持。  回復(fù)  更多評論   

          # re: Android平臺下SeeJoPlayer視頻播放器(功能介紹及源碼解析,附源碼) 2010-01-25 15:28 changedi

          慚愧,首先在eoeandriod看到這篇文章,來支持一下~~最近打算學(xué)習(xí)Andriod  回復(fù)  更多評論   

          # re: Android平臺下SeeJoPlayer視頻播放器(功能介紹及源碼解析,附源碼)[未登錄] 2010-02-08 16:27 a

          Android1.5支持如下的媒體類型:

          類型
          格式
          編碼
          解碼
          詳情
          文件類型

          Audio
          AAC LC/LTP

          Y
          單/ 雙聲道160Kpbs 的碼率,采樣4-48KHz


          3GPP(.3gp)

          MPEG-4(.mp4,.m4a)

          不支持raw AAC(.aac)

          HE-AACv1

          (AAC+)

          Y

          HE-AACv2

          ( 增強(qiáng)AAC+)

          Y

          AMR-NB
          Y
          Y
          4.75 to 12.2 kbps sampled @ 8kHz
          3GPP (.3gp)

          AMR-WB

          Y
          9 rates from 6.60 kbit/s to 23.85 kbit/s sampled @ 16kHz
          3GPP (.3gp)

          MP3

          Y
          Mono/Stereo 8-320Kbps constant (CBR) or variable bit-rate (VBR)
          MP3 (.mp3)

          MIDI

          Y
          MIDI Type 0 and 1. DLS Version 1 and 2. XMF and Mobile XMF. Support for ringtone formats RTTTL/RTX, OTA, and iMelody
          Type 0 and 1 (.mid, .xmf, .mxmf). Also RTTTL/RTX (.rtttl, .rtx), OTA (.ota), and iMelody (.imy)

          Ogg Vorbis

          Y

          Ogg (.ogg)

          PCM/WAVE

          Y
          8- and 16-bit linear PCM (rates up to limit of hardware)
          WAVE (.wav)

          Image
          JPEG
          Y
          Y
          Base+progressive
          JPEG(.jpg)

          GIF

          Y

          GIF(.gif)

          PNG

          Y

          PNG(.png)

          BMP

          Y

          BMP(.bmp)

          Video
          H.263
          Y
          Y

          3GPP (.3gp)


          H.264 AVC

          Y

          3GPP (.3gp) and MPEG-4 (.mp4)


          MPEG-4 SP

          Y

          3GPP (.3gp)


          T1還 額外支持了:Audio 的WMA ,Video 的WMV類型。
            回復(fù)  更多評論   

          評論共2頁: 上一頁 1 2 

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           

          公告

          大家好!歡迎光臨我的 Android 技術(shù)博客!



          本博客旨在交流與 Android 操作系統(tǒng)相關(guān)的各種技術(shù)及信息。

          博客內(nèi)的文章會盡量以開源的形式提供給大家,希望我們能相互交流,共同提高!

          有不足之處,請不吝賜教!

          我的郵箱:zh.weir@gmail.com
          我的新浪微博:@囧虎張建偉

           

          導(dǎo)航

          <2016年1月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          統(tǒng)計(jì)

          留言簿(19)

          隨筆分類(24)

          隨筆檔案(18)

          文章檔案(1)

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 富裕县| 颍上县| 清新县| 长阳| 建瓯市| 泸定县| 邢台市| 霍州市| 桃园市| 永宁县| 临澧县| 塔河县| 岑巩县| 华亭县| 蕉岭县| 定襄县| 松滋市| 徐水县| 霞浦县| 金沙县| 滨海县| 曲松县| 讷河市| 耒阳市| 嘉义市| 杭锦旗| 宜昌市| 汉川市| 得荣县| 合江县| 察隅县| 天峻县| 宾川县| 和平县| 信宜市| 苏州市| 义乌市| 新源县| 江达县| 江西省| 察哈|