失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 基于android的网络音乐播放器-网络音乐的搜索和展示(五)

基于android的网络音乐播放器-网络音乐的搜索和展示(五)

时间:2022-09-15 09:06:34

相关推荐

基于android的网络音乐播放器-网络音乐的搜索和展示(五)

作为android初学者,最近把疯狂android讲义和疯狂Java讲义看了一遍,看到书中介绍的知识点非常多,很难全部记住,为了更好的掌握基础知识点,我将开发一个网络音乐播放器-EasyMusic来巩固下,也当作是练练手。感兴趣的朋友可以看看,有设计不足的地方也欢迎指出。

开发之前首先介绍下该音乐播放器将要开发的功能(需求):

1.本地音乐的加载和播放;

2.网络音乐的搜索,试听和下载;

3.音乐的断点下载;

4.点击播放图标加载专辑图片,点击歌词加载歌词并滚动显示(支持滑动歌词改变音乐播放进度);

5.支持基于popupWindow的弹出式菜单;

6.支持后台任务栏显示和控制。

该篇主要是介绍在NetFragment中实现网络音乐的搜索和展示功能开发:

先看下效果图如下

首先介绍下大概的实现思路:NetFragment布局顶部为搜索框SearchView,下面为一个ListView用来显示搜索到的网络音乐

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><SearchView android:id="@+id/searchView"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#f0f" ></SearchView><ListView android:id="@+id/netmusiclist"android:layout_width="match_parent"android:layout_height="wrap_content" ></ListView></LinearLayout>

搜索框中输入搜索关键字并点击搜索(软键盘最后一个搜索键),为了避免在主线程执行耗时任务,搜索时建立一个异步任务(NetFragment的内部类)执行搜索任务(包括建立Http连接,解析json数据)。异步任务的定义如下:

// 负责搜索音乐的异步任务,搜索完成后显示网络音乐列表private class SearchMusicTask extends AsyncTask<String, Void, Void> {private ListView musicList;public SearchMusicTask(ListView musicList) {this.musicList = musicList;}protected void onPreExecute() {super.onPreExecute();}protected Void doInBackground(String... params) {String url = params[0];try {HttpURLConnection conn = (HttpURLConnection)new URL(url).openConnection();conn.setConnectTimeout(5000);//使用缓存提高处理效率BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));String line = null;StringBuilder sb = new StringBuilder();while ((line = br.readLine()) != null) {sb.append(line);}//网络响应赋值给成员变量searchResponsesearchResponse = sb.toString();parseResponse();Log.d(TAG, "searchResponse = " + searchResponse);} catch (IOException e) {e.printStackTrace();}return null;}protected void onProgressUpdate(Void... values) {super.onProgressUpdate(values);}protected void onPostExecute(Void result) {super.onPostExecute(result);//adapter数据更新后通知列表更新netMusicListAdapter.notifyDataSetChanged();//musicList.setAdapter(netMusicListAdapter);}//json解析网络响应private void parseResponse() {try {JSONObject response = new JSONObject(searchResponse);JSONObject result = response.getJSONObject("result");JSONArray songs = result.getJSONArray("songs");if (netMusicList.size() > 0) netMusicList.clear();for (int i = 0; i < songs.length(); i++) {JSONObject song = songs.getJSONObject(i);//获取歌曲名字String title = song.getString("name");//获取歌词演唱者String artist = song.getJSONArray("artists").getJSONObject(0).getString("name");//获取歌曲专辑图片的urlString albumPicUrl = song.getJSONObject("album").getString("picUrl");//获取歌曲音频的urlString audioUrl = song.getString("audio");Log.d(TAG, "doenloadUrl = " + audioUrl);//保存音乐信息的MapMap<String, Object> item = new HashMap<>();item.put("title", title);item.put("artist", artist);item.put("picUrl", albumPicUrl);picUrlMap.put(title + artist, new SoftReference<String>(albumPicUrl));item.put("audio", audioUrl);//将一条歌曲信息存入list中netMusicList.add(item);}Log.d(TAG, "搜到" + netMusicList.size() + "首歌");} catch (JSONException e) {e.printStackTrace();}}}

异步任务在执行之前会调用onPreExecute(这里可以进行一些初始化的操作),然后调用核心方法doInBackground(该方法运行在独立的线程中,耗时操作往往放在该方法里),当doInBackground执行完成后会回调onPostExecute方法,当执行完任务在该方法中更新UI,值得指出来的是异步任务的onPreExecute,onProgressUpdate(该方法通常用在需要实时更新任务进度的场景),onPostExecute都是运行在主线程中。该异步任务的主要难点是json数据的解析上。json数据的解析可以参考我的另一篇博客–json数据的解析。

根据搜索得到网络音乐列表后应该考虑如下进行下载了,在异步任务里我们已经将音乐的音频url保存起来了,下一步只需要根据点击的歌曲取出相应的url建立Http连接并取出输入流文件-音频文件。该篇主要介绍网络音乐的搜索和展示,下载任务的建立和下载列表的更新将放在下一篇中将。下面附上NetFragment.java的完整代码。

