package com.trans.music.search;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MusicUtil {
static Pattern PATTERN_ROW = Pattern.compile("<tr(.*?)</tr>", Pattern.DOTALL);
static Pattern PATTERN = Pattern.compile(
"<td.*?\\btitle=\"([^\"]*)\".*?" + // 1
"<td.*?\\bsinger=\"([^\"]*)\".*?" + // 2
"<td.*?\\btitle=\"([^\"]*)\".*?" + // 3
"<td.*?</td>.*?" + // Ignore
"<td.*?\'(/down.so.*?)\'.*?" + // 4
// TODO(zyu): In some cases, lyrics are empty. Temporily ignore lyrics.
// "<td.*?href=\"([^\"]*)\".*?" + // 5
"<td>(.*?)</td>.*?" + // 5
"<td.*?</td>.*?" + // Ignore
"<td.*?>([^<]*)<.*?" + // 6
"<td.*?>([^<]*)<.*?" + // 7
"<td.*?spdbar([0-9]?)\".*?"
, Pattern.DOTALL);
private static final Pattern PATTERN_DOWNLOAD_URL = Pattern.compile("href=\"([^\"]*)\"");
private static final String DOWNLOAD_MARKER = "下载歌曲";
//public static final String //SogouSearchBase = "http://mp3.sogou.com/music.so?pf=mp3&as=&st=&ac=1&w=02009900&query=";
//http://mp3.sogou.com/music.so?pf=&as=&st=&ac=1&w=02009900&query=
public static final String SogouSearchBase = "http://mp3.sogou.com/music.so?pf=mp3&query=";
//private static final String URL_SEARCH_PROXY = "http://feebe.appspot.com/msearch/music.so?pf=mp3&query=";
public static String getSogouLinks(String key) {
String reqString = null;
try {
reqString = URLEncoder.encode(key, "GB2312");
} catch (UnsupportedEncodingException e) {
reqString = URLEncoder.encode(key);
} finally {
//Log.e("search url:", SogouSearchBase + reqString);
return SogouSearchBase + reqString;
}
}
private static boolean sUseProxy = false;
public static String getSogouLinks(String url, int page) {
return url + "&page=" + page;
}
private static String sCookie;
public static SharedPreferences mSetting;
public static void setStingKey(String key, String value) {
if (mSetting == null) {
return;
}
Editor e = mSetting.edit();
e.putString(key, value);
e.commit();
}
private static void setConnectionString(HttpURLConnection urlConn) {
urlConn.setRequestProperty("User-Agent",
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.0.8) Gecko/2009032608 Firefox/3.0.8 GTB6 ");
urlConn.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
urlConn.setRequestProperty("Accept-Language", "en-us,en;q=0.5");
//Accept-Encoding: gzip,deflate
urlConn.setRequestProperty("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
urlConn.setRequestProperty("Keep-Alive", "300");
urlConn.setRequestProperty("Connection", "keep-alive");
if (sCookie == null) {
if (mSetting != null) {
sCookie = mSetting.getString("cookie", null);
}
}
if (sCookie != null) {
urlConn.setRequestProperty("Cookie", sCookie);
}
}
//Used to signal between threads.
static class Signal {
public boolean ready;
};
static class HtmlData {
public String content;
};
static class MyJavaScriptInterface {
Signal mSignal;
HtmlData mData;
public MyJavaScriptInterface(Signal s, HtmlData data) {
this.mSignal = s;
this.mData = data;
}
@SuppressWarnings("unused")
public void parseHtml(String html) {
mData.content = html;
mSignal.ready = true;
synchronized(mSignal) {
mSignal.notify();
}
}
}
private static class FetchSearchPage extends WebViewClient {
@Override
public void onPageFinished(WebView view, String url) {
view.loadUrl("javascript:window.HTMLOUT.parseHtml(document.getElementsByTagName('html')[0].innerHTML);");
}
}
private static boolean loadUrl(final Context context, final String url, final HtmlData data) {
final Signal s = new Signal();
s.ready = false;
Const.sHandler.post(new Runnable() {
@Override
public void run() {
WebView web = new WebView(context);
web.getSettings().setJavaScriptEnabled(true);
web.getSettings().setLoadsImagesAutomatically(false);
web.getSettings().setBlockNetworkImage(true);
web.addJavascriptInterface(new MyJavaScriptInterface(s, data), "HTMLOUT");
web.setWebViewClient(new FetchSearchPage());
web.loadUrl(url);
}
});
synchronized(s) {
while (!s.ready) {
try {
s.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
}
return true;
}
}
public static ArrayList<MP3Info> getSogoMp3(Context context, String urlStr, int limit) {
ArrayList<MP3Info> songs = new ArrayList<MP3Info>();
HtmlData data = new HtmlData();
if (!loadUrl(context, urlStr, data))
return null;
if (TextUtils.isEmpty(data.content))
return null;
try {
Matcher matcherRow = PATTERN_ROW.matcher(data.content);
while (matcherRow.find()) {
Matcher m = PATTERN.matcher(matcherRow.group(1));
while (m.find()) {
MP3Info info = new MP3Info();
info.setName(m.group(1).trim());
info.setArtist(URLDecoder.decode(m.group(2), "gb2312").trim());
info.setAlbum(m.group(3).trim());
info.addLink(m.group(4).trim());
info.setFSize(String.valueOf(sizeFromStr(m.group(6).trim())));
info.setSpeed(m.group(8).trim());
songs.add(info);
}
}
} catch (IOException e) {
// ShowToastMessage("Network can not connect, please try again.");
Log.e("getSogoMp3Once", e.getMessage());
return null;
}
if (songs != null) {
//Log.e(TAG, "song size: " + songs.size());
}
return songs;
}
public static long sizeFromStr(String sizeStr) {
if (TextUtils.isEmpty(sizeStr)) {
return 0;
} else {
if (sizeStr.endsWith("K") ||
sizeStr.endsWith("k")) {
return (long) (1024 * Float.valueOf(sizeStr.substring(0, sizeStr.length() - 1)));
} else if (sizeStr.endsWith("M") ||
sizeStr.endsWith("m")) {
return (long) (1024 * 1024 * Float.valueOf(sizeStr.substring(0, sizeStr.length() - 1)));
} else {
try {
return Long.valueOf(sizeStr);
} catch (java.lang.NumberFormatException e) {
e.printStackTrace();
return 0;
}
}
}
}
public static int sizeInM(String sizeStr) {
if (TextUtils.isEmpty(sizeStr)) {
return 0;
}
int size = 0;
try {
size = Integer.parseInt(sizeStr) / (1024 * 1024);
} catch (NumberFormatException e) {
return 0;
}
return size;
}
// Given the link to each individual mp3, get the corresponding link by which we can actually download the music.
public static String getLink(Context context, String req) throws IOException{
String request = "http://mp3.sogou.com" +req;
Log.e("get download link: ", request);
// URL url = new URL(request);
HtmlData data = new HtmlData();
if (!loadUrl(context, request, data))
return null;
if (TextUtils.isEmpty(data.content))
return null;
int start = data.content.indexOf(DOWNLOAD_MARKER) + DOWNLOAD_MARKER.length();
Matcher m = PATTERN_DOWNLOAD_URL.matcher(data.content.substring(start));
if (m.find()) {
return m.group(1);
}
// HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();
// setConnectionString(urlConn);
// urlConn.setConnectTimeout(20000);
// urlConn.connect();
//
// InputStream stream = urlConn.getInputStream();
//
// StringBuilder builder = new StringBuilder(8 * 1024);
//
// char[] buff = new char[4096];
// //必须在此指定编码,否则后面toString会导致乱码
// InputStreamReader is = new InputStreamReader(stream);
//
// int len;
// while ((len = is.read(buff, 0, 4096)) > 0) {
// builder.append(buff, 0, len);
// }
// urlConn.disconnect();
// String httpresponse = builder.toString();
// int linkStartPos = data.content.indexOf("\" href=\"") + "\" href=\"".length();
// if (linkStartPos > 0) {
// int linkEndPos = data.content.indexOf('>', linkStartPos)-1;Log.e("@@@@@@@@@@@@@@data.content", data.content.substring(linkStartPos, linkEndPos));
// if (linkEndPos > 0)
// return data.content.substring(linkStartPos, linkEndPos);
// }
return null;
}
}