Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發學習之路--基於vitamio的視頻播放器(一)

Android開發學習之路--基於vitamio的視頻播放器(一)

編輯:關於Android編程

之前也試過vitamio這個庫,後來不知道被什麼事情給耽擱了,就沒繼續下去。近來覺得視頻還是需要學習一下的,誰讓直播那麼火呢,就想著寫一個簡單的視頻播放的app先吧。好了那就開始吧,暫時取名為JPlayer,後續慢慢改進,源碼也在github上(https://github.com/imchenjianneng/JPlayer),後續不斷更新吧。
首先新建工程JPlayer,然後新建個主界面吧:


    
    

        

            

                
                    

                    

                        

                            

                            
                        
                    
                
            

        

        

    

這裡簡單簡紹下,具體可以看源碼,界面由是兩個radiobutton,一個viewpager組成,比較簡陋,後續再改吧,我們先實現功能要緊。真實項目一般ui都會提供好界面的。
??既然界面搭建好了,那麼繼續開始代碼實現吧:

public class MainActivity extends BaseActivity implements ViewPager.OnPageChangeListener {

    private MainBinding binding;

    private List bts = Arrays.asList(
            R.id.rb_local,
            R.id.rb_intenet);

    private float normalSize, normalSelected;

    @Override
    protected void initParams() {
        binding = DataBindingUtil.setContentView(getActivity(), R.layout.activity_main);
    }

    @Override
    protected void initViews() {
        super.initViews();

        normalSize = getResources().getDimension(R.dimen.normal_size);
        normalSelected = getResources().getDimension(R.dimen.selected_size);

        binding.viewpager.setOffscreenPageLimit(2);
        binding.viewpager.setAdapter(new MyFragmentPagerAdapter(getSupportFragmentManager()));
        initTabPagerListener();
        binding.rgTab.check(bts.get(0));
    }

    private void initTabPagerListener() {

        binding.viewpager.addOnPageChangeListener(this);
        binding.rgTab.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                int i = bts.indexOf(checkedId);
                if (i != -1) {
                    selectTitle(checkedId);
                    binding.viewpager.setCurrentItem(i);
                }
            }
        });
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        selectTitle(bts.get(position));

        binding.rgTab.check(bts.get(position));
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }

    private void selectTitle(int selectResId) {
        binding.rbLocal.setTextSize(TypedValue.COMPLEX_UNIT_PX, normalSize);
        binding.rbIntenet.setTextSize(TypedValue.COMPLEX_UNIT_PX, normalSize);
        ((TextView)findViewById(selectResId)).setTextSize(TypedValue.COMPLEX_UNIT_PX,
                normalSelected);
    }

    public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
        LocalVideoFragment localVideoFragment = new LocalVideoFragment();
        InternetVideoFragment internetVideoFragment = new InternetVideoFragment();
        private List list = Arrays.asList(
                localVideoFragment,
                internetVideoFragment);

        public MyFragmentPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public int getCount() {
            return list.size();
        }

        @Override
        public Fragment getItem(int position) {
            return list.get(position);
        }
    }
}

代碼其實比較簡單,主要實現了viewpager,然後LocalVideoFragment和InternetVideoFragment兩個fragment,第一個是本地的界面,第二個是網絡(這裡暫時不實現),好了,主要的代碼都在LocalVideoFragment裡了。那麼就接著看這個Frament的代碼了。

既然要播放視頻,首先是需要實現掃描所有視頻文件。先看這一段代碼吧:

private class ScanVideoTask extends AsyncTask {

        @Override
        protected Void doInBackground(Void... params) {
            eachAllMedias(Environment.getExternalStorageDirectory());
            return null;
        }

        @Override
        protected void onProgressUpdate(File... values) {
            LocalSource localSource = new LocalSource();
            localSource.setName(values[0].getName());
            localSource.setUrl(values[0].getAbsolutePath());
            localSource.setBitmap(getVideoThumbnail(localSource, localSource.getUrl()));
            localSource.setBitmap(getVideoThumbnail(localSource.getUrl()));
            Log.d("LocalVideoFragment", "hhh"+localSource.getName()+":"+localSource.getUrl());
            fileAdapter.appendItem(localSource);
            fileAdapter.notifyDataSetChanged();

        }

        /** 遍歷所有文件夾,查找出視頻文件 */
        public void eachAllMedias(File f) {
            if (f != null && f.exists() && f.isDirectory()) {
                File[] files = f.listFiles();
                if (files != null) {
                    for (File file : f.listFiles()) {
                        if (file.isDirectory()) {
                            eachAllMedias(file);
                        } else if (file.exists() && file.canRead() && isVideo(file)) {
                            publishProgress(file);
                        }
                    }
                }
            }
        }
    }

??掃描需要花費比較長的時間,所以這裡放到一個異步task中去處理,深度優先的搜索所有的文件,掃描到了文件判斷是否為視頻文件,若是的話,那就直接加到recycleview中去。對於是否是視頻文件,這裡僅僅是判斷後綴名,更合理的方式應該是解碼一部分,然後判斷頭文件的信息的,之類就偷懶了一下,具體可以參考源碼。
??既然已經掃描出了文件,那麼接下來就需要這個播放列表了,因為我們要顯示視頻的縮略圖,視頻的文件名,以及播放時長和大小。用到了MediaMetadataRetriever類,通過extractMetadata方法來獲取視頻的相關信息,看下代碼吧:

public Bitmap getVideoThumbnail(LocalSource localSource, String filePath) {
        Bitmap bitmap = null;
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        try {
            retriever.setDataSource(filePath);
            bitmap = retriever.getFrameAtTime(0);
            localSource.setAuthor(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_AUTHOR));
            localSource.setDuration(Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)));
            localSource.setDate(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE));
            localSource.setBitrate(Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE)));

        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

這通過retriever.getFrameAtTime來獲取一幀的圖像bitmap用來當縮略圖,然後通過MediaMetadataRetriever.METADATA_KEY_DURATION獲取播放時長。通過MediaMetadataRetriever.METADATA_KEY_BITRATE獲取比特率,計算就可以得到所需要的文件大小。
要上班去了,接下去的話就是重點了,怎麼使用vitamio,下次繼續了,想直接看代碼的話可以直接github看起來,代碼寫得比較挫,還沒有整理過,為了實現功能而寫。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved