Android Open Source - netmbuddy Y T Search Helper






From Project

Back to project page netmbuddy.

License

The source code is released under:

------- Default ------- Copyright (C) 2012, 2013, 2014 Younghyung Cho. <yhcting77@gmail.com> All rights reserved. This file is part of NetMBuddy This program is licensed under the FreeBSD license R...

If you think the Android project netmbuddy listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/******************************************************************************
 * Copyright (C) 2012, 2013, 2014/* w  ww.  java 2s.  c o m*/
 * Younghyung Cho. <yhcting77@gmail.com>
 * All rights reserved.
 *
 * This file is part of NetMBuddy
 *
 * This program is licensed under the FreeBSD license
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * The views and conclusions contained in the software and documentation
 * are those of the authors and should not be interpreted as representing
 * official policies, either expressed or implied, of the FreeBSD Project.
 *****************************************************************************/

package free.yhc.netmbuddy.model;

import static free.yhc.netmbuddy.utils.Utils.eAssert;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import free.yhc.netmbuddy.utils.ImageUtils;
import free.yhc.netmbuddy.utils.Utils;

public class YTSearchHelper {
    private static final boolean DBG = false;
    private static final Utils.Logger P = new Utils.Logger(YTSearchHelper.class);

    private static final int MSG_WHAT_OPEN                  = 0;
    private static final int MSG_WHAT_CLOSE                 = 1;
    private static final int MSG_WHAT_SEARCH                = 2;
    private static final int MSG_WHAT_LOAD_THUMBNAIL        = 3;

    private BGHandler                   mBgHandler      = null;
    private SearchDoneReceiver          mSearchRcvr     = null;
    private LoadThumbnailDoneReceiver   mThumbnailRcvr  = null;

    public interface SearchDoneReceiver {
        void searchDone(YTSearchHelper helper, SearchArg arg,
                        YTFeed.Result result, Err err);
    }

    public interface LoadThumbnailDoneReceiver {
        void loadThumbnailDone(YTSearchHelper helper, LoadThumbnailArg arg,
                               Bitmap bm, Err err);
    }

    public static enum Err {
        NO_ERR,
        IO_NET,
        INTERRUPTED,
        NETWORK_UNAVAILABLE,
        PARAMETER,
        FEED_FORMAT,
        BAD_REQUEST,
        UNKNOWN
    }

    public static enum SearchType {
        VID_KEYWORD,
        VID_AUTHOR,
        VID_PLAYLIST,
        PL_USER
    }

    public static class SearchArg {
        public Object       tag;   // user data tag
        public SearchType   type;
        public String       text;  //
        public String       title; // title of this search.
        public int          starti;// start index
        public int          max;   // max size to search
        public SearchArg(Object aTag,
                         SearchType aType, String aText, String aTitle,
                         int aStarti, int aMax) {
            tag = aTag;
            type = aType;
            text = aText;
            title = aTitle;
            starti = aStarti;
            max = aMax;
        }
    }

    public static class LoadThumbnailArg {
        public Object   tag;
        public String   url;
        public int      width;
        public int      height;
        public LoadThumbnailArg(Object aTag, String aUrl,
                                int aWidth, int aHeight) {
            tag = aTag;
            url = aUrl;
            width = aWidth;
            height = aHeight;
        }
    }

    public static class SearchReturn {
        public YTFeed.Result   r;
        public Err             err;
        SearchReturn(YTFeed.Result aR, Err aErr) {
            r = aR;
            err = aErr;
        }
    }

    public static class LoadThumbnailReturn {
        public Bitmap  bm;
        public Err     err;
        LoadThumbnailReturn(Bitmap aBm, Err aErr) {
            bm = aBm;
            err = aErr;
        }
    }

    private static enum FeedType {
        VIDEO,
        PLAYLIST
    }

    private static class BGThread extends HandlerThread {
        private BGHandler mHandler = null;
        BGThread() {
            super("YTSearchHelper.BGThread",Process.THREAD_PRIORITY_BACKGROUND);
        }

        void
        setBgHandler(BGHandler handler) {
            mHandler = handler;
        }

