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

来源:互联网 发布:python 程序 编辑:程序博客网 时间:2024/05/01 05:16
正文
  一、目标
    1.1  A-Z快速切换查找影片
                把手机上的联系人上的A-Z快速查找运用到了这里,查找文件更便捷。这也是"学"的米聊的 :)
    1.2  缓存扫描视频列表
                首次使用扫描SD卡一遍,以后就从数据库读取了,下篇文章再加一个监听即可。
    1.3             截图
     2012-6-8_1.png

  二、实现
        核心代码:
  1. public class FragmentFile extends FragmentBase implements OnItemClickListener {

  2.     private FileAdapter mAdapter;
  3.     private TextView first_letter_overlay;
  4.     private ImageView alphabet_scroller;

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

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

  15.         // ~~~~~~~~~ 加载数据
  16.         if (new SQLiteHelper(getActivity()).isEmpty())
  17.             new ScanVideoTask().execute();
  18.         else
  19.             new DataTask().execute();

  20.         return v;
  21.     }

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

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

  31.         @Override
  32.         protected void onPreExecute() {
  33.             super.onPreExecute();
  34.             mLoadingLayout.setVisibility(View.VISIBLE);
  35.             mListView.setVisibility(View.GONE);
  36.         }

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

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

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

  46.             mLoadingLayout.setVisibility(View.GONE);
  47.             mListView.setVisibility(View.VISIBLE);
  48.         }
  49.     }

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

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

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

  65.             // ~~~ 入库
  66.             SQLiteHelper sqlite = new SQLiteHelper(getActivity());
  67.             SQLiteDatabase db = sqlite.getWritableDatabase();
  68.             try {
  69.                 db.beginTransaction();

  70.                 SQLiteStatement stat = db.compileStatement("INSERT INTO files(" + FilesColumns.COL_TITLE + "," + FilesColumns.COL_TITLE_PINYIN + "," + FilesColumns.COL_PATH + "," + FilesColumns.COL_LAST_ACCESS_TIME + ") VALUES(?,?,?,?)");
  71.                 for (File f : files) {
  72.                     String name = FileUtils.getFileNameNoEx(f.getName());
  73.                     int index = 1;
  74.                     stat.bindString(index++, name);//title
  75.                     stat.bindString(index++, PinyinUtils.chineneToSpell(name));//title_pinyin
  76.                     stat.bindString(index++, f.getPath());//path
  77.                     stat.bindLong(index++, System.currentTimeMillis());//last_access_time
  78.                     stat.execute();
  79.                 }
  80.                 db.setTransactionSuccessful();
  81.             } catch (BadHanyuPinyinOutputFormatCombination e) {
  82.                 e.printStackTrace();
  83.             } catch (Exception e) {
  84.                 e.printStackTrace();
  85.             } finally {
  86.                 db.endTransaction();
  87.                 db.close();
  88.             }

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

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

  98.         /** 遍历所有文件夹,查找出视频文件 */
  99.         public void eachAllMedias(File f) {
  100.             if (f != null && f.exists() && f.isDirectory()) {
  101.                 File[] files = f.listFiles();
  102.                 if (files != null) {
  103.                     for (File file : f.listFiles()) {
  104.                         if (file.isDirectory()) {
  105.                             eachAllMedias(file);
  106.                         } else if (file.exists() && file.canRead() && FileUtils.isVideoOrAudio(file)) {
  107.                             publishProgress(file);
  108.                         }
  109.                     }
  110.                 }
  111.             }
  112.         }

  113.         @Override
  114.         protected void onPostExecute(ArrayList<PFile> result) {
  115.             super.onPostExecute(result);
  116.             mAdapter = new FileAdapter(getActivity(), result);
  117.             mListView.setAdapter(mAdapter);
  118.             pd.dismiss();
  119.         }
  120.     }

  121.     private class FileAdapter extends ArrayAdapter<PFile> {

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

  125.         @Override
  126.         public View getView(int position, View convertView, ViewGroup parent) {
  127.             final PFile f = getItem(position);
  128.             if (convertView == null) {
  129.                 final LayoutInflater mInflater = getActivity().getLayoutInflater();
  130.                 convertView = mInflater.inflate(R.layout.fragment_file_item, null);
  131.             }
  132.             ((TextView) convertView.findViewById(R.id.title)).setText(f.title);
  133.             return convertView;
  134.         }

  135.     }

  136.     /**
  137.      * A-Z
  138.      */
  139.     private OnTouchListener asOnTouch = new OnTouchListener() {

  140.         @Override
  141.         public boolean onTouch(View v, MotionEvent event) {
  142.             switch (event.getAction()) {
  143.             case MotionEvent.ACTION_DOWN:// 0
  144.                 alphabet_scroller.setPressed(true);
  145.                 first_letter_overlay.setVisibility(View.VISIBLE);
  146.                 mathScrollerPosition(event.getY());
  147.                 break;
  148.             case MotionEvent.ACTION_UP:// 1
  149.                 alphabet_scroller.setPressed(false);
  150.                 first_letter_overlay.setVisibility(View.GONE);
  151.                 break;
  152.             case MotionEvent.ACTION_MOVE:
  153.                 mathScrollerPosition(event.getY());
  154.                 break;
  155.             }
  156.             return false;
  157.         }
  158.     };

  159.     /**
  160.      * 显示字符
  161.      *
  162.      * @param y
  163.      */
  164.     private void mathScrollerPosition(float y) {
  165.         int height = alphabet_scroller.getHeight();
  166.         float charHeight = height / 28.0f;
  167.         char c = 'A';
  168.         if (y < 0)
  169.             y = 0;
  170.         else if (y > height)
  171.             y = height;

  172.         int index = (int) (y / charHeight) - 1;
  173.         if (index < 0)
  174.             index = 0;
  175.         else if (index > 25)
  176.             index = 25;

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

  179.         int position = 0;
  180.         if (index == 0)
  181.             mListView.setSelection(0);
  182.         else if (index == 25)
  183.             mListView.setSelection(mAdapter.getCount() - 1);
  184.         else {
  185.             for (PFile item : mAdapter.getAll()) {
  186.                 if (item.title_pinyin.startsWith(key)) {
  187.                     mListView.setSelection(position);
  188.                     break;
  189.                 }
  190.                 position++;
  191.             }
  192.         }
  193.     }
复制代码
代码说明:
                代码是基于上篇文章,新增了播放列表缓存功能以及快速查找功能。

                a).  使用了pinyin4j开源项目,用于提取文件名中的汉字的拼音,以便能够。
                b).  A-Z这部分的代码也是通过反编译参考米聊的,比较有实用价值
                c).  入库部分使用了事务
                其他代码请参见项目代码。
        注意:由于是示例代码,考虑不尽周全,可能在后续章节中补充,请大家注意不要直接使用代码!例如应该检查一下SD卡是否可用等问题。

  三、项目下载

         Vitamio-Demo2012-6-8.zip