当音乐播放器的本地音乐播放和音乐播放界面实现后,我们将逐渐开始网络音乐功能的拓展,本文主要将的是如何实现网络音乐的搜索以及将搜索到的结果以列表的形式展示出来,主要设计的内容包括:音乐接口的使用,添加网络请求(这里使用的是volley-下载地址,下载完将volley.jar拷到项目/libs下),处理响应返回的数据-json(相应的类在org.json包下)
NetFragment.java的主要代码如下:
package com.example.comfortmusic_1.fragment;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.Request.Method;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.example.comfortmusic_1.MainActivity;
import com.example.comfortmusic_1.R;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AbsListView.LayoutParams;
import android.widget.SearchView.OnQueryTextListener;
public class NetFragment extends Fragment {
//搜索音乐接口
public static final String CLOUD_MUSIC_API_PREFIX = "http://s.music.163.com/search/get/?";
//搜索响应时返回的数据
public static String getResponse;
//将响应getResponse包装成JSONObject进行解析
public static JSONObject jo;
//解析出来的结果存在searchResults里并在musicList里以列表的形式展示
public static List<Map<String, String>> searchResults = new ArrayList<Map<String, String>>();
private SearchView searchView;//搜索框
ListView musicList; //展示搜索的音乐结果
String TAG = "NetFragment";
Handler handler;
RequestQueue mQueue = null; //网络请求队列
@Override
public void onAttach(Activity activity) {
// TODO Auto-generated method stub
super.onAttach(activity);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.netmusic, container, false);
searchView = (SearchView)rootView.findViewById(R.id.searchView1);
musicList = (ListView) rootView.findViewById(R.id.netmusiclist);
mQueue = Volley.newRequestQueue(NetFragment.this.getActivity());
Log.d(TAG, Environment.getExternalStorageDirectory().getAbsolutePath());
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0) {
musicList.setAdapter(getAdapter());
Log.d(TAG,"getMusic!");
} else if (msg.what == 1) {
Toast.makeText(NetFragment.this.getActivity(), "下载完成!", 300).show();
Log.d(TAG,"下载完成!");
}
}
};
searchView.setOnQueryTextListener(new OnQueryTextListener() {
@Override
public boolean onQueryTextChange(String arg0) {
return false;
}
@Override
public boolean onQueryTextSubmit(String query) {//搜索框输入内容点击搜索调用getSong(query)方法
Toast.makeText(NetFragment.this.getActivity(), "搜索内容为:" + query, 300).show();
musicList.setAdapter(null);
searchResults.clear();
getSong(query);
return false;
}
});
return rootView;
}
/**
* 这里先将搜索内容进行UTF-8编码,再与音乐搜索接口进行拼接组成网络请求url
* @param search
*/
public void getSong(String search) {
if (search.equals("")) return;
Log.d(TAG,"connecting...");
Toast.makeText(NetFragment.this.getActivity(), "connectURL...", 300).show();
String s = null;
if (search != null) {
try {
s= URLEncoder.encode(search, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
final String url = CLOUD_MUSIC_API_PREFIX + "type=1&s='" + s + "'&limit=20&offset=0";
Log.d(TAG, "url = " + url);
//请求类,请求返回数据response类型为String
StringRequest stringRequest = new StringRequest(Method.GET,url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, response);
getResponse = response;
showList();
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, error.getMessage(), error);
Toast.makeText(NetFragment.this.getActivity(), "请检查网络连接!", 300).show();
}
});
mQueue.add(stringRequest); //请求添加到队列里
}
/**
* 将String类型的响应包装成JSONObject类型进行解析
* 其中JSONObject是{key1:value1, key2:value2, ...}形式的类似map的键值对,其中value也可以是JSONObject,即嵌套
* JSONArray是[JSONObject, JSONObject, ...]形式的数据结构
*/
protected void showList() {
Log.d(TAG, "showList");
try {
jo = new JSONObject(getResponse);
String result = jo.getString("result");
String songs = new JSONObject(result).getString("songs");
JSONArray js = new JSONObject(result).getJSONArray("songs");
for (int i=0; i<js.length(); i++) {
JSONObject child = js.getJSONObject(i);
JSONArray artists = child.getJSONArray("artists");
String artist = artists.getJSONObject(0).getString("name");
String name = child.getString("name");
String audioUrl = child.getString("audio");
JSONObject album = child.getJSONObject("album");
String picUrl = album.getString("picUrl");
Map<String, String> item = new HashMap<String, String>();
item.put("name", name);
item.put("artist", artist);
item.put("audioUrl", audioUrl);
item.put("picUrl", picUrl);
searchResults.add(item);
Log.d(TAG, "name = " + name + "---artists:" + artist);
Log.d(TAG, "audioUrl = " + audioUrl);
Log.d(TAG, "picUrl = " + picUrl);
}
handler.sendEmptyMessage(0);
Toast.makeText(NetFragment.this.getActivity(), "下载完成!", 300).show();
} catch (JSONException e) {
e.printStackTrace();
}
}
//构建搜索结果列表的适配器
private BaseAdapter getAdapter() {
BaseAdapter adapter = new BaseAdapter() {
@Override
public int getCount() {
return searchResults.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
Map<String, String> map = searchResults.get(position);
LinearLayout line = new LinearLayout(NetFragment.this.getActivity());
line.setOrientation(LinearLayout.HORIZONTAL);
line.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,100));
ImageView musicTag = new ImageView(NetFragment.this.getActivity());
musicTag.setImageResource(R.drawable.music);
musicTag.setLayoutParams(new LayoutParams(80,80));
//标题格式设置
TextView songTitle = new TextView(NetFragment.this.getActivity());
String musicName = map.get("name");
songTitle.setWidth(MainActivity.screenWidth/2);
songTitle.setHeight(100);
songTitle.setMaxLines(1);
songTitle.setTextColor(Color.MAGENTA);
songTitle.setTextSize(18);
songTitle.setText(musicName);
songTitle.setGravity(TextView.TEXT_ALIGNMENT_CENTER);
songTitle.setGravity(Gravity.CENTER_VERTICAL);
//艺术家格式设置
TextView artist = new TextView(NetFragment.this.getActivity());
artist.setGravity(TextView.TEXT_ALIGNMENT_CENTER);
artist.setWidth(MainActivity.screenWidth/3);
artist.setHeight(100);
artist.setTextColor(Color.MAGENTA);
artist.setText(map.get("artist"));
artist.setTextSize(15);
artist.setMaxLines(1);
artist.setPadding(50, 0, 0, 10);
artist.setGravity(Gravity.RIGHT);
//下载图标
ImageView download = new ImageView(NetFragment.this.getActivity());
download.setImageResource(R.drawable.downloaded_music);
download.setLayoutParams(new LayoutParams(70,80));
download.setPaddingRelative(10, 0, 0, 0);
line.addView(musicTag);
line.addView(songTitle);
line.addView(artist);
line.addView(download);
return line;
}};
return adapter;
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
该功能实现的核心在于对网络响应返回的json数据的解析-(另为了便于理解解析json数据过程,附上一段json数据格式的response,结合showList()看更容易理解)
{"result":{"songCount":463,"songs":[
{"id":65126,
"name":"红玫瑰",
"artists":[{"id":2116,"name":"陈奕迅","picUrl":null}],
"album":{"id":6404,"name":"1997-2007 跨世纪国语精选",
"artist":{"id":0,"name":"","picUrl":null},"picUrl":"http://p1.music.126.net/WJgLE2ImnLgqPPLQSlF7iQ==/114349209289440.jpg"},
"audio":"http://m2.music.126.net/J_dEE5O0YuytnLWoFHsYCw==/8002245628486539.mp3",
"djProgramId":0,"page":"http://music.163.com/m/song/65126"},
{"id":420513158,
"name":"红蔷薇白玫瑰",
"artists":[{"id":7763,"name":"G.E.M.邓紫棋","picUrl":null}],
"album":{"id":34767677,"name":"红蔷薇白玫瑰",
"artist":{"id":0,"name":"","picUrl":null},
"picUrl":"http://p1.music.126.net/ExDuzcVK5vkMNpPpzmFX6Q==/3446968958754370.jpg"},
"audio":"http://m2.music.126.net/HrWiNyX5yRroNh4QCcJy4A==/3413983618586421.mp3",
"djProgramId":0,"page":"http://music.163.com/m/song/420513158"},
{"id":65533,
"name":"红玫瑰",
"artists":[{"id":2116,"name":"陈奕迅","picUrl":null}],
"album":{"id":6434,"name":"认了吧",
"artist":{"id":0,"name":"","picUrl":null},
"picUrl":"http://p1.music.126.net/obu1uFbrm9EjrVpqaaKQvw==/90159953489756.jpg"},
"audio":"http://m2.music.126.net/eeSo9acw4OUaGtqnOpV2hA==/3273246115947004.mp3",
"djProgramId":0,"page":"http://music.163.com/m/song/65533"},......] }