最近這段時間老師讓我們學生自己去做個項目,我自己選擇做一個音樂播放器,因為這個比較簡單,上手也比較容易,老師教的知識基本都用得上。
我自己就無聊跑去弄個網絡擷取歌單,當然也隻是歌單,并不能實作播放功能,不過也學到了一些知識。擷取網絡的歌曲名與歌手名,我是這樣弄的,我參考了很多前輩的用法,大多數的前輩們基本都是使用jsoup這個包去解析一些音樂網站,然後再擷取想要的資訊,這裡我對我學到的知識做一下總結:
首先我們需要去導一下jsoup的jar包,在Android Studio中導入的方法:
第一種方法:可以直接在app檔案夾下的build.gradle中的
dependencies{
compile 'org.jsoup:jsoup:1.10.3' //版本看情況
}
第二種方法:可以直接去https://jsoup.org/download 這個網址下載下傳jsoup的jar包,下載下傳完後,
然後對着這個jar包點選右鍵 找到Add As Library,軟體就會幫你導入這個jar包啦
第三種方法:這種最為友善,可以直接在Android Studio中下載下傳
這些準備工作基本都做完了,下面我們就開始進入項目中:
首先我們先把他的布局給弄出來,不弄布局哪裡會顯示哦。。
布局檔案名:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.caijixieshou.NetMusic.MainActivity">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/net_song_listview"
/>
</LinearLayout>
弄好布局後,我們建立在java檔案夾下建立一個包叫domain,在該包下建立一個Bean類NetSongsResults來封裝歌曲的資訊
public class NetSongsResults {
private String MusicName;//歌名
private String Artist;//歌手名
private String Album;//專輯
//用系統自帶的Getter和Setter封裝
public String getMusicName() {
return MusicName;
}
public void setMusicName(String musicName) {
MusicName = musicName;
}
public String getArtist() {
return Artist;
}
public void setArtist(String artist) {
Artist = artist;
}
public String getAlbum() {
return Album;
}
public void setAlbum(String album) {
Album = album;
}
//這裡用系統生成的toString方法為了友善列印資訊
@Override
public String toString() {
return "NetSongsResults{" +
"MusicName='" + MusicName + '\'' +
", Artist='" + Artist + '\'' +
", Album='" + Album + '\'' +
'}';
}
}
弄好了bean檔案後,我們還在java檔案夾下建立一個工具util包,在該包下建立一個解析類JsoupUtils,該類用來解析音樂網站
public class JsoupUtils {
private static JsoupUtils instance;
//這裡用單例的方式,為了友善使用
public static JsoupUtils getInstance(){
if (instance == null){
instance = new JsoupUtils();
}
return instance;
}
public void getMusic(final String url, final String title,
final String artist, final ArrayList<NetSongsResults> datalist,
final CallBack mCallBack){
//因為聯網解析網頁屬于一種耗時操作,是以我們需要在這裡另起一個線程
new Thread(new Runnable() {
@Override
public void run() {
try {
Document doc = Jsoup.connect(url).userAgent("Mozilla/5.0 (Windows NT 10.0; WOW64) " +
"AppleWebKit/537.36 (KHTML, like G" +
"ecko) Chrome/53.0.2785.104 " +
"Safari/537.36 Core/1.53.3226.400").timeout(10000).get();
Elements titleEls = doc.select(title);
Elements artistEls = doc.select(artist);
//這裡我們周遊一下我們所擷取的資訊,然後通過bean類封裝資訊再把資訊添加到集合中
for (int i = 0;i<titleEls.size();i++){
//執行個體化NetSongsResults
NetSongsResults netSongsResults = new NetSongsResults();
//getAllElements方法為擷取該cssQuery下的所有标簽(我網頁學得不好,我也不知道是不是)
Elements title = titleEls.get(i).getAllElements();
//這裡用netSongsResults調用set方法封裝資訊
netSongsResults.setMusicName(title.get(0).text());
Elements artist = artistEls.get(i).getAllElements();
netSongsResults.setArtist(artist.get(0).text());
//這裡添加專輯名,随便起一個
netSongsResults.setAlbum("最新推薦");
//最後把netSongsResults添加到集合中
datalist.add(netSongsResults);
}
//判斷如果資料源不為空的時候調用回調接口的Success方法,為空時調用Error方法
if (datalist != null){
mCallBack.Success(datalist);
} else {
mCallBack.Error(datalist);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
//這裡我們定義一個回調接口,判斷是否成功的擷取到了datalist
public interface CallBack{
public void Success(ArrayList<NetSongsResults> datalist);
public void Error(ArrayList<NetSongsResults> datalist);
}
}
弄好了工具類之後,我們弄一個自定義擴充卡去為了讓ListView顯示資料,ListView中的每一項的布局為:
item_net_song_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:id="@+id/item_net_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:textSize="17sp"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal"
android:layout_marginLeft="10dp"
android:layout_marginBottom="10dp"
>
<TextView
android:id="@+id/item_net_artist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="未知藝術家"
android:textSize="15sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" - "
android:textSize="20sp"
/>
<TextView
android:id="@+id/item_net_ablum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="未知專輯"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>
弄好了布局之後就開始寫自定義擴充卡了
public class NetSongAdapter extends BaseAdapter {
private Context context; //上下文
private ArrayList<NetSongsResults> datalist; //資料源
private LayoutInflater inflater; //布局填充器
private NetSongsResults netSongsResults;
public NetSongAdapter(Context context, ArrayList<NetSongsResults> datalist) {
this.context = context;
this.datalist = datalist;
this.inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return datalist.size();
}
@Override
public Object getItem(int i) {
return datalist.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
ViewHolder holder = null;
if (convertView == null){
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.item_net_song_layout,null);
holder.title = convertView.findViewById(R.id.item_net_title);
holder.artist = convertView.findViewById(R.id.item_net_artist);
holder.ablum = convertView.findViewById(R.id.item_net_ablum);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//執行個體化NetSongsResults對象,去接收datalist.get(position);
netSongsResults = datalist.get(position);
String artist = netSongsResults.getArtist();
String ablum = netSongsResults.getAlbum();
holder.title.setText(netSongsResults.getMusicName());
if (!TextUtils.isEmpty(artist)){
holder.artist.setText(artist);
} else {
holder.artist.setText("未知藝術家");
}
if (!TextUtils.isEmpty(ablum)){
holder.ablum.setText(ablum);
}else {
holder.ablum.setText("未知專輯");
}
return convertView;
}
class ViewHolder{
TextView title;
TextView artist;
TextView ablum;
}
}
擴充卡也弄好了,我們就開始去寫MainActivity了
public class MainActivity extends AppCompatActivity {
private ListView net_song_listview;
private static final String url = "http://music.baidu.com/search?key=%E8%96%9B%E4%B9%8B%E8%B0%A6";
private ArrayList<NetSongsResults> datalist;
private NetSongAdapter netSongAdapter;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
net_song_listview = (ListView) findViewById(R.id.net_song_listview);
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case Contents.ConnectSuccess:
netSongAdapter = new NetSongAdapter(MainActivity.this,datalist);
net_song_listview.setAdapter(netSongAdapter);
Toast.makeText(MainActivity.this,"更新完成...",Toast.LENGTH_SHORT).show();
break;
case Contents.ConnectFail:
//msg.what = (int) msg.obj;
Toast.makeText(MainActivity.this,"更新失敗...",Toast.LENGTH_SHORT).show();
break;
}
}
};
datalist = new ArrayList<NetSongsResults>();
JsoupUtils.getInstance().getMusic(url, "span.song-title", "span.author_list",
datalist, new JsoupUtils.CallBack() {
@Override
public void Success(ArrayList<NetSongsResults> datalist) {
if (datalist != null ){
handler.sendEmptyMessage(Contents.ConnectSuccess);
}else {
return;
}
}
@Override
public void Error(ArrayList<NetSongsResults> datalist) {
if (datalist == null){
handler.sendEmptyMessage(Contents.ConnectFail);
}
}
});
}
}
這樣就把擷取網絡歌曲資訊的功能寫完了,最後需要在配置檔案AndroidManifest.xml中添加網絡權限
<uses-permission android:name="android.permission.INTERNET" />
實際圖是這樣的:
之前也有提到在Elements中的select方法的參數怎麼去用,這裡我也是參考前輩的用法粗略的說一下:
首先打開一個網址:https://try.jsoup.org/
打開網頁後點選Fetch Url,會出現下面的視窗:
這時候就會出現這樣:
這些都是網頁的解析出來的資料,然後再做以下操作:
這樣我們就講完了,如果我講的有什麼地方不好的還請幫忙指出,因為我也是個初學者,學得也不太好,而且也是第一次寫部落格,希望大家多多支援!