2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > Android开发 本地与音乐播放器(基于Service实现)

Android开发 本地与音乐播放器(基于Service实现)

时间:2022-04-20 14:59:08

相关推荐

Android开发 本地与音乐播放器(基于Service实现)

项目里需要做一个类似于QQ音乐,网易云音乐一样的实现本地与在线播放的音乐播发器。

本地的好做,查询安卓自己的媒体库ContentProvidre返回Cursor,一个个读出来就好了。

关键是在线播放。

一开始在网上搜了搜Demo.找到一个在线播放的Demo.但看了看源码,在线播放那一部分是在Activity里new 一个Thread,在Thread里实现播放。

这样做尽管能实现在线播放,但是和Activity的通信变成了麻烦。毕竟还需要和Seekbar交互,实现拖拽进度,暂停,继续等这样的操作。

于是,自己在Service里写了一个在线播放。效果还不错。‘

先看下最后的结果图:

1.本地播放:

歌曲列表

播放界面,模仿网易云音乐,背景根据专辑图片高斯模糊

在线歌曲列表

2.在线播放,SeekBar里的红色代表当前进度,灰色代表在线缓冲进度,透明代表没有缓冲到的。

接下来一步步说方法。

首先是本地播放:

根据ContentProvider查询出一个包含所有本地音乐的Cursor.

1.用来获取所有本地歌曲的MediaUtil.

MediaUtil.java

package com.lzw.util;import java.io.FileDescriptor;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import android.content.ContentResolver;import android.content.ContentUris;import android.content.Context;import android.database.Cursor;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.BitmapFactory.Options;import .Uri;import android.os.ParcelFileDescriptor;import android.provider.MediaStore;import android.util.Log;import com.lzw.bean.SongBean;import com.lzw.lmusicplayer.R;public class MediaUtil {private static final Uri albumArtUri = Uri.parse("content://media/external/audio/albumart");public static ArrayList<SongBean> getAllSongs(Context context) {Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null,MediaStore.Audio.Media.DEFAULT_SORT_ORDER);ArrayList<SongBean> mp3Infos = new ArrayList<SongBean>();for (int i = 0; i < cursor.getCount(); i++) {cursor.moveToNext();SongBean mp3Info = new SongBean();long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media._ID));String title = cursor.getString((cursor.getColumnIndex(MediaStore.Audio.Media.TITLE))); String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)); String album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM));String displayName = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));long albumId = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));long duration = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION)); long size = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE)); String url = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)); int isMusic = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.IS_MUSIC)); if (isMusic != 0) { mp3Info.setId(id);mp3Info.setTitle(title);mp3Info.setArtist(artist);mp3Info.setAlbum(album);mp3Info.setDisplayName(displayName);mp3Info.setAlbumId(albumId);mp3Info.setDuration(duration);mp3Info.setSize(size);mp3Info.setUrl(url);mp3Infos.add(mp3Info);}}return mp3Infos;}public static List<HashMap<String, String>> getMusicMaps(List<SongBean> mp3Infos) {List<HashMap<String, String>> mp3list = new ArrayList<HashMap<String, String>>();for (Iterator iterator = mp3Infos.iterator(); iterator.hasNext();) {SongBean mp3Info = (SongBean) iterator.next(); HashMap<String, String> map = new HashMap<String, String>();map.put("title", mp3Info.getTitle());map.put("Artist", mp3Info.getArtist());map.put("album", mp3Info.getAlbum());map.put("displayName", mp3Info.getDisplayName());map.put("albumId", String.valueOf(mp3Info.getAlbumId()));map.put("duration", formatTime(mp3Info.getDuration()));map.put("size", String.valueOf(mp3Info.getSize()));map.put("url", mp3Info.getUrl());mp3list.add(map);}return mp3list;}public static String formatTime(long time) {String min = time / (1000 * 60) + "";String sec = time % (1000 * 60) + "";if (min.length() < 2) {min = "0" + time / (1000 * 60) + "";} else {min = time / (1000 * 60) + "";}if (sec.length() == 4) {sec = "0" + (time % (1000 * 60)) + "";} else if (sec.length() == 3) {sec = "00" + (time % (1000 * 60)) + "";} else if (sec.length() == 2) {sec = "000" + (time % (1000 * 60)) + "";} else if (sec.length() == 1) {sec = "0000" + (time % (1000 * 60)) + "";}return min + ":" + sec.trim().substring(0, 2);}private static final Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");private static final BitmapFactory.Options sBitmapOptions = new BitmapFactory.Options();public static Bitmap getArtwork(Context context, long song_id, long album_id,boolean allowdefault) {if (album_id < 0) {if (song_id >= 0) {Bitmap bm = getArtworkFromFile(context, song_id, -1);if (bm != null) {return bm;}}if (allowdefault) {return getDefaultArtwork(context);}return null;}ContentResolver res = context.getContentResolver();Uri uri = ContentUris.withAppendedId(sArtworkUri, album_id);if (uri != null) {InputStream in = null;try {in = res.openInputStream(uri);Bitmap bmp = BitmapFactory.decodeStream(in, null, sBitmapOptions);if (bmp == null) {bmp = getDefaultArtwork(context);}return bmp;} catch (FileNotFoundException ex) {Bitmap bm = getArtworkFromFile(context, song_id, album_id);if (bm != null) {if (bm.getConfig() == null) {bm = bm.copy(Bitmap.Config.RGB_565, false);if (bm == null && allowdefault) {return getDefaultArtwork(context);}}} else if (allowdefault) {bm = getDefaultArtwork(context);}return bm;} finally {try {if (in != null) {in.close();}} catch (IOException e) {e.printStackTrace();}}}return null;}private static Bitmap getArtworkFromFile(Context context, long songid, long albumid) {Bitmap bm = null;if (albumid < 0 && songid < 0) {throw new IllegalArgumentException("Must specify an album or a song id");}try {if (albumid < 0) {Uri uri = Uri.parse("content://media/external/audio/media/" + songid + "/albumart");ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r");if (pfd != null) {FileDescriptor fd = pfd.getFileDescriptor();bm = BitmapFactory.decodeFileDescriptor(fd);}} else {Uri uri = ContentUris.withAppendedId(sArtworkUri, albumid);ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r");if (pfd != null) {FileDescriptor fd = pfd.getFileDescriptor();bm = BitmapFactory.decodeFileDescriptor(fd);}}} catch (FileNotFoundException ex) {}return bm;}private static Bitmap getDefaultArtwork(Context context) {BitmapFactory.Options opts = new BitmapFactory.Options();opts.inPreferredConfig = Bitmap.Config.RGB_565;return BitmapFactory.decodeStream(context.getResources().openRawResource(R.drawable.default_album), null,opts);}}

