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

来源:互联网 发布:ibm人工智能医学 编辑:程序博客网 时间:2024/04/29 22:45

项目里需要做一个类似于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 android.net.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.lzw.service.NetPlayerService;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;    @Override    protected 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);    }    @Override    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {    Intent intent=new Intent();    intent.setClass(ListActivity.this, NetPlayerService.class);    intent.setAction("com.lzw.media.NET_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;        @Override        protected Void doInBackground(Void... params) {        arrayList=MediaUtil.getAllSongs(ListActivity.this);            return null;        }        @Override        protected void onPreExecute() {            arrayList=new ArrayList<SongBean>();            loadingGifView.showAnimation();        }        @Override        protected 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;        }        @Override        public int getCount() {            return musicBeanArrayList.size();        }        @Override        public Object getItem(int position) {            return musicBeanArrayList.get(position);        }        @Override        public long getItemId(int position) {            return musicBeanArrayList.get(position).getId();        }        @Override        public 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";    @Override    protected 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);}        @Override    public 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.lzw.activity.NetPlayActivity.PlayerReceiver;import com.lzw.bean.NetSongBean;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.lzw.action.NET_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>() {        @Override        public 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() {        @Override        public void onErrorResponse(VolleyError error) {            Log.e("er", error.getMessage(), error);        }    }) {    @Override    protected 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;        }        @Override        public int getCount() {            return musicBeanArrayList.size();        }        @Override        public Object getItem(int position) {            return musicBeanArrayList.get(position);        }        @Override        public long getItemId(int position) {            return Integer.parseInt(musicBeanArrayList.get(position).getMusic_id());        }        @Override        public 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.lzw.action.NET_MUSIC_CURRENT";public static final String MUSIC_DURATION = "com.lzw.action.NET_MUSIC_DURATION";public static final String MUSIC_PERCENT="com.lzw.action.NET_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.lzw.bean.NetSongBean;import com.lzw.lmusicplayer.R;import com.lzw.service.NetPlayerService;import com.lzw.service.PlayerService;import com.lzw.util.AppConstantUtil;import com.lzw.util.GaussianBlurUtil;import com.lzw.util.MediaUtil;import com.lzw.util.NetPlayerUtil;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.lzw.action.NET_UPDATE_ACTION"; public static final String CTL_ACTION = "com.lzw.action.NET_CTL_ACTION"; public static final String MUSIC_CURRENT = "com.lzw.action.NET_MUSIC_CURRENT";public static final String MUSIC_DURATION = "com.lzw.action.NET_MUSIC_DURATION";public static final String MUSIC_PERCENT="com.lzw.action.NET_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.lzw.media.NET_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.lzw.media.NET_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.lzw.media.NET_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.lzw.media.NET_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的四大组件在这里全都用上了。

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



1 0
原创粉丝点击