package com.sprd.easymusic.fragment;import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.UnsupportedEncodingException;import java.lang.ref.SoftReference;import .HttpURLConnection;import .MalformedURLException;import .URL;import .URLEncoder;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.concurrent.Executor;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;import com.sprd.easymusic.MainActivity;import com.sprd.easymusic.R;import com.sprd.easymusic.util.DownloadTask;import com.sprd.easymusic.util.DownloadUtil;import android.app.Activity;import android.content.Context;import android.graphics.Color;import android.support.v4.app.Fragment;import android.os.AsyncTask;import android.os.Bundle;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.View.OnClickListener;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.ListView;import android.widget.SearchView;import android.widget.SearchView.OnCloseListener;import android.widget.Toast;import android.widget.SearchView.OnQueryTextListener;import android.widget.TextView;public class NetFragment extends Fragment {private final String TAG = "NetFragment";//音乐搜索接口public static final String CLOUD_MUSIC_API_PREFIX = "http://s./search/get/?";private Context mContext;//获取输入的搜索框private SearchView searchView;//根据关键字搜索到的音乐列表private ListView netMusicListView;//存放搜索到的音乐信息的listprivate List<Map<String, Object>> netMusicList = new ArrayList<>();//获取的json数据格式的网络响应赋值给searchResponseprivate String searchResponse = null;private LayoutInflater inflater;//缓存专辑图片的下载链接,当下载完成并播放歌曲时,点击播放图标加载专辑图标时避免重新联网搜索,直接从缓存中获取private Map<String, SoftReference<String>> picUrlMap = new HashMap<String, SoftReference<String>>();public void onAttach(Activity activity) {super.onAttach(activity);}public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mContext = this.getActivity();inflater = LayoutInflater.from(mContext);Log.d(TAG, "onCreate");}// NetFragment向外界展示的内容,返回值为viewpublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View view = inflater.inflate(music, container, false);netMusicListView = (ListView) view.findViewById(musiclist);netMusicListView.setAdapter(netMusicListAdapter);netMusicListView.setOnItemClickListener(new OnItemClickListener() {public void onItemClick(AdapterView<?> parent, View view, int position, long id) {//点击搜索到的网络音乐列表的第position项即可建立下载任务下载对应歌曲,下一篇介绍//createDownloadTask(position);}});searchView = (SearchView) view.findViewById(R.id.searchView);//搜索框监听,点击搜索建立异步任务执行搜索任务searchView.setOnQueryTextListener(new OnQueryTextListener() {public boolean onQueryTextSubmit(String query) {Toast.makeText(mContext, "搜索内容为:" + query, 100).show();String musicUrl = getRealUrl(query);new SearchMusicTask(netMusicListView).execute(musicUrl);return false;}public boolean onQueryTextChange(String newText) {return false;}});searchView.setOnCloseListener(new OnCloseListener() {public boolean onClose() {netMusicListView.setAdapter(null);// netMusicList.clear();adapter.notifyDataSetChanged();return false;}});return view;}// 网络音乐列表适配器private BaseAdapter netMusicListAdapter = new BaseAdapter() {@Overridepublic int getCount() {return netMusicList.size();}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(final int position, View convertView,ViewGroup parent) {View view = convertView;Map<String, Object> item = netMusicList.get(position);if (convertView == null) {view = inflater.inflate(musiclist_item, null);}TextView musicTitle = (TextView) view.findViewById(R.id.musicTitle);musicTitle.setTag("title");TextView musicArtist = (TextView) view.findViewById(R.id.musicArtist);musicTitle.setText((String) item.get("title"));musicArtist.setText((String) item.get("artist"));return view;}};//返回可以访问的网络资源private String getRealUrl(String query) {String key = null;try {key = URLEncoder.encode(query, "UTF-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}return CLOUD_MUSIC_API_PREFIX + "type=1&s='" + key+ "'&limit=20&offset=0";}public void onDestroy() {super.onDestroy();}// 负责搜索音乐的异步任务,搜索完成后显示网络音乐列表private class SearchMusicTask extends AsyncTask<String, Void, Void> {private ListView musicList;public SearchMusicTask(ListView musicList) {this.musicList = musicList;}protected void onPreExecute() {super.onPreExecute();}protected Void doInBackground(String... params) {String url = params[0];try {HttpURLConnection conn = (HttpURLConnection)new URL(url).openConnection();conn.setConnectTimeout(5000);//使用缓存提高处理效率BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));String line = null;StringBuilder sb = new StringBuilder();while ((line = br.readLine()) != null) {sb.append(line);}//网络响应赋值给成员变量searchResponsesearchResponse = sb.toString();parseResponse();Log.d(TAG, "searchResponse = " + searchResponse);} catch (IOException e) {e.printStackTrace();}return null;}protected void onProgressUpdate(Void... values) {super.onProgressUpdate(values);}protected void onPostExecute(Void result) {super.onPostExecute(result);//adapter数据更新后通知列表更新netMusicListAdapter.notifyDataSetChanged();//musicList.setAdapter(netMusicListAdapter);}//json解析网络响应private void parseResponse() {try {JSONObject response = new JSONObject(searchResponse);JSONObject result = response.getJSONObject("result");JSONArray songs = result.getJSONArray("songs");if (netMusicList.size() > 0) netMusicList.clear();for (int i = 0; i < songs.length(); i++) {JSONObject song = songs.getJSONObject(i);//获取歌曲名字String title = song.getString("name");//获取歌词演唱者String artist = song.getJSONArray("artists").getJSONObject(0).getString("name");//获取歌曲专辑图片的urlString albumPicUrl = song.getJSONObject("album").getString("picUrl");//获取歌曲音频的urlString audioUrl = song.getString("audio");Log.d(TAG, "doenloadUrl = " + audioUrl);//保存音乐信息的MapMap<String, Object> item = new HashMap<>();item.put("title", title);item.put("artist", artist);item.put("picUrl", albumPicUrl);picUrlMap.put(title + artist, new SoftReference<String>(albumPicUrl));item.put("audio", audioUrl);//将一条歌曲信息存入list中netMusicList.add(item);}Log.d(TAG, "搜到" + netMusicList.size() + "首歌");} catch (JSONException e) {e.printStackTrace();}}}}

音乐播放器已完成,下载地址:

Android音乐播放器

如果觉得《基于android的网络音乐播放器-网络音乐的搜索和展示(五)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。