實現功能:
實現網絡音樂歌詞下載功能(下載音樂的同時,下載對應歌詞)
下載好的歌詞目前不在播放器內,可以通過文件瀏覽器查看。
后續將博文,將實現本地音樂歌詞下載和已下載音樂掃描功能。
因為,沒有自己的服務器,所以網絡音樂所有相關功能(包含搜索音樂、下載音樂、下載歌詞)均無法保證時效性,建議,盡快下載和練習;如果你下載時候,已經因為我采集的服務器更改規則,請給我留言,如果可以解決,我將在有空的時候獻上新的源碼。
實現效果如圖:



實現代碼如下:
DownloadUtils如下:
package com.iwanghang.drmplayer.utils;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import com.iwanghang.drmplayer.vo.SearchResult;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.xml.parsers.ParserConfigurationException;
/**
* Created by iwanghang on 16/5/3.
* 網絡音樂下載工具類
*/
public class DownloadUtils {
private static final String DOWNLOAD_URL = "/download?_o=%2Fsearch%2Fsong";
private static final int SUCCESS_LRC = 1;//下載歌詞成功
private static final int FAILED_LRC = 2;//下載歌詞失敗
private static final int SUCCESS_MP3 = 3;//下載歌曲成功
private static final int FAILED_MP3 = 4;//下載歌曲失敗
private static final int GET_MP3_URL = 5;//獲取音樂下載地址成功
private static final int GET_FAILED_MP3_URL = 6;//獲取音樂下載地址失敗
private static final int MUSIC_EXISTS = 7;//下載時,音樂已存在
private static DownloadUtils sInstance;
private OnDownloadListener mListener;
private ExecutorService mThreadPool;
/**
*設置回調監聽器對象
* @param mListener
* @return
*/
public DownloadUtils setListener(OnDownloadListener mListener){
this.mListener = mListener;
return this;
}
//獲取下載工具的實例
public synchronized static DownloadUtils getsInstance(){
if (sInstance == null){
try {
sInstance = new DownloadUtils();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
return sInstance;
}
/**
* 下載的具體業務方法
* @throws ParserConfigurationException
*/
private DownloadUtils() throws ParserConfigurationException{
mThreadPool = Executors.newSingleThreadExecutor();
}
public void download(final SearchResult searchResult){
final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case SUCCESS_LRC:
if (mListener != null) mListener.onDowload("歌詞下載成功");
break;
case FAILED_LRC:
if (mListener != null) mListener.onFailed("歌詞下載失敗");
break;
case GET_MP3_URL:
System.out.println("GET_MP3_URL:"+msg.obj);
downloadMusic(searchResult,(String)msg.obj,this);
break;
case GET_FAILED_MP3_URL:
if (mListener != null) mListener.onFailed("下載失敗,該歌曲為收費或VIP類型");
break;
case SUCCESS_MP3:
if (mListener != null) mListener.onDowload(searchResult.getMusicName()+"已經下載");
String url = Constant.MIGU_URL + searchResult.getUrl();
System.out.println("download lrc:"+url);
downloadLRC(url,searchResult.getMusicName(),searchResult.getArtist(),this);
break;
case FAILED_MP3:
if (mListener != null) mListener.onFailed(searchResult.getMusicName()+"下載失敗");
break;
case MUSIC_EXISTS:
if (mListener != null) mListener.onFailed("音樂已存在");
break;
}
}
};
getDownloadMusicURL(searchResult,handler);
}
//獲取下載歌詞的URL
private void getDownloadLrcURL(final SearchResult searchResult, final Handler handler) {
mThreadPool.execute(new Runnable() {
@Override
public void run() {
//http://music.baidu.com/search/lrc?key=%E6%9C%89%E5%BF%83%E4%BA%BA%20G.E.M.%E9%82%93%E7%B4%AB%E6%A3%8B
//"http://music.baidu.com/search/lrc?key=" + 歌名 + " " + 歌手
//System.out.println("searchResult.getUrl() = " + searchResult.getUrl());
//String[] aa = searchResult.getUrl().split("/");
//String sn = aa[5];
//System.out.println("歌曲編號 = " + sn);
//從瀏覽器復制出來的Url是這樣的,"http://music.baidu.com/search?key=%E6%B2%A1%E6%9C%89";
//漢字經過utf8編碼,比如 冰雨 == %E5%86%B0%E9%9B%A8;
//經過測試 獲取頁面 使用"http://music.baidu.com/search?key=冰雨";無法打開正確連接
//比如使用URLEncoder.encode轉碼,轉為utf8
//實際使用 獲取頁面 使用"http://music.baidu.com/search?key=%E6%B2%A1%E6%9C%89";
try {
String musicName = URLEncoder.encode(searchResult.getMusicName(), "utf8");
String artistName = URLEncoder.encode(searchResult.getArtist(), "utf8");
//String url = Constant.BAIDU_LRC_SEARCH_HEAD + searchResult.getMusicName() + " " + searchResult.getArtist();
String url = Constant.BAIDU_LRC_SEARCH_HEAD + musicName + "+" + artistName;
System.out.println("歌詞下載頁面url = " + url);
Document doc = Jsoup.connect(url).userAgent(Constant.USER_AGENT).timeout(6000).get();
//System.out.println("歌詞下載頁面 doc : " + doc);
Elements lrcUrls = doc.select("span.lyric-action");
System.out.println(lrcUrls);
for (int i=0;i下載LRC歌詞
if (urla.indexOf("'href':'")>0){
String[] uu = urla.split("'href':'");
System.out.println("uu1 : " + uu[1]);
//uu1 : /data2/lrc/14488216/14488216.lrc' }" href="#">下載LRC歌詞
String[] uuu = uu[1].split(".lrc");
System.out.println("uuu0 : " + uuu[0]);
//uuu0 : /data2/lrc/14488216/14488216
String result = "http://music.baidu.com" + uuu[0] + ".lrc";
System.out.println("result : " + result);
//result : http://music.baidu.com/data2/lrc/14488216/14488216.lrc
Message msg = handler.obtainMessage(SUCCESS_LRC,result);
msg.sendToTarget();
break;
}
}
}
} catch (IOException e) {
e.printStackTrace();
handler.obtainMessage(FAILED_LRC).sendToTarget();
}
}
});
}
//獲取下載音樂的URL
private void getDownloadMusicURL(final SearchResult searchResult, final Handler handler) {
mThreadPool.execute(new Runnable() {
@Override
public void run() {
//http://music.migu.cn/#/album/1003215276
//1003215279
//http://music.migu.cn/order/1003215279/down/self/P2Z3Y12L1N2/3/001002A/1003215279
System.out.println("searchResult.getUrl() = " + searchResult.getUrl());
String[] aa = searchResult.getUrl().split("/");
String sn = aa[5];
System.out.println("歌曲編號 = " + sn);
String url = Constant.MIGU_DOWN_HEAD + sn + Constant.MIGU_DOWN_FOOT;
System.out.println("歌曲下載頁面url = " + url);
try {
Document doc = Jsoup.connect(url).userAgent(Constant.USER_AGENT).timeout(6000).get();
//System.out.println(doc);
System.out.println("doc.toString() = " + doc.toString());
String[] bb = doc.toString().split("song");//把 下載頁面源碼 按照"song"分割
for (int i=0;i0){
System.out.println("mp3?msisdn = " + bb[i]);
String initMp3Url = bb[i];//initMp3Url 初始Mp3下載鏈接,如下
//mp3?msisdn = ":"http://tyst.migu.cn/public/ringmaker01/10月31日中文延期/文件/全套格式/9000首/全曲試聽/Mp3_128_44_16/一起走過的日子-劉德華.mp3?msisdn\u003d7b609763f0ff","
String[] arrayHttp = initMp3Url.split("http");//把 初始Mp3下載鏈接 按照"http"分割
String[] arrayMp3 = arrayHttp[1].split(".mp3");//把 arrayHttp 按照".mp3"分割
String result = "http" + arrayMp3[0] + ".mp3";//把分割去掉的"http"和".mp3",組合回來
System.out.println("result");
//String result = "http://tyst.migu.cn/public/ringmaker01/10月31日中文延期/文件/全套格式/9000首/全曲試聽/Mp3_128_44_16/一起走過的日子-劉德華.mp3";
Message msg = handler.obtainMessage(GET_MP3_URL,result);
msg.sendToTarget();
}
}
} catch (IOException e) {
e.printStackTrace();
handler.obtainMessage(GET_FAILED_MP3_URL).sendToTarget();
}
}
});
}
//下載歌詞
private void downloadLRC(final String url, final String musicName, final String artistName,final Handler handler){
mThreadPool.execute(new Runnable() {
@Override
public void run() {
//從瀏覽器復制出來的Url是這樣的,"http://music.baidu.com/search?key=%E6%B2%A1%E6%9C%89";
//漢字經過utf8編碼,比如 冰雨 == %E5%86%B0%E9%9B%A8;
//經過測試 獲取頁面 使用"http://music.baidu.com/search?key=冰雨";無法打開正確連接
//比如使用URLEncoder.encode轉碼,轉為utf8
//實際使用 獲取頁面 使用"http://music.baidu.com/search?key=%E6%B2%A1%E6%9C%89";
try {
String musicNameEn = URLEncoder.encode(musicName, "utf8");
String artistNameEn = URLEncoder.encode(artistName, "utf8");
//String url = Constant.BAIDU_LRC_SEARCH_HEAD + searchResult.getMusicName() + " " + searchResult.getArtist();
String url = Constant.BAIDU_LRC_SEARCH_HEAD + musicNameEn + "+" + artistNameEn;
System.out.println("歌詞下載頁面url = " + url);
Document doc = Jsoup.connect(url).userAgent(Constant.USER_AGENT).timeout(6000).get();
//System.out.println("歌詞下載頁面 doc : " + doc);
Elements lrcUrls = doc.select("span.lyric-action");
System.out.println(lrcUrls);
for (int i = 0; i < lrcUrls.size(); i++) {
Elements urlsa = lrcUrls.get(i).getElementsByTag("a");
System.out.println("tag a urlsa : " + urlsa);
for (int a = 0; a < urlsa.size(); a++) {
//System.out.println("----" + urlsa.get(a).toString());
String urla = urlsa.get(a).toString();
System.out.println("-----" + urla);
//-----下載LRC歌詞
if (urla.indexOf("'href':'") > 0) {
String[] uu = urla.split("'href':'");
System.out.println("uu1 : " + uu[1]);
//uu1 : /data2/lrc/14488216/14488216.lrc' }" href="#">下載LRC歌詞
String[] uuu = uu[1].split(".lrc'");
System.out.println("uuu0 : " + uuu[0]);
//uuu0 : /data2/lrc/246970367/246970367.lrc
String lrcDwonUrl = "http://music.baidu.com" + uuu[0] + ".lrc";
System.out.println("lrcDwonUrl : " + lrcDwonUrl);
//result : http://music.baidu.com/data2/lrc/14488216/14488216.lrc
File LrcDirFile = new File(Environment.getExternalStorageDirectory() + Constant.DIR_LRC);
System.out.println("LrcDirFile : " + LrcDirFile);
if (!LrcDirFile.exists()) {
LrcDirFile.mkdirs();
}
String target = LrcDirFile + "/" + musicName + ".lrc";
System.out.println("lrcDwonUrl : " + lrcDwonUrl);
System.out.println("target : " + target);
File fileTarget = new File(target);
if (fileTarget.exists()) {
handler.obtainMessage(MUSIC_EXISTS).sendToTarget();
return;
} else {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(lrcDwonUrl).build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
PrintStream ps = new PrintStream(new File(target));
byte[] bytes = response.body().bytes();
ps.write(bytes, 0, bytes.length);
ps.close();
handler.obtainMessage(SUCCESS_LRC, target).sendToTarget();
}
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
//下載MP3
private void downloadMusic(final SearchResult searchResult,final String url,final Handler handler){
mThreadPool.execute(new Runnable() {
@Override
public void run() {
File musicDirFile = new File(Environment.getExternalStorageDirectory()+Constant.DIR_MUSIC);
if (!musicDirFile.exists()){
musicDirFile.mkdirs();
}
String mp3url = url;
//String mp3url = "http://tyst.migu.cn/public/600902-2008430/tone/2008/09/10/2008年9月/4月環球106首歌曲/彩鈴/7_mp3-128kbps/等你等到我心痛-張學友.mp3";
String target = musicDirFile + "/" + searchResult.getMusicName() + ".mp3";
System.out.println(mp3url);
System.out.println(target);
File fileTarget = new File(target);
if (fileTarget.exists()){
handler.obtainMessage(MUSIC_EXISTS).sendToTarget();
return;
}else {
//使用OkHttpClient組件
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(mp3url).build();
System.out.println(request);
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()){
PrintStream ps = new PrintStream(fileTarget);
byte[] bytes = response.body().bytes();
ps.write(bytes,0,bytes.length);
ps.close();
handler.obtainMessage(SUCCESS_MP3).sendToTarget();
}
} catch (IOException e) {
e.printStackTrace();
handler.obtainMessage(FAILED_MP3).sendToTarget();
}
}
}
});
}
//自定義下載事件監聽器
public interface OnDownloadListener {
public void onDowload(String mp3Url);
public void onFailed(String error);
}
}