        @Override
        protected void
        onLooperPrepared() {
            super.onLooperPrepared();
        }

        @Override
        public void
        run() {
            try {
                super.run();
            } catch (Exception ignored) {
            } finally {
                if (null != mHandler)
                    mHandler.cleanupPostClose();
            }
        }
    }

    private static class BGHandler extends Handler {
        private final YTSearchHelper        _mHelper;

        private MultiThreadRunner           _mMtrunner      = null;
        private SearchDoneReceiver          _mSearchRcvr    = null;
        private LoadThumbnailDoneReceiver   _mThumbnailRcvr = null;
        private boolean                     _mClosed        = false;

        BGHandler(Looper looper, YTSearchHelper helper) {
            super(looper);
            _mHelper = helper;
        }

        private void
        sendFeedDone(final SearchArg arg, final YTFeed.Result res, final Err err) {
            Utils.getUiHandler().post(new Runnable() {
                @Override
                public void
                run() {
                    if (!_mClosed && null != _mSearchRcvr)
                        _mSearchRcvr.searchDone(_mHelper, arg, res, err);
                }
            });
            return;
        }

        private void
        sendLoadThumbnailDone(final LoadThumbnailArg arg, final Bitmap bm, final Err err) {
            Utils.getUiHandler().post(new Runnable() {
                @Override
                public void
                run() {
                    if (!_mClosed && null != _mThumbnailRcvr)
                        _mThumbnailRcvr.loadThumbnailDone(_mHelper, arg, bm, err);
                }
            });
            return;
        }

        /**
         * This function will be called end of 'run()' function in HandlerThread.
         */
        void
        cleanupPostClose() {
            if (null != _mMtrunner) {
                _mMtrunner.cancel();
                _mMtrunner = null;
            }
        }

        void
        close(boolean interrupt) {
            if (_mClosed)
                return; // already closed.

            removeMessages(MSG_WHAT_OPEN);
            removeMessages(MSG_WHAT_SEARCH);
            removeMessages(MSG_WHAT_LOAD_THUMBNAIL);
            _mSearchRcvr = null;
            _mThumbnailRcvr = null;
            if (interrupt) {
                _mClosed = true;
                getLooper().getThread().interrupt();
                ((HandlerThread)getLooper().getThread()).quit();
                return;
            } else
                sendEmptyMessage(MSG_WHAT_CLOSE);
        }

        void
        setSearchDoneRecevier(SearchDoneReceiver receiver) {
            _mSearchRcvr = receiver;
        }

        void
        setLoadThumbnailDoneRecevier(LoadThumbnailDoneReceiver receiver) {
            _mThumbnailRcvr = receiver;
        }

        @Override
        public void
        handleMessage(final Message msg) {
            if (_mClosed)
                return;

            switch (msg.what) {
            case MSG_WHAT_OPEN: {
                eAssert(null == _mMtrunner);
                _mMtrunner = new MultiThreadRunner(this,
                                                   Policy.YTSEARCH_MAX_LOAD_THUMBNAIL_THREAD);
            } break;

            case MSG_WHAT_CLOSE: {
                _mClosed = true;
                ((HandlerThread)getLooper().getThread()).quit();
            } break;

            case MSG_WHAT_SEARCH: {
                SearchArg arg = (SearchArg)msg.obj;
                SearchReturn r = doSearch(arg);
                sendFeedDone(arg, r.r, r.err);
            } break;

            case MSG_WHAT_LOAD_THUMBNAIL: {
                final LoadThumbnailArg arg = (LoadThumbnailArg)msg.obj;
                MultiThreadRunner.Job<Integer> job
                    = new MultiThreadRunner.Job<Integer>(true, 0) {
                    @Override
                    public Integer
                    doJob() {
                        LoadThumbnailReturn r = null;
                        try {
                            r = doLoadThumbnail(arg);
                        } finally {
                            if (null == r)
                                sendLoadThumbnailDone(arg, null, YTSearchHelper.Err.UNKNOWN);
                            else
                                sendLoadThumbnailDone(arg, r.bm, r.err);
                        }
                        return 0;
                    }
                };
                _mMtrunner.appendJob(job);
            } break;
            }
        }
    }

