• 使用Vitamio打造自己的Android万能播放器(4)——本地播放(快捷搜索、数据存储)



    前言

      关键字:Vitamio、VPlayer、Android播放器、Android影音、Android开源播放器

      本章节把Android万能播放器本地播放的主要功能(缓存播放列表和A-Z快速查询功能)完成,和播放组件关系不大,但用到一些实用的技术,欢迎交流!

    声明
      欢迎转载,但请保留文章原始出处:) 
        博客园:http://www.cnblogs.com

        农民伯伯: http://over140.cnblogs.com 

    系列

      1、使用Vitamio打造自己的Android万能播放器(1)——准备

      2、使用Vitamio打造自己的Android万能播放器(2)—— 手势控制亮度、音量、缩放

      3、使用Vitamio打造自己的Android万能播放器(3)——本地播放(主界面、播放列表)
     

    正文

      一、目标

        1.1  A-Z快速切换查找影片

    把手机上的联系人上的A-Z快速查找运用到了这里,查找文件更便捷。这也是"学"的米聊的 :)

        1.2  缓存扫描视频列表

    首次使用扫描SD卡一遍,以后就从数据库读取了,下篇文章再加一个监听即可。

        1.3      截图 

             

      二、实现

    核心代码:

    public class FragmentFile extends FragmentBase implements OnItemClickListener {

        private FileAdapter mAdapter;
        private TextView first_letter_overlay;
        private ImageView alphabet_scroller;

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View v = super.onCreateView(inflater, container, savedInstanceState);
            // ~~~~~~~~~ 绑定控件
            first_letter_overlay = (TextView) v.findViewById(R.id.first_letter_overlay);
            alphabet_scroller = (ImageView) v.findViewById(R.id.alphabet_scroller);

            // ~~~~~~~~~ 绑定事件
            alphabet_scroller.setClickable(true);
            alphabet_scroller.setOnTouchListener(asOnTouch);
            mListView.setOnItemClickListener(this);

            // ~~~~~~~~~ 加载数据
            if (new SQLiteHelper(getActivity()).isEmpty())
                new ScanVideoTask().execute();
            else
                new DataTask().execute();

            return v;
        }

        /** 单击启动播放 */
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            final PFile f = mAdapter.getItem(position);
            Intent intent = new Intent(getActivity(), VideoViewDemo.class);
            intent.putExtra("path", f.path);
            startActivity(intent);
        }

        private class DataTask extends AsyncTask<Void, Void, ArrayList<PFile>> {

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                mLoadingLayout.setVisibility(View.VISIBLE);
                mListView.setVisibility(View.GONE);
            }

            @Override
            protected ArrayList<PFile> doInBackground(Void... params) {
                return FileBusiness.getAllSortFiles(getActivity());
            }

            @Override
            protected void onPostExecute(ArrayList<PFile> result) {
                super.onPostExecute(result);

                mAdapter = new FileAdapter(getActivity(), FileBusiness.getAllSortFiles(getActivity()));
                mListView.setAdapter(mAdapter);

                mLoadingLayout.setVisibility(View.GONE);
                mListView.setVisibility(View.VISIBLE);
            }
        }

        /** 扫描SD卡 */
        private class ScanVideoTask extends AsyncTask<Void, File, ArrayList<PFile>> {
            private ProgressDialog pd;
            private ArrayList<File> files = new ArrayList<File>();

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                pd = new ProgressDialog(getActivity());
                pd.setMessage("正在扫描视频文件...");
                pd.show();
            }

            @Override
            protected ArrayList<PFile> doInBackground(Void... params) {
                // ~~~ 遍历文件夹
                eachAllMedias(Environment.getExternalStorageDirectory());

                // ~~~ 入库
                SQLiteHelper sqlite = new SQLiteHelper(getActivity());
                SQLiteDatabase db = sqlite.getWritableDatabase();
                try {
                    db.beginTransaction();

                    SQLiteStatement stat = db.compileStatement("INSERT INTO files(" + FilesColumns.COL_TITLE + "," + FilesColumns.COL_TITLE_PINYIN + "," + FilesColumns.COL_PATH + "," + FilesColumns.COL_LAST_ACCESS_TIME + ") VALUES(?,?,?,?)");
                    for (File f : files) {
                        String name = FileUtils.getFileNameNoEx(f.getName());
                        int index = 1;
                        stat.bindString(index++, name);//title
                        stat.bindString(index++, PinyinUtils.chineneToSpell(name));//title_pinyin
                        stat.bindString(index++, f.getPath());//path
                        stat.bindLong(index++, System.currentTimeMillis());//last_access_time
                        stat.execute();
                    }
                    db.setTransactionSuccessful();
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    db.endTransaction();
                    db.close();
                }

                // ~~~ 查询数据
                return FileBusiness.getAllSortFiles(getActivity());
            }

            @Override
            protected void onProgressUpdate(final File... values) {
                File f = values[0];
                files.add(f);
                pd.setMessage(f.getName());
            }

            /** 遍历所有文件夹,查找出视频文件 */
            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() && FileUtils.isVideoOrAudio(file)) {
                                publishProgress(file);
                            }
                        }
                    }
                }
            }

            @Override
            protected void onPostExecute(ArrayList<PFile> result) {
                super.onPostExecute(result);
                mAdapter = new FileAdapter(getActivity(), result);
                mListView.setAdapter(mAdapter);
                pd.dismiss();
            }
        }

        private class FileAdapter extends ArrayAdapter<PFile> {

            public FileAdapter(Context ctx, ArrayList<PFile> l) {
                super(ctx, l);
            }

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                final PFile f = getItem(position);
                if (convertView == null) {
                    final LayoutInflater mInflater = getActivity().getLayoutInflater();
                    convertView = mInflater.inflate(R.layout.fragment_file_item, null);
                }
                ((TextView) convertView.findViewById(R.id.title)).setText(f.title);
                return convertView;
            }

        }

        /**
         * A-Z
         
    */
        private OnTouchListener asOnTouch = new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:// 0
                    alphabet_scroller.setPressed(true);
                    first_letter_overlay.setVisibility(View.VISIBLE);
                    mathScrollerPosition(event.getY());
                    break;
                case MotionEvent.ACTION_UP:// 1
                    alphabet_scroller.setPressed(false);
                    first_letter_overlay.setVisibility(View.GONE);
                    break;
                case MotionEvent.ACTION_MOVE:
                    mathScrollerPosition(event.getY());
                    break;
                }
                return false;
            }
        };

        /**
         * 显示字符
         * 
         * 
    @param y
         
    */
        private void mathScrollerPosition(float y) {
            int height = alphabet_scroller.getHeight();
            float charHeight = height / 28.0f;
            char c = 'A';
            if (y < 0)
                y = 0;
            else if (y > height)
                y = height;

            int index = (int) (y / charHeight) - 1;
            if (index < 0)
                index = 0;
            else if (index > 25)
                index = 25;

            String key = String.valueOf((char) (c + index));
            first_letter_overlay.setText(key);

            int position = 0;
            if (index == 0)
                mListView.setSelection(0);
            else if (index == 25)
                mListView.setSelection(mAdapter.getCount() - 1);
            else {
                for (PFile item : mAdapter.getAll()) {
                    if (item.title_pinyin.startsWith(key)) {
                        mListView.setSelection(position);
                        break;
                    }
                    position++;
                }
            }
        }

     代码说明:

            代码是基于上篇文章,新增了播放列表缓存功能以及快速查找功能。

    a).  使用了pinyin4j开源项目,用于提取文件名中的汉字的拼音,以便能够。

    b).  A-Z这部分的代码也是通过反编译参考米聊的,比较有实用价值

    c).  入库部分使用了事务

    其他代码请参见项目代码。 

    注意:由于是示例代码,考虑不尽周全,可能在后续章节中补充,请大家注意不要直接使用代码!例如应该检查一下SD卡是否可用等问题。 

      三、项目下载

     Vitamio-Demo2012-6-8.zip

      四、Vtamio与VPlayer

    Vitamio:http://vov.io 
      VPlayer:http://vplayer.net (使用Vitamio最成功的产品,用户超过500万)

    结束

    这周发布新的版本稍忙,拖到周五才写这篇文章,总算没有食言 :) 功能越做越细,也会尽量往一个正式的产品方向靠,尽可能的提供有用的代码。

  • 相关阅读:
    我参与过的开源项目
    chineking / WeiboCrawler / wiki / Home — Bitbucket
    PIL应用之生成验证码图片
    hurl
    Hadoop笔记之安装及伪分布式模式配置
    httpbin(1): HTTP Client Testing Service
    动态规划求编辑距离 残阳似血的博客
    cppreference.com
    sscanf
    在python中定义二维数组
  • 原文地址:https://www.cnblogs.com/over140/p/2541452.html
Copyright © 2020-2023  润新知