2.在列表中展示的Activity.

这里面有两点要说。一个是因为考虑到一些发烧友歌曲量过大,1000+以上首歌曲,我在加载的时候,使用GifView显示一张动态的Loading的GIF图片,提高体验度。加载要写异步任务。

第二点是,因为本地和在线是两个不同的Service,所以在start其中一个Service的时候,要stop另一个Service,不然若此时在线的Service也在运行,则会出现本地和在线两首歌同时播放的现象。

ListActivity.java

package com.lzw.activity;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.content.SharedPreferences;import android.os.AsyncTask;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.BaseAdapter;import android.widget.ListView;import android.widget.TextView;import com.ant.liao.GifView;import com.google.gson.Gson;import com.lzw.bean.SongBean;import com.lzw.lmusicplayer.R;import com.PlayerService;import com.lzw.service.PlayerService;import com.lzw.util.MediaUtil;import java.util.ArrayList;public class ListActivity extends Activity implements ListView.OnItemClickListener{private ListView musicListView;private ArrayList<SongBean> arrayList;private MusicListAdapter musicListAdapter;private GifView loadingGifView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_list);musicListView= (ListView) this.findViewById(R.id.musiclist);loadingGifView= (GifView) this.findViewById(R.id.loadinggif);loadingGifView.setGifImage(R.drawable.loading);new GetSystemMusicDataTask().execute();musicListView.setOnItemClickListener(this);}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {Intent intent=new Intent();intent.setClass(ListActivity.this, NetPlayerService.class);intent.setAction("com._MUSIC_SERVICE");stopService(intent);Intent intent2=new Intent(ListActivity.this,PlayActivity.class);intent2.putExtra("position",position);startActivity(intent2);}public class GetSystemMusicDataTask extends AsyncTask<Void,Void,Void>{private String musicjsonstr;@Overrideprotected Void doInBackground(Void... params) {arrayList=MediaUtil.getAllSongs(ListActivity.this);return null;}@Overrideprotected void onPreExecute() {arrayList=new ArrayList<SongBean>();loadingGifView.showAnimation();}@Overrideprotected void onPostExecute(Void aVoid) {loadingGifView.clearAnimation();loadingGifView.setVisibility(View.GONE);musicListAdapter=new MusicListAdapter(arrayList);musicListView.setAdapter(musicListAdapter);}}public class MusicListAdapter extends BaseAdapter{private ArrayList<SongBean> musicBeanArrayList;public MusicListAdapter(ArrayList arrayList){musicBeanArrayList=arrayList;}@Overridepublic int getCount() {return musicBeanArrayList.size();}@Overridepublic Object getItem(int position) {return musicBeanArrayList.get(position);}@Overridepublic long getItemId(int position) {return musicBeanArrayList.get(position).getId();}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder = null;if(convertView==null){convertView= LayoutInflater.from(ListActivity.this).inflate(R.layout.item_song,null);holder = new ViewHolder();holder.nameTextView= (TextView) convertView.findViewById(R.id.name);holder.singerTextView= (TextView) convertView.findViewById(R.id.singer);convertView.setTag(holder);}else{holder = (ViewHolder)convertView.getTag();}holder.singerTextView.setText(musicBeanArrayList.get(position).getArtist());holder.nameTextView.setText(musicBeanArrayList.get(position).getTitle());return convertView;}}public static class ViewHolder {public TextView nameTextView;public TextView singerTextView;}}

3.本地播放的Activity.

PlayActivity.java

在这个Activity里,通过获取专辑图片Bitmap,使用高斯模糊算法,生成模糊后的背景Bitmap,并设置。

注册广播,接受从Service传来的总时长,当前进度等。

在用户按下暂定按钮,上一首,下一首按钮的时候,给Service发MSG,更新Servie里的MediaPlayer操作。