    private static Err
    map(NetLoader.Err err, Object extra) {
        switch (err) {
        case IO_NET:
            return Err.IO_NET;
        case HTTPGET:
            if (!(extra instanceof Integer))
                return Err.IO_NET;

            int stcode = (Integer)extra;
            switch (stcode) {
            case HttpUtils.SC_BAD_REQUEST:
                return Err.BAD_REQUEST;

            case HttpUtils.SC_NOT_FOUND:
                return Err.PARAMETER;

            default:
                return Err.IO_NET;
            }

        case INTERRUPTED:
            return Err.INTERRUPTED;

        case NO_ERR:
            eAssert(false);

        default:
            return Err.UNKNOWN;
        }
    }

    private static LoadThumbnailReturn
    doLoadThumbnail(LoadThumbnailArg arg) {
        Bitmap bm;
        try {
            bm = ImageUtils.decodeImage(loadUrl(arg.url), arg.width, arg.height);
        } catch (NetLoader.LocalException e) {
            eAssert(NetLoader.Err.NO_ERR != e.error());
            return new LoadThumbnailReturn(null, map(e.error(), e.extra()));
        } catch (IOException e) {
            return new LoadThumbnailReturn(null, Err.UNKNOWN);
        }
        return new LoadThumbnailReturn(bm, Err.NO_ERR);
    }

    private static byte[]
    loadUrl(String urlStr) throws NetLoader.LocalException, IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        Uri uri = Uri.parse(urlStr);
        NetLoader loader = new NetLoader().open(null);
        loader.readHttpData(baos, uri);
        loader.close();

