zoukankan      html  css  js  c++  java
  • 使用Vitamio打造自己的Android万能播放器(11)—— 本地扫描后台服务


    前言

    Vitamio和OPlayer系列文章得到广大同行的关注和支持,非常感谢!离系列文章的上篇有几个月了,各种忙暂停了本系列文章,非常抱歉!离OPlayer正式上线还有距离,还有很多要做的事情,继续前行!

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

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

    正文

    一、注意事项

    本章节使用的是Vitamio 3.0(2012-11-07)请大家及时更新。

    注意3.0整合的适合建议使用Library方式整合Vitamio,否则需要反射或者使用OPlayer的方法,覆盖R(参见代码)。 

    二、主要代码:

    /** 媒体扫描 */
    public class MediaScannerService extends Service implements Runnable {

        private static final String SERVICE_NAME = "com.nmbb.oplayer.service.MediaScannerService";
        /** 扫描文件夹 */
        public static final String EXTRA_DIRECTORY = "scan_directory";
        /** 扫描文件 */
        public static final String EXTRA_FILE_PATH = "scan_file";
        public static final String EXTRA_MIME_TYPE = "mimetype";

        public static final int SCAN_STATUS_NORMAL = -1;
        /** 开始扫描 */
        public static final int SCAN_STATUS_START = 0;
        /** 正在扫描 扫描到一个视频文件 */
        public static final int SCAN_STATUS_RUNNING = 1;
        /** 扫描完成 */
        public static final int SCAN_STATUS_END = 2;
        /**  */
        private ArrayList<IMediaScannerObserver> observers = new ArrayList<IMediaScannerObserver>();
        private ConcurrentHashMap<String, String> mScanMap = new ConcurrentHashMap<String, String>();

        /** 当前状态 */
        private volatile int mServiceStatus = SCAN_STATUS_NORMAL;
        private DbHelper<POMedia> mDbHelper;
        private Map<String, Object> mDbWhere = new HashMap<String, Object>(2);

        @Override
        public void onCreate() {
            super.onCreate();

            mDbHelper = new DbHelper<POMedia>();
        }

        /** 是否正在运行 */
        public static boolean isRunning() {
            ActivityManager manager = (ActivityManager) OPlayerApplication.getContext().getSystemService(Context.ACTIVITY_SERVICE);
            for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
                if (SERVICE_NAME.equals(service.service.getClassName()))
                    return true;
            }
            return false;
        }

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            if (intent != null)
                parseIntent(intent);

            return super.onStartCommand(intent, flags, startId);
        }

        /** 解析Intent */
        private void parseIntent(final Intent intent) {
            final Bundle arguments = intent.getExtras();
            if (arguments != null) {
                if (arguments.containsKey(EXTRA_DIRECTORY)) {
                    String directory = arguments.getString(EXTRA_DIRECTORY);
                    Logger.i("onStartCommand:" + directory);
                    //扫描文件夹
                    if (!mScanMap.containsKey(directory))
                        mScanMap.put(directory, "");
                } else if (arguments.containsKey(EXTRA_FILE_PATH)) {
                    //单文件
                    String filePath = arguments.getString(EXTRA_FILE_PATH);
                    Logger.i("onStartCommand:" + filePath);
                    if (!StringUtils.isEmpty(filePath)) {
                        if (!mScanMap.containsKey(filePath))
                            mScanMap.put(filePath, arguments.getString(EXTRA_MIME_TYPE));
                        //                    scanFile(filePath, arguments.getString(EXTRA_MIME_TYPE));
                    }
                }
            }

            if (mServiceStatus == SCAN_STATUS_NORMAL || mServiceStatus == SCAN_STATUS_END) {
                new Thread(this).start();
                //scan();
            }
        }

        @Override
        public void run() {
            scan();
        }

        /** 扫描 */
        private void scan() {
            //开始扫描
            notifyObservers(SCAN_STATUS_START, null);

            while (mScanMap.keySet().size() > 0) {

                String path = "";
                for (String key : mScanMap.keySet()) {
                    path = key;
                    break;
                }
                if (mScanMap.containsKey(path)) {
                    String mimeType = mScanMap.get(path);
                    if ("".equals(mimeType)) {
                        scanDirectory(path);
                    } else {
                        scanFile(path, mimeType);
                    }

                    //扫描完成一个
                    mScanMap.remove(path);
                }

                //任务之间歇息一秒
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Logger.e(e);
                }
            }

            //全部扫描完成
            notifyObservers(SCAN_STATUS_END, null);

            //第一次扫描
            OPreference pref = new OPreference(this);
            if (pref.getBoolean(OPlayerApplication.PREF_KEY_FIRST, true))
                pref.putBooleanAndCommit(OPlayerApplication.PREF_KEY_FIRST, false);

            //停止服务
            stopSelf();
        }

        private Handler mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                for (IMediaScannerObserver s : observers) {
                    if (s != null) {
                        s.update(msg.what, (POMedia) msg.obj);
                    }
                }
            }
        };

        /** 扫描文件 */
        private void scanFile(String path, String mimeType) {
            save(new POMedia(path, mimeType));
        }

        /** 扫描文件夹 */
        private void scanDirectory(String path) {
            eachAllMedias(new File(path));
        }

        /** 递归查找视频 */
        private void eachAllMedias(File f) {
            if (f != null && f.exists() && f.isDirectory()) {
                File[] files = f.listFiles();
                if (files != null) {
                    for (File file : f.listFiles()) {
                        //                    Logger.i(f.getAbsolutePath());
                        if (file.isDirectory()) {
                            //忽略.开头的文件夹
                            if (!file.getAbsolutePath().startsWith("."))
                                eachAllMedias(file);
                        } else if (file.exists() && file.canRead() && FileUtils.isVideo(file)) {
                            save(new POMedia(file));
                        }
                    }
                }
            }
        }

        /**
         * 保存入库
         * 
         * 
    @throws FileNotFoundException
         
    */
        private void save(POMedia media) {
            mDbWhere.put("path", media.path);
            mDbWhere.put("last_modify_time", media.last_modify_time);
            //检测
            if (!mDbHelper.exists(media, mDbWhere)) {
                try {
                    if (media.title != null && media.title.length() > 0)
                        media.title_key = PinyinUtils.chineneToSpell(media.title.charAt(0) + "");
                } catch (Exception ex) {
                    Logger.e(ex);
                }
                media.last_access_time = System.currentTimeMillis();

                //提取缩略图
                
    //            extractThumbnail(media);
                media.mime_type = FileUtils.getMimeType(media.path);

                //入库
                mDbHelper.create(media);

                //扫描到一个
                notifyObservers(SCAN_STATUS_RUNNING, media);
            }
        }

        /** 提取生成缩略图 */
        private void extractThumbnail(POMedia media) {
            final Context ctx = OPlayerApplication.getContext();
            //        ThumbnailUtils.
            Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(ctx, media.path, ThumbnailUtils.MINI_KIND);
            try {
                if (bitmap == null) {
                    //缩略图创建失败
                    bitmap = Bitmap.createBitmap(ThumbnailUtils.TARGET_SIZE_MINI_THUMBNAIL_WIDTH, ThumbnailUtils.TARGET_SIZE_MINI_THUMBNAIL_HEIGHT, Bitmap.Config.RGB_565);
                }

                media.width = bitmap.getWidth();
                media.height = bitmap.getHeight();

                //缩略图
                bitmap = ThumbnailUtils.extractThumbnail(bitmap, ConvertUtils.dipToPX(ctx, ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL_WIDTH), ConvertUtils.dipToPX(ctx, ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL_HEIGHT), ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
                if (bitmap != null) {
                    //将缩略图存到视频当前路径
                    File thum = new File(OPlayerApplication.OPLAYER_VIDEO_THUMB, UUID.randomUUID().toString());
                    media.thumb_path = thum.getAbsolutePath();
                    //thum.createNewFile();
                    FileOutputStream iStream = new FileOutputStream(thum);
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 85, iStream);
                    iStream.close();
                }

                //入库

            } catch (Exception ex) {
                Logger.e(ex);
            } finally {
                if (bitmap != null)
                    bitmap.recycle();

            }
        }

        // ~~~ 状态改变 

        /** 通知状态改变 */
        private void notifyObservers(int flag, POMedia media) {
            mHandler.sendMessage(mHandler.obtainMessage(flag, media));
        }

        /** 增加观察者 */
        public void addObserver(IMediaScannerObserver s) {
            synchronized (this) {
                if (!observers.contains(s)) {
                    observers.add(s);
                }
            }
        }

        /** 删除观察者 */
        public synchronized void deleteObserver(IMediaScannerObserver s) {
            observers.remove(s);
        }

        /** 删除所有观察者 */
        public synchronized void deleteObservers() {
            observers.clear();
        }

        public interface IMediaScannerObserver {
            /**
             * 
             * 
    @param flag 0 开始扫描 1 正在扫描 2 扫描完成
             * 
    @param file 扫描到的视频文件
             
    */
            public void update(int flag, POMedia media);
        }

        // ~~~ Binder 

        private final MediaScannerServiceBinder mBinder = new MediaScannerServiceBinder();

        public class MediaScannerServiceBinder extends Binder {
            public MediaScannerService getService() {
                return MediaScannerService.this;
            }
        }

        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }

    }

    代码说明:

    1、默认Service是在主线程中运行的,扫描比较耗时,这里启用了一个新的线程。

    2、使用了观察者模式来通知数据变化,没有用广播。

    3、暂时去掉了截图,截图报错,还在修改。 

    三、OPlayer

    3.1 下载
    请移步#Taocode(SVN):(没有账户的请注册一个即可)
    项目地址:http://code.taobao.org/p/oplayer
    SVN地址:http://code.taobao.org/svn/oplayer/ 

    3.2 更新
    a). 数据库层使用了ormlite框架。
    b). 将扫描视频文件修改为后台服务,单独起了一个线程。

    c). 整合Vitamio 3.0,修改反射为覆盖io.voo.vitamio.R。 

    四、Vitamio

    已建立Vitamio开发者联盟官方QQ群!群号为:246969281
    注意:目前仅接受已经开发基于Vitamio产品的开发者申请加入,申请理由请填写产品的名称和链接!
    官方微博:http://weibo.com/vitamio 
     

    五、八卦

    想在这里澄清一下OPlayer与VPlayer、Vitamio的关系:

    1、OPlayer这个项目是跟公司没有关系,纯属于个人业余爱好作品。

    2、OPlayer使用的是Vitamio,但不会比大家优先获取Vitamio的新版本。

    3、OPlayer非官方示例。

    结束

     更加深刻体会“坚持就是胜利”这句话的意义。

  • 相关阅读:
    Flex之五筒布局:想去哪儿就去哪儿 上手就会
    CSS画出三角形与圆形小技巧
    HTML table表格标签
    HTML 常用列表标签
    vue-learning:4-template-v-if-and-v-show
    vue-learning:3-template-{{}}-and-v-html
    vue-learning:2
    vue-learning:0
    vue-learning:1
    【转】像素 Pixel (Picture Element)
  • 原文地址:https://www.cnblogs.com/over140/p/2759241.html
Copyright © 2011-2022 走看看