package com.lzw.activity;import android.app.Activity;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.graphics.Bitmap;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.RelativeLayout;import android.widget.SeekBar;import android.widget.SeekBar.OnSeekBarChangeListener;import android.widget.TextView;import android.widget.Toast;import java.util.ArrayList;import com.lzw.bean.SongBean;import com.lzw.lmusicplayer.R;import com.lzw.service.PlayerService;import com.lzw.util.AppConstantUtil;import com.lzw.util.GaussianBlurUtil;import com.lzw.util.MediaUtil;import com.lzw.view.CircleImageView;public class PlayActivity extends Activity implements View.OnClickListener {private Button mPlayPause;private RelativeLayout mBackground ;private CircleImageView mAvatar;private boolean isPlaying; private boolean isPause;private Button mNext;private Button mPrevious;private Bitmap mResource;private static int mCurrentPosition=-1;private Boolean flag;private String url;private SongBean mSongBean;private ArrayList<SongBean> musicInfos;private TextView nameTextView,singerTextView,currentProgress,finalProgress;private SeekBar music_progressBar; private int currentTime;private PlayerReceiver playerReceiver;public static final String UPDATE_ACTION = "com.lzw.action.UPDATE_ACTION";public static final String CTL_ACTION = "com.lzw.action.CTL_ACTION"; public static final String MUSIC_CURRENT = "com.lzw.action.MUSIC_CURRENT"; public static final String MUSIC_DURATION = "com.lzw.action.MUSIC_DURATION";public static final String MUSIC_PLAYING = "com.lzw.action.MUSIC_PLAYING";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_play);Intent intent=getIntent();int position=intent.getIntExtra("position", -1);if(position!=mCurrentPosition){mCurrentPosition=position;flag=true;isPause=false;isPlaying=true;}else {flag=false;isPlaying=true;isPause=false;}musicInfos=MediaUtil.getAllSongs(this);mSongBean=musicInfos.get(mCurrentPosition);mPlayPause = (Button) findViewById(R.id.btn_play_pause);music_progressBar=(SeekBar) this.findViewById(R.id.audioTrack);mBackground = (RelativeLayout) findViewById(R.id.bg);mAvatar = (CircleImageView) findViewById(R.id.avatar);nameTextView=(TextView) this.findViewById(R.id.name);singerTextView=(TextView) this.findViewById(R.id.singer);currentProgress = (TextView) findViewById(R.id.current_progress);finalProgress = (TextView) findViewById(R.id.final_progress);mPlayPause.setOnClickListener(this);mNext = (Button) findViewById(R.id.btn_next);mNext.setOnClickListener(this);mPrevious = (Button) findViewById(R.id.btn_previous);mPrevious.setOnClickListener(this);mResource = MediaUtil.getArtwork(this, mSongBean.getId(), mSongBean.getAlbumId(),true);setViewContent(mResource);nameTextView.setText(mSongBean.getTitle());singerTextView.setText(mSongBean.getArtist());music_progressBar.setMax((int) mSongBean.getDuration());finalProgress.setText(MediaUtil.formatTime(mSongBean.getDuration()));music_progressBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {// TODO Auto-generated method stub}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {// TODO Auto-generated method stub}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {// TODO Auto-generated method stubif (fromUser) {mPlayPause.setBackgroundResource(R.drawable.fm_btn_pause);isPlaying=true;isPause=false;audioTrackChange(progress); }}});playerReceiver = new PlayerReceiver();IntentFilter filter = new IntentFilter();filter.addAction(UPDATE_ACTION);filter.addAction(MUSIC_CURRENT);filter.addAction(MUSIC_DURATION);registerReceiver(playerReceiver, filter);if(flag){play();isPlaying=true;isPause=false;}else{Intent intent2=new Intent(this,PlayerService.class);intent2.putExtra("MSG", AppConstantUtil.PlayerMsg.PLAYING_MSG);intent2.putExtra("position", mCurrentPosition);intent2.setAction("com.lzw.media.MUSIC_SERVICE");startService(intent2);isPlaying=true;isPause=false;}if(isPause){mPlayPause.setBackgroundResource(R.drawable.fm_btn_play);}else{mPlayPause.setBackgroundResource(R.drawable.fm_btn_pause);}}public void setViewContent(Bitmap bitmap){setBackgroundBitmap(bitmap);setAvatarBitmap(bitmap);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn_play_pause:if(isPlaying){pause();}else if (isPause){resume();}else{play();}break;case R.id.btn_previous:mCurrentPosition--;if(mCurrentPosition>=0) {mSongBean=musicInfos.get(mCurrentPosition);nameTextView.setText(mSongBean.getTitle());singerTextView.setText(mSongBean.getArtist());music_progressBar.setProgress(0);mResource = MediaUtil.getArtwork(this, mSongBean.getId(), mSongBean.getAlbumId(), true);previous(mResource);if (isPlaying) {mPlayPause.setBackgroundResource(R.drawable.fm_btn_pause);} else {mPlayPause.setBackgroundResource(R.drawable.fm_btn_play);}}else {mCurrentPosition=0;Toast.makeText(PlayActivity.this, "没有上一首了", Toast.LENGTH_SHORT).show();}break;case R.id.btn_next:mCurrentPosition++;if(mCurrentPosition<musicInfos.size()) {mSongBean=musicInfos.get(mCurrentPosition);nameTextView.setText(mSongBean.getTitle());music_progressBar.setProgress(0);singerTextView.setText(mSongBean.getArtist());mResource = MediaUtil.getArtwork(this, mSongBean.getId(), mSongBean.getAlbumId(), true);next(mResource);if (isPlaying) {mPlayPause.setBackgroundResource(R.drawable.fm_btn_pause);} else {mPlayPause.setBackgroundResource(R.drawable.fm_btn_play);}}else{mCurrentPosition = musicInfos.size() - 1;Toast.makeText(PlayActivity.this, "没有下一首了", Toast.LENGTH_SHORT).show();}break;default:break;}}public void setBackgroundBitmap(Bitmap bitmap){mBackground.setBackgroundDrawable(GaussianBlurUtil.BoxBlurFilter(bitmap));}public void play(){Intent intent = new Intent();intent.setAction("com.lzw.media.MUSIC_SERVICE");intent.setClass(this, PlayerService.class);intent.putExtra("url", mSongBean.getUrl());intent.putExtra("position", mCurrentPosition);intent.putExtra("MSG", AppConstantUtil.PlayerMsg.PLAY_MSG);startService(intent);mPlayPause.setBackgroundResource(R.drawable.fm_btn_pause);isPlaying=true;isPause=false;}public void pause(){Intent intent=new Intent();intent.setClass(PlayActivity.this, PlayerService.class);intent.setAction("com.lzw.media.MUSIC_SERVICE");intent.putExtra("MSG", AppConstantUtil.PlayerMsg.PAUSE_MSG);startService(intent);isPlaying = false;isPause = true;mPlayPause.setBackgroundResource(R.drawable.fm_btn_play);}private void resume(){Intent intent=new Intent();intent.setAction("com.lzw.media.MUSIC_SERVICE");intent.setClass(PlayActivity.this, PlayerService.class);intent.putExtra("MSG", AppConstantUtil.PlayerMsg.CONTINUE_MSG);startService(intent);isPause = false;isPlaying = true;mPlayPause.setBackgroundResource(R.drawable.fm_btn_pause);}public void previous(Bitmap bitmap){//pause();changeImage(bitmap);play();}public void next(Bitmap bitmap) {//pause();changeImage(bitmap);play();}public void setAvatarBitmap(Bitmap bitmap){mAvatar.setImageBitmap(bitmap);}private void changeImage(final Bitmap bitmap){mAvatar.postDelayed(new Runnable() {@Overridepublic void run() {setAvatarBitmap(bitmap);}}, 100);mBackground.postDelayed(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubsetBackgroundBitmap(bitmap);}}, 100);}public void audioTrackChange(int progress) {Intent intent = new Intent();intent.setClass(this, PlayerService.class);intent.setAction("com.lzw.media.MUSIC_SERVICE");intent.putExtra("url", mSongBean.getUrl());intent.putExtra("MSG", AppConstantUtil.PlayerMsg.PROGRESS_CHANGE);intent.putExtra("position", mCurrentPosition);intent.putExtra("progress", progress);startService(intent);}public class PlayerReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (action.equals(MUSIC_CURRENT)) {currentTime = intent.getIntExtra("currentTime", -1);currentProgress.setText(MediaUtil.formatTime(currentTime));music_progressBar.setProgress(currentTime);} else if (action.equals(MUSIC_DURATION)) {int duration = intent.getIntExtra("duration", -1);music_progressBar.setMax(duration);finalProgress.setText(MediaUtil.formatTime(duration));} else if (action.equals(UPDATE_ACTION)) {mCurrentPosition = intent.getIntExtra("current", -1);mSongBean=musicInfos.get(mCurrentPosition);url = mSongBean.getUrl();if (mCurrentPosition >= 0) {nameTextView.setText(mSongBean.getTitle());singerTextView.setText(mSongBean.getArtist());mResource = MediaUtil.getArtwork(PlayActivity.this, mSongBean.getId(), mSongBean.getAlbumId(),true);setViewContent(mResource);}if (mCurrentPosition == 0) {finalProgress.setText(MediaUtil.formatTime(musicInfos.get(mCurrentPosition).getDuration()));mPlayPause.setBackgroundResource(R.drawable.fm_btn_play);isPause = true;}}}}}

4.PlayerServie.java

这个是实现本地播放的Service;

在Servie里既要在Handler里给Activity发广播,传递当前的播放进度和总时长。

又要接受Activity发来的Intent里的动作消息,切换播放状态。

为了实现更新进度,我在Handler里进行消息循环,每隔1000毫秒给PlayActiviy发送一次广播,更新当前的进度。

package com.lzw.service;import java.util.ArrayList;import com.lzw.bean.SongBean;import com.lzw.util.AppConstantUtil;import com.lzw.util.MediaUtil;import android.app.Service;import android.content.Intent;import android.media.MediaPlayer;import android.media.MediaPlayer.OnCompletionListener;import android.media.MediaPlayer.OnPreparedListener;import android.os.Handler;import android.os.IBinder;import android.util.Log;public class PlayerService extends Service{private MediaPlayer mediaPlayer;private String path; private int msg;private boolean isPause; private int mCurrentPosition;private int currentTime;private int duration;private ArrayList<SongBean> mp3Infos;public static final String UPDATE_ACTION = "com.lzw.action.UPDATE_ACTION";public static final String CTL_ACTION = "com.lzw.action.CTL_ACTION";public static final String MUSIC_CURRENT = "com.lzw.action.MUSIC_CURRENT";public static final String MUSIC_DURATION = "com.lzw.action.MUSIC_DURATION";private Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {if (msg.what == 1) {if(mediaPlayer != null) {currentTime = mediaPlayer.getCurrentPosition(); // 获取当前音乐播放的位置Intent intent = new Intent();intent.setAction(MUSIC_CURRENT);intent.putExtra("currentTime", currentTime);sendBroadcast(intent); // 给PlayerActivity发送广播handler.sendEmptyMessageDelayed(1, 1000);}}};};@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubreturn null;}@Overridepublic void onCreate() {super.onCreate();Log.d("service", "service created");mediaPlayer = new MediaPlayer();mp3Infos = MediaUtil.getAllSongs(PlayerService.this);mediaPlayer.setOnCompletionListener(new OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mp) {// TODO Auto-generated method stubmCurrentPosition++;Log.v("po", mCurrentPosition+"");if (mCurrentPosition <= mp3Infos.size() - 1) {Intent sendIntent = new Intent(UPDATE_ACTION);sendIntent.putExtra("current", mCurrentPosition);sendBroadcast(sendIntent);path = mp3Infos.get(mCurrentPosition).getUrl();play(0);}else {mediaPlayer.seekTo(0);mCurrentPosition = 0;Intent sendIntent = new Intent(UPDATE_ACTION);sendIntent.putExtra("current", mCurrentPosition);sendBroadcast(sendIntent);}}});}@Overridepublic void onStart(Intent intent, int startId) {if(intent==null){stopSelf();}else{path = intent.getStringExtra("url");msg = intent.getIntExtra("MSG", 0);mCurrentPosition=intent.getIntExtra("position",-1);if (msg == AppConstantUtil.PlayerMsg.PLAY_MSG) {play(0);} else if (msg == AppConstantUtil.PlayerMsg.PAUSE_MSG) {pause();} else if (msg == AppConstantUtil.PlayerMsg.STOP_MSG) {stop();} else if (msg == AppConstantUtil.PlayerMsg.CONTINUE_MSG) {resume();} else if (msg == AppConstantUtil.PlayerMsg.PROGRESS_CHANGE) {currentTime = intent.getIntExtra("progress", -1);play(currentTime);} else if (msg == AppConstantUtil.PlayerMsg.PLAYING_MSG) {handler.sendEmptyMessage(1);}super.onStart(intent, startId);}}private void play(int currentTime) {try {mediaPlayer.reset();mediaPlayer.setDataSource(path);mediaPlayer.prepare(); mediaPlayer.setOnPreparedListener(new PreparedListener(currentTime));handler.sendEmptyMessage(1);} catch (Exception e) {e.printStackTrace();}}private void pause() {if (mediaPlayer != null && mediaPlayer.isPlaying()) {mediaPlayer.pause();isPause = true;}}private void resume() {if (isPause) {mediaPlayer.start();isPause = false;}}private void stop() {if (mediaPlayer != null) {mediaPlayer.stop();try {mediaPlayer.prepare(); } catch (Exception e) {e.printStackTrace();}}}private final class PreparedListener implements OnPreparedListener {private int currentTime;public PreparedListener(int currentTime) {this.currentTime = currentTime;}@Overridepublic void onPrepared(MediaPlayer mp) {mediaPlayer.start(); if (currentTime > 0) { mediaPlayer.seekTo(currentTime);}Intent intent = new Intent();intent.setAction(MUSIC_DURATION);duration = mediaPlayer.getDuration();intent.putExtra("duration", duration);sendBroadcast(intent);}}@Overridepublic void onDestroy() {if (mediaPlayer != null) {mediaPlayer.stop();mediaPlayer.release();mediaPlayer = null;}}}

5.存储歌曲实体的Bean

package com.lzw.bean;import java.io.Serializable;public class SongBean implements Serializable {private long id; private String title; private String album; private long albumId;private String displayName; private String artist; private long duration;private long size; private String url; public SongBean() {}public SongBean(long id, String title, String album, long albumId,String displayName, String artist, long duration, long size,String url, String lrcTitle, String lrcSize) {super();this.id = id;this.title = title;this.album = album;this.albumId = albumId;this.displayName = displayName;this.artist = artist;this.duration = duration;this.size = size;this.url = url;}public long getId() {return id;}public void setId(long id) {this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getAlbum() {return album;}public void setAlbum(String album) {this.album = album;}public long getAlbumId() {return albumId;}public void setAlbumId(long albumId) {this.albumId = albumId;}public String getArtist() {return artist;}public void setArtist(String artist) {this.artist = artist;}public long getDuration() {return duration;}public void setDuration(long duration) {this.duration = duration;}public long getSize() {return size;}public void setSize(long size) {this.size = size;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getDisplayName() {return displayName;}public void setDisplayName(String displayName) {this.displayName = displayName;}}

本地音乐的关键代码就是这些。

接下来看在线播放的关键部分。

首先,服务端的测试接口是我自己写的

需要的注意的是,获得out对象是要在设置了response的编码后再获得,一定要注意这一点,不然会出现中文乱码的情况。

为了下拉刷新与上拉加载的功能,我设了一个page参数。

Server部分

IMusicList.java

package com.lzw.mobVod.interfac;import java.io.IOException;import java.io.PrintWriter;import java.util.ArrayList;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.google.gson.Gson;import com.lzw.mobVod.bean.MusicBean;public class IMusicList extends HttpServlet{/* (non-Javadoc)* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)*/@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// TODO Auto-generated method stub}/* (non-Javadoc)* @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)*/@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// TODO Auto-generated method stubresp.setContentType("text/html;charset=UTF-8");resp.setCharacterEncoding("UTF-8");resp.setHeader("ContentType","text/html;charset=UTF-8");req.setCharacterEncoding("UTF-8");PrintWriter out=resp.getWriter();Gson gson=new Gson();ArrayList<MusicBean> arrayList=new ArrayList<>();int page=Integer.parseInt(req.getParameter("page"));for(int i=10*(page-1);i<10*page;i++) {MusicBean bean=new MusicBean();bean.setMusic_name("陌生人"+i);bean.setMusic_singer("蔡健雅"+i);bean.setMusic_id(i+"");bean.setMusic_cover_url("http://xxx.xx.xx.xxx:8080/mobVod/img/music_icon.jpg");//改成自己的服务器地址bean.setMusic_url("http://xxx.xx.xx.xx:8080/mobVod/music/hongsegaogenxie.mp3");arrayList.add(bean);}String jsonstr=gson.toJson(arrayList);out.print(jsonstr);}}

客户端接收接口并在XListView中显示,下拉刷新与上拉加载

NetPlayActivity.java

package com.lzw.activity;import java.util.ArrayList;import java.util.HashMap;import java.util.Map;import com.android.volley.Request;import com.android.volley.RequestQueue;import com.android.volley.Response;import com.android.volley.VolleyError;import com.android.volley.toolbox.StringRequest;import com.android.volley.toolbox.Volley;import com.google.gson.Gson;import com.google.gson.reflect.TypeToken;import com.PlayActivity.PlayerReceiver;import com.SongBean;import com.lzw.lmusicplayer.R;import com.lzw.service.PlayerService;import com.lzw.util.AppConstantUtil;import com.lzw.view.XListView;import com.lzw.view.XListView.IXListViewListener;import android.app.Activity;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.os.Bundle;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.BaseAdapter;import android.widget.TextView;public class NetListActivity extends Activity{private XListView musicListView;private ArrayList<NetSongBean> arrayList;private MusicListAdapter musicListAdapter;private int page=1;private final String URL="http://xxx.xx.xx.xxx:8080/mobVod/IMusicList.do";private RequestQueue mRequestQueue; public static final String MUSIC_DURATION = "com._MUSIC_DURATION";//新音乐长度更新动作private ListReceiver mListReceiver;private Gson gson;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_netlist);musicListView=(XListView) this.findViewById(R.id.musiclist);arrayList=new ArrayList<NetSongBean>();gson=new Gson();musicListView.setPullLoadEnable(true);musicListView.setPullRefreshEnable(true);mRequestQueue = Volley.newRequestQueue(this);getNetData();musicListView.setXListViewListener(new IXListViewListener() {@Overridepublic void onRefresh() {// TODO Auto-generated method stubpage++;getNetData();}@Overridepublic void onLoadMore() {// TODO Auto-generated method stubpage++;getNetData();musicListView.smoothScrollToPosition(musicListView.getCount() - 1);}});musicListView.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {// TODO Auto-generated method stubIntent intent=new Intent();intent.setClass(NetListActivity.this, PlayerService.class);intent.setAction("com.lzw.media.MUSIC_SERVICE");stopService(intent);Intent intent2=new Intent(NetListActivity.this,NetPlayActivity.class);intent2.putExtra("netmusicitem", arrayList.get(position-1));intent2.putExtra("position", position-1);startActivity(intent2);}});mListReceiver = new ListReceiver();IntentFilter filter = new IntentFilter();filter.addAction(MUSIC_DURATION);registerReceiver(mListReceiver, filter);}private void onLoad() {musicListView.stopRefresh();musicListView.stopLoadMore();}private void getNetData(){RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());StringRequest stringRequest = new StringRequest(Request.Method.POST,URL,new Response.Listener<String>() {@Overridepublic void onResponse(String response) {Log.d("re", "response -> " + response);arrayList.addAll((ArrayList<NetSongBean>)gson.fromJson(response, new TypeToken<ArrayList<NetSongBean>>(){}.getType()));musicListAdapter=new MusicListAdapter(arrayList);musicListView.setAdapter(musicListAdapter);onLoad();}}, new Response.ErrorListener() {@Overridepublic void onErrorResponse(VolleyError error) {Log.e("er", error.getMessage(), error);}}) {@Overrideprotected Map<String, String> getParams() {//在这里设置需要post的参数Map<String, String> map = new HashMap<String, String>(); map.put("page", page+""); return map;}}; requestQueue.add(stringRequest);}public class MusicListAdapter extends BaseAdapter{private ArrayList<NetSongBean> musicBeanArrayList;public MusicListAdapter(ArrayList arrayList){musicBeanArrayList=arrayList;}@Overridepublic int getCount() {return musicBeanArrayList.size();}@Overridepublic Object getItem(int position) {return musicBeanArrayList.get(position);}@Overridepublic long getItemId(int position) {return Integer.parseInt(musicBeanArrayList.get(position).getMusic_id());}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder = null;if(convertView==null){convertView= LayoutInflater.from(NetListActivity.this).inflate(R.layout.item_song,null);holder = new ViewHolder();holder.nameTextView= (TextView) convertView.findViewById(R.id.name);holder.singerTextView= (TextView) convertView.findViewById(R.id.singer);convertView.setTag(holder);}else{holder = (ViewHolder)convertView.getTag();}holder.singerTextView.setText(musicBeanArrayList.get(position).getMusic_name());holder.nameTextView.setText(musicBeanArrayList.get(position).getMusic_singer());return convertView;}}public static class ViewHolder {public TextView nameTextView;public TextView singerTextView;}public class ListReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {// TODO Auto-generated method stubString action=intent.getAction();if(action.equals(MUSIC_DURATION)){int pos=intent.getIntExtra("pos", -1);int dura=intent.getIntExtra("duration", 1);if(pos>0&&dura>0){arrayList.get(pos).setDuration(dura);}}}}}

可以发现,歌曲的时长在接口里的json中并没有数据,我通过在Service播放一首歌时,MediaPlayer获得当前播放歌曲的时长,发送广播,让两个NetPlayActivity和NetListActivity都接受到,在播放界面的NetPlayActivity里收到歌曲市场后,设置Textview的text值,同时为了保证在播放过程中下一次点同一个Postion能跳转到之前的播放界面,让数据保持之前的状态,在ListActivity收到广播后,更新对应的NetSongBean的duartion属性。

存储网络在线歌曲信息的实体Bean

NetSongBean.java

package com.lzw.bean;import java.io.Serializable;public class NetSongBean implements Serializable {private String music_id;public String getMusic_id() {return music_id;}public void setMusic_id(String music_id) {this.music_id = music_id;}public String getMusic_name() {return music_name;}public void setMusic_name(String music_name) {this.music_name = music_name;}public String getMusic_cover_url() {return music_cover_url;}public void setMusic_cover_url(String music_cover_url) {this.music_cover_url = music_cover_url;}public String getMusic_url() {return music_url;}public void setMusic_url(String music_url) {this.music_url = music_url;}public String getMusic_singer() {return music_singer;}public void setMusic_singer(String music_singer) {this.music_singer = music_singer;}private String music_name;private String music_cover_url;private String music_url;private String music_singer;private int duration=-1;public void setDuration(int duration) {this.duration = duration;}public int getDuration() {return duration;}}

接下来就是最关键的NetPlayService,实现了在线播放音乐的Service.

NetPlayService.java

这个Servce实现了接口OnBufferingUpdateListener。

当网络音频开始加载的时候,每次更新一次进度,会在回掉函数里更新一次当前的百分比。此时Service给Activity发送广播,根据缓冲百分比,歌曲总时长,来设置SeekBar的SecondaryProgress的值。同时,Servie里接受用户拖动进度条后的Progress值,Activity发给Service,Servie收到后,判断这个值是否在已缓冲的范围内,如果在的话,mediaplayer.seekto一下。实现拖动进度播放。

package com.lzw.service;import java.io.IOException;import java.util.Timer;import java.util.TimerTask;import com.lzw.util.AppConstantUtil;import android.R.integer;import android.app.Service;import android.content.Intent;import android.media.AudioManager;import android.media.MediaPlayer;import android.media.MediaPlayer.OnBufferingUpdateListener;import android.media.MediaPlayer.OnCompletionListener;import android.media.MediaPlayer.OnPreparedListener;import android.os.Handler;import android.os.IBinder;import android.util.Log;public class NetPlayerService extends Service implements OnBufferingUpdateListener, OnCompletionListener,OnPreparedListener {public MediaPlayer mediaPlayer;private int currentTime;private int duration;private int mCurrentPosition;private int msg;private boolean isPause;private String url;private int percent;public static final String MUSIC_CURRENT = "com._MUSIC_CURRENT";public static final String MUSIC_DURATION = "com._MUSIC_DURATION";public static final String MUSIC_PERCENT="com._MUSIC_PERCENT";private Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {if (msg.what == 0) {if(mediaPlayer != null) {currentTime = mediaPlayer.getCurrentPosition(); Intent intent = new Intent();intent.setAction(MUSIC_CURRENT);intent.putExtra("currentTime", currentTime);sendBroadcast(intent); handler.sendEmptyMessageDelayed(0, 1000);}}if(msg.what==1){duration = mediaPlayer.getDuration();if (duration > 0) {Intent intent = new Intent();intent.setAction(MUSIC_DURATION);intent.putExtra("pos", mCurrentPosition);Log.v("DUA", duration+"");intent.putExtra("duration", duration);sendBroadcast(intent); }}if(msg.what==2){Intent intent=new Intent();intent.setAction(MUSIC_PERCENT);intent.putExtra("percent", percent);sendBroadcast(intent);}};};@Overridepublic void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();if (mediaPlayer != null) {mediaPlayer.stop();mediaPlayer.release();mediaPlayer = null;}}@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();try {mediaPlayer = new MediaPlayer();mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);mediaPlayer.setOnBufferingUpdateListener(this);mediaPlayer.setOnPreparedListener(this);} catch (Exception e) {e.printStackTrace();}}private void play(int currentTime) {try {mediaPlayer.reset();mediaPlayer.setDataSource(url); mediaPlayer.prepare(); mediaPlayer.setOnPreparedListener(this);handler.sendEmptyMessage(0);handler.sendEmptyMessage(1);} catch (Exception e) {e.printStackTrace();}}@Overridepublic void onStart(Intent intent, int flags) {// TODO Auto-generated method stubif(intent==null){stopSelf();}url=intent.getStringExtra("url");msg = intent.getIntExtra("MSG", 0);mCurrentPosition=intent.getIntExtra("position",-1);if (msg == AppConstantUtil.PlayerMsg.PLAY_MSG) {play(0);} else if(msg==AppConstantUtil.PlayerMsg.PROGRESS_CHANGE){currentTime = intent.getIntExtra("progress", -1);if(currentTime>0&¤tTime<=(percent*duration/100)){mediaPlayer.seekTo(currentTime);handler.sendEmptyMessage(1);//play(currentTime);}}else if (msg == AppConstantUtil.PlayerMsg.PLAYING_MSG) {handler.sendEmptyMessage(0);}else if (msg == AppConstantUtil.PlayerMsg.PAUSE_MSG) {pause();} else if (msg == AppConstantUtil.PlayerMsg.STOP_MSG) {stop();} else if (msg == AppConstantUtil.PlayerMsg.CONTINUE_MSG) {resume();}return;}private void pause() {if (mediaPlayer != null && mediaPlayer.isPlaying()) {mediaPlayer.pause();isPause = true;}}private void resume() {if (isPause) {mediaPlayer.start();isPause = false;}}/*** 停止音乐*/private void stop() {if (mediaPlayer != null) {mediaPlayer.stop();try {mediaPlayer.prepare(); } catch (Exception e) {e.printStackTrace();}}}@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubreturn null;}@Overridepublic void onPrepared(MediaPlayer mp) {mediaPlayer.start();Intent intent = new Intent();intent.setAction(MUSIC_DURATION);duration = mediaPlayer.getDuration();intent.putExtra("duration", duration);Log.v("duran", duration+"");sendBroadcast(intent);}@Overridepublic void onCompletion(MediaPlayer mp) {Log.e("mediaPlayer", "onCompletion");}@Overridepublic void onBufferingUpdate(MediaPlayer mp, int perc) {percent=perc;handler.sendEmptyMessage(2);}}

在线播放界面

NetPlayActivity.java

接收广播与发送广播。

package com.lzw.activity;import com.android.volley.RequestQueue;import com.android.volley.Response;import com.android.volley.VolleyError;import com.android.volley.toolbox.ImageRequest;import com.android.volley.toolbox.Volley;import com.bumptech.glide.Glide;import com.bumptech.glide.load.Transformation;import com.bumptech.glide.request.animation.GlideAnimation;import com.bumptech.glide.request.target.SimpleTarget;import com.lzw.activity.PlayActivity.PlayerReceiver;import com.SongBean;import com.lzw.lmusicplayer.R;import com.PlayerService;import com.lzw.service.PlayerService;import com.lzw.util.AppConstantUtil;import com.lzw.util.GaussianBlurUtil;import com.lzw.util.MediaUtil;import com.PlayerUtil;import com.lzw.view.CircleImageView;import android.app.Activity;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.content.SharedPreferences;import android.graphics.Bitmap;import android.graphics.Bitmap.Config;import android.graphics.drawable.BitmapDrawable;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.support.v4.widget.SimpleCursorAdapter.ViewBinder;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.RelativeLayout;import android.widget.SeekBar;import android.widget.TextView;import android.widget.SeekBar.OnSeekBarChangeListener;import android.widget.Toast;public class NetPlayActivity extends Activity implements OnClickListener{private static int mCurrentPosition=-1;private Boolean flag;private Button playBtn;private RelativeLayout mBackground;private CircleImageView mAvatar;private SeekBar musicProgress;private RequestQueue mQueue;private boolean isPlaying; private boolean isPause; private NetSongBean mNetSongBean;private int currentTime;private TextView nameTextView,singerTextView,currentProgress,finalProgress;public static final String UPDATE_ACTION = "com._UPDATE_ACTION"; public static final String CTL_ACTION = "com._CTL_ACTION"; public static final String MUSIC_CURRENT = "com._MUSIC_CURRENT";public static final String MUSIC_DURATION = "com._MUSIC_DURATION";public static final String MUSIC_PERCENT="com._MUSIC_PERCENT";private PlayerReceiver playerReceiver;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_netplay);playBtn = (Button) findViewById(R.id.btn_online_play);mBackground = (RelativeLayout) findViewById(R.id.bg);mAvatar = (CircleImageView) findViewById(R.id.avatar);nameTextView=(TextView) this.findViewById(R.id.name);singerTextView=(TextView) this.findViewById(R.id.singer);currentProgress = (TextView) findViewById(R.id.current_progress);finalProgress = (TextView) findViewById(R.id.final_progress);musicProgress = (SeekBar) findViewById(R.id.audioTrack);Intent intent=getIntent();mNetSongBean=(NetSongBean) intent.getSerializableExtra("netmusicitem");int position=intent.getIntExtra("position", -1);if(isPlaying){if(position!=mCurrentPosition){mCurrentPosition=position;flag=true;isPlaying=true;isPause=false;}else {flag=false;isPause=false;isPlaying=true;}}else{if(position!=mCurrentPosition){mCurrentPosition=position;flag=true;isPlaying=true;isPause=false;}else {flag=false;isPause=true;isPlaying=false;}}nameTextView.setText(mNetSongBean.getMusic_name());singerTextView.setText(mNetSongBean.getMusic_singer());playBtn.setOnClickListener(this);musicProgress.setOnSeekBarChangeListener(new SeekBarChangeEvent());if(mNetSongBean.getDuration()>0){finalProgress.setText(MediaUtil.formatTime(mNetSongBean.getDuration()));musicProgress.setMax(mNetSongBean.getDuration());}Glide.with(this).load(mNetSongBean.getMusic_cover_url()).into(mAvatar);mQueue=Volley.newRequestQueue(this);mBackground.postDelayed(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubImageRequest imageRequest = new ImageRequest( mNetSongBean.getMusic_cover_url(), new Response.Listener<Bitmap>() { @SuppressWarnings("deprecation")@Override public void onResponse(Bitmap response) { //Glide.with(NetPlayActivity.this).load(mNetSongBean.getMusic_cover_url()).into(mAvatar);mBackground.setBackgroundDrawable(GaussianBlurUtil.BoxBlurFilter(response));} }, 0, 0, Config.RGB_565, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }); mQueue.add(imageRequest); }}, 1500);playerReceiver = new PlayerReceiver();IntentFilter filter = new IntentFilter();filter.addAction(UPDATE_ACTION);filter.addAction(MUSIC_CURRENT);filter.addAction(MUSIC_DURATION);filter.addAction(MUSIC_PERCENT);registerReceiver(playerReceiver, filter);if(flag){play();isPlaying=true;isPause=false;}else{isPlaying=true;isPause=false;}if(isPause){playBtn.setBackgroundResource(R.drawable.fm_btn_play);}else{playBtn.setBackgroundResource(R.drawable.fm_btn_pause);}}public class PlayerReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (action.equals(MUSIC_CURRENT)) {currentTime = intent.getIntExtra("currentTime", -1);currentProgress.setText(MediaUtil.formatTime(currentTime));musicProgress.setProgress(currentTime);} else if (action.equals(MUSIC_DURATION)) {int duration = intent.getIntExtra("duration", -1);Log.v("dura", duration+"");musicProgress.setMax(duration);if(mNetSongBean.getDuration()==-1){mNetSongBean.setDuration(duration);}finalProgress.setText(MediaUtil.formatTime(duration));}else if(action.equals(MUSIC_PERCENT)){int percent=intent.getIntExtra("percent",-1);musicProgress.setSecondaryProgress(musicProgress.getMax()*percent/100);}}}private void play(){Intent intent = new Intent();intent.setAction("com._MUSIC_SERVICE");intent.setClass(this,NetPlayerService.class);intent.putExtra("url", mNetSongBean.getMusic_url());intent.putExtra("position", mCurrentPosition);intent.putExtra("MSG", AppConstantUtil.PlayerMsg.PLAY_MSG);startService(intent);isPlaying=true;isPause=false;}class SeekBarChangeEvent implements OnSeekBarChangeListener {@Overridepublic void onProgressChanged(SeekBar seekBar, int progre,boolean fromUser) {currentTime=progre; }@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {Intent intent = new Intent();intent.setClass(NetPlayActivity.this, NetPlayerService.class);intent.setAction("com._MUSIC_SERVICE");intent.putExtra("url", mNetSongBean.getMusic_url());intent.putExtra("MSG", AppConstantUtil.PlayerMsg.PROGRESS_CHANGE);intent.putExtra("position", mCurrentPosition);intent.putExtra("progress", currentTime);startService(intent);}}@Overrideprotected void onDestroy() {super.onDestroy();}public void pause(){Intent intent=new Intent();intent.setClass(NetPlayActivity.this, NetPlayerService.class);intent.setAction("com._MUSIC_SERVICE");intent.putExtra("MSG", AppConstantUtil.PlayerMsg.PAUSE_MSG);startService(intent);isPlaying = false;isPause = true;playBtn.setBackgroundResource(R.drawable.fm_btn_play);}private void resume(){Intent intent=new Intent();intent.setAction("com._MUSIC_SERVICE");intent.setClass(NetPlayActivity.this, NetPlayerService.class);intent.putExtra("MSG", AppConstantUtil.PlayerMsg.CONTINUE_MSG);startService(intent);isPause = false;isPlaying = true;playBtn.setBackgroundResource(R.drawable.fm_btn_pause);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn_online_play:if(isPlaying&&!isPause){pause();Log.v("clickpause", isPlaying+""+isPause);}else if (isPause&&!isPlaying){resume();Log.v("clickresume", isPlaying+""+isPause);}else{Log.v("clickplay", isPlaying+""+isPause);play();}break;}}}

整个做法大体就是这样了,最后放一个高斯模糊算法。

package com.lzw.util;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.PixelFormat;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;public class GaussianBlurUtil {private static float hRadius = 10;private static float vRadius = 10;private static int iterations = 7;public static Drawable BoxBlurFilter(Bitmap bmp) {int width = bmp.getWidth();int height = bmp.getHeight();int[] inPixels = new int[width * height];int[] outPixels = new int[width * height];Bitmap bitmap = Bitmap.createBitmap(width, height,Bitmap.Config.ARGB_8888);bmp.getPixels(inPixels, 0, width, 0, 0, width, height);for (int i = 0; i < iterations; i++) {blur(inPixels, outPixels, width, height, hRadius);blur(outPixels, inPixels, height, width, vRadius);}blurFractional(inPixels, outPixels, width, height, hRadius);blurFractional(outPixels, inPixels, height, width, vRadius);bitmap.setPixels(inPixels, 0, width, 0, 0, width, height);Drawable drawable = new BitmapDrawable(bitmap);return drawable;}public static Bitmap BoxBlurFilterBitmap(Bitmap bmp) {int width = bmp.getWidth();int height = bmp.getHeight();int[] inPixels = new int[width * height];int[] outPixels = new int[width * height];Bitmap bitmap = Bitmap.createBitmap(width, height,Bitmap.Config.ARGB_8888);bmp.getPixels(inPixels, 0, width, 0, 0, width, height);for (int i = 0; i < iterations; i++) {blur(inPixels, outPixels, width, height, hRadius);blur(outPixels, inPixels, height, width, vRadius);}blurFractional(inPixels, outPixels, width, height, hRadius);blurFractional(outPixels, inPixels, height, width, vRadius);bitmap.setPixels(inPixels, 0, width, 0, 0, width, height);return bitmap;}public static void blur(int[] in, int[] out, int width, int height,float radius) {int widthMinus1 = width - 1;int r = (int) radius;int tableSize = 2 * r + 1;int divide[] = new int[256 * tableSize];for (int i = 0; i < 256 * tableSize; i++)divide[i] = i / tableSize;int inIndex = 0;for (int y = 0; y < height; y++) {int outIndex = y;int ta = 0, tr = 0, tg = 0, tb = 0;for (int i = -r; i <= r; i++) {int rgb = in[inIndex + clamp(i, 0, width - 1)];ta += (rgb >> 24) & 0xff;tr += (rgb >> 16) & 0xff;tg += (rgb >> 8) & 0xff;tb += rgb & 0xff;}for (int x = 0; x < width; x++) {out[outIndex] = (divide[ta] << 24) | (divide[tr] << 16)| (divide[tg] << 8) | divide[tb];int i1 = x + r + 1;if (i1 > widthMinus1)i1 = widthMinus1;int i2 = x - r;if (i2 < 0)i2 = 0;int rgb1 = in[inIndex + i1];int rgb2 = in[inIndex + i2];ta += ((rgb1 >> 24) & 0xff) - ((rgb2 >> 24) & 0xff);tr += ((rgb1 & 0xff0000) - (rgb2 & 0xff0000)) >> 16;tg += ((rgb1 & 0xff00) - (rgb2 & 0xff00)) >> 8;tb += (rgb1 & 0xff) - (rgb2 & 0xff);outIndex += height;}inIndex += width;}}public static void blurFractional(int[] in, int[] out, int width,int height, float radius) {radius -= (int) radius;float f = 1.0f / (1 + 2 * radius);int inIndex = 0;for (int y = 0; y < height; y++) {int outIndex = y;out[outIndex] = in[0];outIndex += height;for (int x = 1; x < width - 1; x++) {int i = inIndex + x;int rgb1 = in[i - 1];int rgb2 = in[i];int rgb3 = in[i + 1];int a1 = (rgb1 >> 24) & 0xff;int r1 = (rgb1 >> 16) & 0xff;int g1 = (rgb1 >> 8) & 0xff;int b1 = rgb1 & 0xff;int a2 = (rgb2 >> 24) & 0xff;int r2 = (rgb2 >> 16) & 0xff;int g2 = (rgb2 >> 8) & 0xff;int b2 = rgb2 & 0xff;int a3 = (rgb3 >> 24) & 0xff;int r3 = (rgb3 >> 16) & 0xff;int g3 = (rgb3 >> 8) & 0xff;int b3 = rgb3 & 0xff;a1 = a2 + (int) ((a1 + a3) * radius);r1 = r2 + (int) ((r1 + r3) * radius);g1 = g2 + (int) ((g1 + g3) * radius);b1 = b2 + (int) ((b1 + b3) * radius);a1 *= f;r1 *= f;g1 *= f;b1 *= f;out[outIndex] = (a1 << 24) | (r1 << 16) | (g1 << 8) | b1;outIndex += height;}out[outIndex] = in[width - 1];inIndex += width;}}public static int clamp(int x, int a, int b) {return (x < a) ? a : (x > b) ? b : x;}public static Bitmap drawableToBitmap(Drawable drawable) {Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight(),drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888: Bitmap.Config.RGB_565);Canvas canvas = new Canvas(bitmap);drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());drawable.draw(canvas);return bitmap;}}

基本上Android的四大组件在这里全都用上了。

分享一下。工程源码就不传了。

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