        byte[] data = baos.toByteArray();
        baos.close();
        return data;
    }

    private static YTFeed.Result
    parse(byte[] xmlData, FeedType type) throws
        IOException, SAXException, ParserConfigurationException {
        Document dom = DocumentBuilderFactory.newInstance()
                                             .newDocumentBuilder()
                                             .parse(new ByteArrayInputStream(xmlData));

        switch (type) {
        case VIDEO:
            return YTVideoFeed.parseFeed(dom);

        case PLAYLIST:
            return YTPlaylistFeed.parseFeed(dom);

        default:
            eAssert(false);
        }
        return null;
    }

    private static SearchReturn
    doSearch(SearchArg arg) {
        YTFeed.Result r = null;
        try {
            switch (arg.type) {
            case VID_KEYWORD:
                r = parse(loadUrl(YTVideoFeed.getFeedUrlByKeyword(arg.text, arg.starti, arg.max)),
                          FeedType.VIDEO);
                break;

            case VID_AUTHOR:
                r = parse(loadUrl(YTVideoFeed.getFeedUrlByAuthor(arg.text, arg.starti, arg.max)),
                          FeedType.VIDEO);
                break;

            case VID_PLAYLIST:
                r = parse(loadUrl(YTVideoFeed.getFeedUrlByPlaylist(arg.text, arg.starti, arg.max)),
                          FeedType.VIDEO);
                break;

            case PL_USER:
                r = parse(loadUrl(YTPlaylistFeed.getFeedUrlByUser(arg.text, arg.starti, arg.max)),
                          FeedType.PLAYLIST);
                break;

            default:
                eAssert(false);
            }
        } catch (IOException e) {
            if (DBG) P.w("DOM IO error!");
            return new SearchReturn(null, Err.IO_NET);
        } catch (SAXException e) {
            if (DBG) P.w("Parse unexpected format!");
            return new SearchReturn(null, Err.FEED_FORMAT);
        } catch (ParserConfigurationException pe) {
            if (DBG) P.w("Parse cofiguration exception!");
            return new SearchReturn(null, Err.UNKNOWN);
        } catch (NetLoader.LocalException e) {
            eAssert(NetLoader.Err.NO_ERR != e.error());
            Object extra = e.extra();
            Err reterr = map(e.error(), extra);


            return new SearchReturn(null, reterr);
        }
        return new SearchReturn(r, Err.NO_ERR);
    }

    /**
     * Thread safe
     * @param arg
     * @return
     */
    public static SearchReturn
    search(SearchArg arg) {
        if (!Utils.isNetworkAvailable())
            return new SearchReturn(null, Err.NETWORK_UNAVAILABLE);
        return doSearch(arg);
    }

    /**
     * Thread safe
     * @param arg
     * @return
     */
    public static LoadThumbnailReturn
    loadThumbnail(LoadThumbnailArg arg) {
        if (!Utils.isNetworkAvailable())
            return new LoadThumbnailReturn(null, Err.NETWORK_UNAVAILABLE);
        return doLoadThumbnail(arg);
    }

    public YTSearchHelper() {
    }

    public void
    setSearchDoneRecevier(SearchDoneReceiver receiver) {
        mSearchRcvr = receiver;
        if (null != mBgHandler)
            mBgHandler.setSearchDoneRecevier(receiver);
    }

    public void
    setLoadThumbnailDoneRecevier(LoadThumbnailDoneReceiver receiver) {
        mThumbnailRcvr = receiver;
        if (null != mBgHandler)
            mBgHandler.setLoadThumbnailDoneRecevier(receiver);
    }

    public void
    loadThumbnailAsync(LoadThumbnailArg arg) {
        if (null == mBgHandler)
            return;

        Message msg = mBgHandler.obtainMessage(MSG_WHAT_LOAD_THUMBNAIL, arg);
        mBgHandler.sendMessage(msg);
    }

    public Err
    searchAsync(SearchArg arg) {
        eAssert(0 < arg.starti && 0 < arg.max && arg.max <= Policy.YTSEARCH_MAX_RESULTS);
        if (Utils.isNetworkAvailable()) {
            Message msg = mBgHandler.obtainMessage(MSG_WHAT_SEARCH, arg);
            mBgHandler.sendMessage(msg);
            return Err.NO_ERR;
        }
        return Err.NETWORK_UNAVAILABLE;
    }

    public void
    open() {
        BGThread hThread = new BGThread();
        hThread.start();
        mBgHandler = new BGHandler(hThread.getLooper(), this);
        hThread.setBgHandler(mBgHandler);
        mBgHandler.sendEmptyMessage(MSG_WHAT_OPEN);
        mBgHandler.setSearchDoneRecevier(mSearchRcvr);
        mBgHandler.setLoadThumbnailDoneRecevier(mThumbnailRcvr);
    }

    public void
    close(boolean interrupt) {
        // TODO
        // Stop running thread!
        // Need to check that below code works as expected perfectly.
        // "interrupting thread" is quite annoying and unpredictable job!
        if (null != mBgHandler) {
            mBgHandler.close(interrupt);
            mBgHandler = null;
        }
    }
}




Java Source Code List

