使用百度音樂盒API介面實現音樂播放器
阿新 • • 發佈:2019-01-04
百度音樂盒提供了一個便捷的API可以拿來訪問一些音樂資源,開發者通過訪問指定格式的url可以拿到返回的資料,這個資料可以是json或者xml,這裡麵包含了歌曲的資訊。完整的API各種訪問格式是非常豐富的,參見http://www.cnblogs.com/liuying1995/p/5704176.html。這裡我們只實現查詢關鍵字,得到返回的歌曲列表和百度定義的歌曲的id,然後再使用這個id訪問,再從返回的資料中得到歌曲和歌詞的地址,接下來就可以順利完成歌曲的播放和下載了。-------另外,本文中還提供了一個動態顯示歌詞的自定義view和讀取歌詞檔案的工具類。
2.在查詢方法中訪問URL並得到返回的json,傳入解析json的方法。這裡面的url字串格式參見開頭提到的網站,可以看到字串最後的引數query=我們傳入的查詢資料。
4.展示歌詞的自定義view(轉):這裡傳入了一個自定義的歌詞類,是把每一行歌詞作為一個物件,其中有歌詞內容和歌詞開始時間這兩個值。
我直接展示我的實現思路:
1.接收輸入框的輸入文字並傳到查詢方法裡。
String name = etSearch.getText().toString(); if (name.length() == 0) { Toast.makeText(this, "請輸入歌曲名稱", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this,"已開始查詢,請耐心等待",Toast.LENGTH_SHORT).show(); query2(name); }
2.在查詢方法中訪問URL並得到返回的json,傳入解析json的方法。這裡面的url字串格式參見開頭提到的網站,可以看到字串最後的引數query=我們傳入的查詢資料。
3.在解析方法中最終取得歌曲的名稱,藝術家,地址,歌詞地址資訊,json解析就不具體展開了,然後我把這些資料封裝在自定義的Song物件裡。(方法中呼叫了兩個方法,分別是獲取歌曲地址和歌詞地址,在下面會展示,這是因為獲取這兩個資料需要用得到的歌曲的id再一次訪問)。private void query2(final String title){ new Thread(new Runnable() { @Override public void run() { try { HttpURLConnection connection; String finalTitle = URLEncoder.encode(title,"utf-8"); URL url = new URL("http://tingapi.ting.baidu.com/v1/restserver/ting?from=webapp_music&method=baidu.ting.search.catalogSug&format=json&callback=&query="+finalTitle); connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(60*1000); connection.setReadTimeout(60*1000); connection.connect(); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String s; if ((s=reader.readLine())!=null) doJson(s); } catch (IOException e) { e.printStackTrace(); } } }).start(); }
//解析返回的json public Song doJson(String json){ Song song = null; JSONObject jsonObject = null; list.clear();//清空原有的歌曲陣列 try { //去掉括號 json = json.replace("(",""); json = json.replace(")",""); jsonObject = new JSONObject(json); JSONArray array = new JSONArray(jsonObject.getString("song")); for (int i=0;i<array.length();i++){ JSONObject object = array.getJSONObject(i); String songname = object.getString("songname"); String artistname = object.getString("artistname"); String songid = object.getString("songid"); String adress = getAdress(songid); Song song1 = new Song(songname,artistname,adress,0); song1.setLrcPath(getLrcAdress(songid)); list.add(i,song1); Log.v("tag",songname+" "+artistname+" "+songid); //列表更新 Message msg = new Message(); msg.what = 1; handler.sendMessage(msg); } } catch (JSONException e) { e.printStackTrace(); } return song; } public String getAdress(final String songid){ new Thread(new Runnable() { @Override public void run() { try { HttpURLConnection connection; //URL url = new URL("http://api.5288z.com/weixin/musicapi.php?q="+finalTitle); URL url = new URL("http://ting.baidu.com/data/music/links?songIds="+songid); connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(60*1000); connection.setReadTimeout(60*1000); connection.connect(); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String s; if ((s=reader.readLine())!=null){ s = s.replace("\\","");//去掉\\ try { JSONObject object = new JSONObject(s); JSONObject object1 = object.getJSONObject("data"); JSONArray array = object1.getJSONArray("songList"); JSONObject object2 = array.getJSONObject(0); adress = object2.getString("songLink"); Log.v("tagadress",adress); } catch (JSONException e) { e.printStackTrace(); } } } catch (IOException e) { e.printStackTrace(); } } }).start(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } return adress; } //獲取歌詞地址 public String getLrcAdress(final String songid){ new Thread(new Runnable() { @Override public void run() { try { HttpURLConnection connection; //URL url = new URL("http://api.5288z.com/weixin/musicapi.php?q="+finalTitle); URL url = new URL("http://ting.baidu.com/data/music/links?songIds="+songid); connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(60*1000); connection.setReadTimeout(60*1000); connection.connect(); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String s; if ((s=reader.readLine())!=null){ s = s.replace("\\","");//去掉\\ Log.v("tag","------"+s); try { JSONObject object = new JSONObject(s); JSONObject object1 = object.getJSONObject("data"); JSONArray array = object1.getJSONArray("songList"); JSONObject object2 = array.getJSONObject(0); LrcAdress = object2.getString("lrcLink"); Log.v("tag","888888lrc"+ LrcAdress); } catch (JSONException e) { e.printStackTrace(); } } } catch (IOException e) { e.printStackTrace(); } } }).start(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } return LrcAdress; }
4.展示歌詞的自定義view(轉):這裡傳入了一個自定義的歌詞類,是把每一行歌詞作為一個物件,其中有歌詞內容和歌詞開始時間這兩個值。
package com.example.one.newmusicplayer.ui;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;
import com.example.one.newmusicplayer.item.LrcOne;
import java.util.ArrayList;
import java.util.List;
/**
* Created by lenovo on 2016/10/27.
* 顯示歌詞的自定義view
*/
public class LrcView extends TextView {
private float width; //歌詞檢視寬度
private float height; //歌詞檢視高度
private Paint currentPaint; //當前歌詞畫筆
private Paint notCurrentPaint; //非當前歌詞畫筆
private float textHeight = 45; //每一行高度
private float textSize = 35; //每一行非當前文字的大小
private int index = 0; //list集合下標
private List<LrcOne> list = new ArrayList<>();
public LrcView(Context context) {
super(context);
init();
}
public LrcView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setFocusable(true); //設定可對焦
//高亮部分
currentPaint = new Paint();
currentPaint.setAntiAlias(true); //設定抗鋸齒,讓文字美觀飽滿
currentPaint.setTextAlign(Paint.Align.CENTER);//設定文字對齊方式
//非高亮部分
notCurrentPaint = new Paint();
notCurrentPaint.setAntiAlias(true);
notCurrentPaint.setTextAlign(Paint.Align.CENTER);
}
/**
* 繪畫歌詞
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(canvas == null) {
return;
}
//設定字型的大小顏色樣式以及繪製出來的畫筆
currentPaint.setColor(Color.argb(210, 251, 0, 0));
notCurrentPaint.setColor(Color.argb(140, 0, 0, 0));
currentPaint.setTextSize(40);
currentPaint.setTypeface(Typeface.SERIF);
notCurrentPaint.setTextSize(textSize);
notCurrentPaint.setTypeface(Typeface.DEFAULT);
try {
setText("");
canvas.drawText(list.get(index).getLrcStr(), width / 2, height / 2, currentPaint);
float tempY = height / 2;
//畫出本句之前的句子
for(int i = index - 1; i >= 0; i--) {
//向上推移
tempY = tempY - textHeight;
canvas.drawText(list.get(i).getLrcStr(), width / 2, tempY, notCurrentPaint);
}
tempY = height / 2;
//畫出本句之後的句子
for(int i = index + 1; i < list.size(); i++) {
//往下推移
tempY = tempY + textHeight;
canvas.drawText(list.get(i).getLrcStr(), width / 2, tempY, notCurrentPaint);
}
} catch (Exception e) {
setText("");
}
}
/**
* 當view大小改變的時候呼叫的方法
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
this.width = w;
this.height = h;
}
public void setIndex(int index) {
this.index = index;
}
public void setmLrcList(List<LrcOne> mLrcList) {
this.list = mLrcList;
}
}
5.讀取歌詞檔案的工具類,讀取後封裝在一個歌詞類的數組裡。package com.example.one.newmusicplayer.tools;
import android.util.Log;
import android.widget.Toast;
import com.example.one.newmusicplayer.item.LrcOne;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
/**
* Created by lenovo on 2016/10/27.
* 讀取歌詞並將其拆成一個個歌詞類的工具類
*/
public class LrcDeal {
public List<LrcOne> getList() {
return list;
}
private List<LrcOne> list = new ArrayList<>();
//讀取歌詞並返回一個裝滿歌詞物件的list
//讀取網路歌詞檔案的方法
public List<LrcOne> readIntnetLrc(String path){
InputStream inputStream = null;
try {
URL url = new URL(path);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(60*1000);
connection.setReadTimeout(60*1000);
inputStream = connection.getInputStream();
} catch (Exception e) {
e.printStackTrace();
}
StringBuilder stringBuilder = new StringBuilder();
//建立一個檔案輸入流
try {
//建立一個檔案輸入流物件
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
String s = "";
while((s = br.readLine()) != null) {
s = s.replace("[", "");
s = s.replace("]", "@");
//分離“@”字元
String splitLrcData[] = s.split("@");
LrcOne lrcOne = new LrcOne();
if(splitLrcData.length > 1) {
lrcOne.setLrcStr(splitLrcData[1]);
//處理歌詞取得歌曲的時間
int lrcTime = time2Str(splitLrcData[0]);
lrcOne.setLrcTime(lrcTime);
//新增進列表陣列
list.add(lrcOne);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
stringBuilder.append("木有歌詞檔案,趕緊去下載!...");
} catch (IOException e) {
e.printStackTrace();
stringBuilder.append("木有讀取到歌詞哦!");
}
return list;
}
//對時間字串進行處理
public int time2Str(String timeStr) {
timeStr = timeStr.replace(":", ".");
timeStr = timeStr.replace(".", "@");
String timeData[] = timeStr.split("@"); //將時間分隔成字串陣列
//分離出分、秒並轉換為整型
int minute = Integer.parseInt(timeData[0]);
int second = Integer.parseInt(timeData[1]);
int millisecond = Integer.parseInt(timeData[2]);
//計算上一行與下一行的時間轉換為毫秒數
int currentTime = (minute * 60 + second) * 1000 + millisecond * 10;
return currentTime;
}
}