天天看點

使用Vitamio打造自己的Android萬能播放器(11)—— 本地掃描背景服務

前言

vitamio和oplayer系列文章得到廣大同行的關注和支援,非常感謝!離系列文章的上篇有幾個月了,各種忙暫停了本系列文章,非常抱歉!離oplayer正式上線還有距離,還有很多要做的事情,繼續前行!

聲明

  歡迎轉載,但請保留文章原始出處:) 

    部落格園:http://www.cnblogs.com

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

正文

一、注意事項

注意3.0整合的适合建議使用library方式整合vitamio,否則需要反射或者使用oplayer的方法,覆寫r(參見代碼)。 

二、主要代碼:

使用Vitamio打造自己的Android萬能播放器(11)—— 本地掃描背景服務

/** 媒體掃描 */

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;

    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();

    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)) {

                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;

    public ibinder onbind(intent intent) {

        return mbinder;

}

使用Vitamio打造自己的Android萬能播放器(11)—— 本地掃描背景服務

代碼說明:

1、預設service是在主線程中運作的,掃描比較耗時,這裡啟用了一個新的線程。

2、使用了觀察者模式來通知資料變化,沒有用廣播。

3、暫時去掉了截圖,截圖報錯,還在修改。 

三、oplayer

3.1 下載下傳

請移步#taocode(svn):(沒有賬戶的請注冊一個即可)

3.2 更新

a). 資料庫層使用了ormlite架構。

b). 将掃描視訊檔案修改為背景服務,單獨起了一個線程。

c). 整合vitamio 3.0,修改反射為覆寫io.voo.vitamio.r。 

四、vitamio

已建立vitamio開發者聯盟官方qq群!群号為:246969281

注意:目前僅接受已經開發基于vitamio産品的開發者申請加入,申請理由請填寫産品的名稱和連結!

五、八卦

想在這裡澄清一下oplayer與vplayer、vitamio的關系:

1、oplayer這個項目是跟公司沒有關系,純屬于個人業餘愛好作品。

2、oplayer使用的是vitamio,但不會比大家優先擷取vitamio的新版本。

3、oplayer非官方示例。

結束

 更加深刻體會“堅持就是勝利”這句話的意義。

轉載:http://www.cnblogs.com/over140/archive/2012/11/07/2759241.html