free.yhc.netmbuddy.DiagAsyncTask.java
free.yhc.netmbuddy.Err.java
free.yhc.netmbuddy.FragmentPagerAdapterEx.java
free.yhc.netmbuddy.ImportShareActivity.java
free.yhc.netmbuddy.ImportShareContentActivity.java
free.yhc.netmbuddy.ImportShareFileActivity.java
free.yhc.netmbuddy.LockScreenActivity.java
free.yhc.netmbuddy.MusicsActivity.java
free.yhc.netmbuddy.MusicsAdapter.java
free.yhc.netmbuddy.PlaylistActivity.java
free.yhc.netmbuddy.PlaylistAdapter.java
free.yhc.netmbuddy.VideoPlayerActivity.java
free.yhc.netmbuddy.YTMPActivity.java
free.yhc.netmbuddy.YTMPApp.java
free.yhc.netmbuddy.YTMPPreferenceActivity.java
free.yhc.netmbuddy.YTPlaylistSearchActivity.java
free.yhc.netmbuddy.YTPlaylistSearchAdapter.java
free.yhc.netmbuddy.YTPlaylistSearchFragment.java
free.yhc.netmbuddy.YTSearchActivity.java
free.yhc.netmbuddy.YTSearchAdapter.java
free.yhc.netmbuddy.YTSearchFragment.java
free.yhc.netmbuddy.YTSearchPagerAdapter.java
free.yhc.netmbuddy.YTVideoSearchActivity.java
free.yhc.netmbuddy.YTVideoSearchAdapter.java
free.yhc.netmbuddy.YTVideoSearchAuthorActivity.java
free.yhc.netmbuddy.YTVideoSearchFragment.java
free.yhc.netmbuddy.YTVideoSearchKeywordActivity.java
free.yhc.netmbuddy.YTVideoSearchPlaylistActivity.java
free.yhc.netmbuddy.db.ColPlaylist.java
free.yhc.netmbuddy.db.ColVideoRef.java
free.yhc.netmbuddy.db.ColVideo.java
free.yhc.netmbuddy.db.DBHelper.java
free.yhc.netmbuddy.db.DBHistory.java
free.yhc.netmbuddy.db.DBManager.java
free.yhc.netmbuddy.db.DBUpgrader.java
free.yhc.netmbuddy.db.DBUtils.java
free.yhc.netmbuddy.db.DB.java
free.yhc.netmbuddy.model.AtomicFloat.java
free.yhc.netmbuddy.model.BGTask.java
free.yhc.netmbuddy.model.HttpUtils.java
free.yhc.netmbuddy.model.KBLinkedList.java
free.yhc.netmbuddy.model.MultiThreadRunner.java
free.yhc.netmbuddy.model.NetLoader.java
free.yhc.netmbuddy.model.NotiManager.java
free.yhc.netmbuddy.model.Policy.java
free.yhc.netmbuddy.model.RTState.java
free.yhc.netmbuddy.model.SearchSuggestionProvider.java
free.yhc.netmbuddy.model.UnexpectedExceptionHandler.java
free.yhc.netmbuddy.model.YTConstants.java
free.yhc.netmbuddy.model.YTDownloader.java
free.yhc.netmbuddy.model.YTFeed.java
free.yhc.netmbuddy.model.YTHacker.java
free.yhc.netmbuddy.model.YTPlayerLifeSupportService.java
free.yhc.netmbuddy.model.YTPlayerUI.java
free.yhc.netmbuddy.model.YTPlayerVideoListAdapter.java
free.yhc.netmbuddy.model.YTPlayerVideoListManager.java
free.yhc.netmbuddy.model.YTPlayer.java
free.yhc.netmbuddy.model.YTPlaylistFeed.java
free.yhc.netmbuddy.model.YTSearchHelper.java
free.yhc.netmbuddy.model.YTVideoFeed.java
free.yhc.netmbuddy.scmp.DNLoop.java
free.yhc.netmbuddy.scmp.SCElemChar.java
free.yhc.netmbuddy.scmp.SCElemI.java
free.yhc.netmbuddy.scmp.SCElemSStr.java
free.yhc.netmbuddy.scmp.SCElemSTok.java
free.yhc.netmbuddy.scmp.SCElemTok.java
free.yhc.netmbuddy.scmp.SCElem.java
free.yhc.netmbuddy.scmp.SCmpPolicy.java
free.yhc.netmbuddy.scmp.SCmp.java
free.yhc.netmbuddy.share.ExporterPlaylist.java
free.yhc.netmbuddy.share.ImporterPlaylist.java
free.yhc.netmbuddy.share.Importer.java
free.yhc.netmbuddy.share.Json.java
free.yhc.netmbuddy.share.Share.java
free.yhc.netmbuddy.utils.BookmarkListAdapter.java
free.yhc.netmbuddy.utils.FileUtils.java
free.yhc.netmbuddy.utils.ImageUtils.java
free.yhc.netmbuddy.utils.ReportUtils.java
free.yhc.netmbuddy.utils.SimilarTitlesListAdapter.java
free.yhc.netmbuddy.utils.UiUtils.java
free.yhc.netmbuddy.utils.Utils.java
free.yhc.netmbuddy.utils.YTUtils.java