/**
*
*/
package com.video.ui.idata;
import android.content.Context;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.WebView;
import android.webkit.JavascriptInterface;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author tianli
*
*/
public class Html5PlayUrlRetriever {
public interface JSObject {
}
private static final String TAG = "html5";
private static final int URL_LOOP_INTERVAL_QIYI = 3000;
private static final int URL_LOOP_INTERVAL = 2000;
private String mSource ;
private String mPlayUrl = null;
private boolean mAutoPlay = false;
private boolean mVideoReady = false;
private boolean mReleased = false;
private LogCatMonitor mLogCat = null;
private Handler mHandler;
private PlayUrlListener mPlayUrlListener = null;
private WebView mWebView = null;
private boolean mSkipAd = false;
public Html5PlayUrlRetriever(WebView webView, String source){
init(webView, source);
}
public void setSkipAd(boolean skip){
mSkipAd = skip;
}
private int step=0;
private void init(WebView webView, String source){
mSource = source;
mWebView = webView;
Context context = webView.getContext();
mHandler = new Handler(context.getMainLooper());
mWebView.addJavascriptInterface(new H5Object(), "Methods");
mLogCat = new LogCatMonitor();
}
public synchronized void start(){
if(mSource.equals("iqiyi")){//iqiyi
mLogCat.start();
}else{
step++;
getVideoUrlLoop(2000);
Log.d(TAG, "times step:"+step + " to fetch url:"+mSource);
}
mAutoPlay = true;
}
public synchronized void startQiyiLoop(){
getVideoUrlQiyiLoop(3000);
}
private synchronized void getVideoUrlLoop(int delay) {
if(!mReleased){
Log.i(TAG, "get video url");
mHandler.removeCallbacks(mGetVideoUrlRunnale);
if(step <= 60) {
mHandler.postDelayed(mGetVideoUrlRunnale, delay);
}else {
Log.d(TAG, "not find result for 60 times");
}
}
}
private void onUrlFound(final String pageUrl, final String url){
mHandler.post(new Runnable() {
@Override
public void run() {
if(!TextUtils.isEmpty(url) && !url.equals(mPlayUrl)){
WebView webView = mWebView;
String webUrl = pageUrl;
if(TextUtils.isEmpty(webUrl)){
webUrl = webView.getUrl();
}
mPlayUrl = url;
notifyUrlReady(webUrl, mPlayUrl);
}
}
});
}
private void getVideoUrlQiyiLoop(int delay) {
if(!mReleased){
Log.i(TAG, "get video url qiyi");
mHandler.removeCallbacks(mGetVideoUrlQiyiRunnale);
mHandler.postDelayed(mGetVideoUrlQiyiRunnale, delay);
}
}
private Runnable mGetVideoUrlQiyiRunnale = new Runnable() {
@Override
public void run() {
Log.i(TAG, "get video url qiyi run...");
if(!mReleased && TextUtils.isEmpty(mPlayUrl)) {
exeJs(JS_GET_URL);
getVideoUrlQiyiLoop(URL_LOOP_INTERVAL_QIYI);
}
};
};
private Runnable mGetVideoUrlRunnale = new Runnable() {
@Override
public void run() {
Log.i(TAG, "get video url run...");
if(!mReleased && !mVideoReady && TextUtils.isEmpty(mPlayUrl)) {
exeJs(JS_GET_URL);
getVideoUrlLoop(URL_LOOP_INTERVAL);
}
};
};
public boolean isAutoPlay(){
return mAutoPlay;
}
private void exeJs(String js){
try {
mWebView.loadUrl(js);
} catch (Exception e) {
}
}
public synchronized void release(){
mReleased = true;
mVideoReady = false;
mPlayUrl = null;
setPlayUrlListener(null);
mHandler.removeCallbacks(mGetVideoUrlQiyiRunnale);
mHandler.removeCallbacks(mGetVideoUrlRunnale);
if(mSource.equals("iqiyi")){
mLogCat.interrupt();
}
Log.d(TAG, "I am just released: "+this);
}
private synchronized void notifyUrlReady(String pageUrl, String playUrl){
Log.d(TAG, "find url:"+playUrl + " this:"+this + " mReleased:"+mReleased );
if(mPlayUrlListener != null){
mPlayUrlListener.onUrlUpdate(pageUrl, playUrl);
}
}
public synchronized void setPlayUrlListener(PlayUrlListener playUrlListener) {
this.mPlayUrlListener = playUrlListener;
}
public class H5Object implements JSObject{
@JavascriptInterface
public boolean isVideoReady() {
Log.d(TAG, "isVideoReady " + mVideoReady);
return mVideoReady;
}
@JavascriptInterface
public void onVideoReady() {
Log.d(TAG, "onVideoReady.");
mVideoReady = true;
}
@JavascriptInterface
public boolean canAutoPlay(){
return true;
}
@JavascriptInterface
public boolean canSkipAd(){
return mSkipAd;
}
private String mLastUrl = null;
@JavascriptInterface
public void getUrl(final String pageUrl, final String playUrl, boolean neverAd) {
Log.d(TAG, "getUrl pageUrl = " + pageUrl + ", playUrl = " + playUrl);
if(playUrl.contains(".html")){
return;
}
if(neverAd){
onUrlFound(pageUrl, playUrl);
return;
}
if(mLastUrl != null && mLastUrl.equals(playUrl)){
return;
}
mLastUrl = playUrl;
onUrlFound(pageUrl, playUrl);
Log.d(TAG, "i am released: "+mReleased);
}
}
private class LogCatMonitor extends Thread{
@Override
public void run() {
try{
Pattern pattern = Pattern.compile("MediaPlayer.* [uU]ri is .*(http\\:.*)");
Process logProc = Runtime.getRuntime().exec("logcat -c");
logProc.waitFor();
logProc = Runtime.getRuntime().exec("logcat");
BufferedReader br = new BufferedReader(new InputStreamReader(
logProc.getInputStream()));
do{
String line = br.readLine();
Matcher matcher = pattern.matcher(line);
if(matcher.find()){
String url = matcher.group(1).trim();
matcher.group();
Log.d(TAG, "onUrlFound " + url);
onUrlFound(null, url);
break;
}
}while(!isInterrupted());
}catch(Exception e){
}
}
}
private static final String JS_GET_URL = "javascript:(function() {" +
"if(window.Methods == undefined || window.Methods.isVideoReady == undefined || window.Methods.isVideoReady()){" +
" return;" +
"}" +
"var pageUrl = window.location.href;" +
"var videoTags = document.getElementsByTagName('video');" +
"if(videoTags == null || videoTags == undefined || videoTags.length == 0){" +
"return;" +
"}" +
"window.Methods.onVideoReady();" +
"var url = videoTags[0].getAttribute('src');" +
"var sources = videoTags[0].getElementsByTagName('source');" +
"if(sources != null && sources != undefined){" +
" for(var i = 0; i < sources.length; i++){" +
" var source = sources[i].getAttribute('src');" +
" if(source != null || source != undefined || source.length > 0){" +
" url = source;" +
" break;"+
" }"+
" }"+
"}"+
"if(window.Methods != undefined && window.Methods.canAutoPlay != undefined" +
" && window.Methods.canAutoPlay()){" +
" videoTags[0].play();" +
"}" +
"if(url != null && url != undefined && url.length > 0) {" +
"var adover = null;" +
"if(videoTags != null && videoTags != undefined && videoTags.length > 0){" +
" adover = videoTags[0].getAttribute('data-adover');" +
"}" +
"if(adover == undefined || adover == null){" +
"window.Methods.getUrl(pageUrl, url, false);" +
"}else if(adover){" +
"window.Methods.getUrl(pageUrl, url, false);" +
"}" +
"}" +
"videoTags[0].addEventListener('durationchange',function() {" +
"var videoTags = document.getElementsByTagName('video');" +
"if(videoTags == null || videoTags == undefined || videoTags.length == 0){" +
" return;" +
"}" +
"var url = videoTags[0].getAttribute('src');" +
"if(window.Methods != undefined && window.Methods.canSkipAd != undefined &&" +
" window.Methods.canSkipAd()){" +
" if(videoTags[0].duration >= 5 && videoTags[0].duration <= 30){" +
" videoTags[0].currentTime = videoTags[0].duration - 1;" +
" videoTags[0].play();" +
" }" +
"}" +
"var sources = videoTags[0].getElementsByTagName('source');" +
" if(sources != null && sources != undefined){" +
" for(var i = 0; i < sources.length; i++){" +
" var source = sources[i].src;" +
" if(source != null || source != undefined || source.length > 0){" +
" url = source;" +
" break;"+
" }"+
" }"+
" }"+
"if(url == null || url == undefined || url.length == 0){" +
" return; " +
"}" +
"if(url == null || url == undefined || url.length == 0){" +
" return; " +
"}" +
"var video = document.getElementsByTagName('video');" +
"var adover = null;" +
"if(video != null && video != undefined && video.length > 0){" +
" adover = video[0].getAttribute('data-adover');" +
"}" +
"if(adover == undefined || adover == null){" +
"window.Methods.getUrl(pageUrl, url, false);" +
"}else if(adover){" +
"window.Methods.getUrl(pageUrl, url, false);" + // set false temporarily.
"}" +
"}, false); " +
// "videoTags[0].addEventListener('durationchange',function() {" +
// " var videoTags = document.getElementsByTagName('video');" +
// " if(videoTags == null || videoTags == undefined || videoTags.length == 0){" +
// " return;" +
// " }" +
// " if(videoTags[0].duration > 5 && videoTags[0].duration < 60){" +
// " videoTags[0].currentTime = videoTags[0].duration - 1;" +
// " videoTags[0].play();" +
// " }" +
// "}, false); " +
"})()";
public interface PlayUrlListener {
public void onUrlUpdate(String htmlUrl, String url);
}
}