这是去年大二做的一个简单音乐播放器项目:是尽可能模仿酷狗音乐写的,具体实现的功能如下:
1:启动动画:点击运行程序会出现一个两秒钟的视频,类似酷狗音乐的启动动画一样,非常可观!
2:登录注册界面:输入账号和密码检验信息登录!
3:轮播图:和酷狗音乐的一模一样,在主界面的上方有一个自动循环的轮播图,点击轮播图的每一个图片信息即可进入对应的具体服务,非常具有加分点!
4:音乐唱片的转盘,歌曲同步进度条,以及音乐的暂停/播放/继续/上下歌曲切换!
5:音乐的搜索实现!
6:视频专栏的播放!
7;个人信息界面的布局实现,如反馈,评分,更多,性别年龄昵称,收藏等!
音乐唱片的转盘,歌曲同步进度条,以及音乐的暂停/播放/继续/上下歌曲切换代码如下:
MusicService.java
package com.ypc.xiaoxiongmusic;import android.app.Service;import android.content.Intent;import android.media.MediaPlayer;import .Uri;import android.os.Binder;import android.os.Bundle;import android.os.IBinder;import android.os.Message;import java.util.Timer;import java.util.TimerTask;public class MusicService extends Service {private MediaPlayer player;private Timer timer;//引入⏲@Override//构造public IBinder onBind(Intent intent){return new MusicControl();}@Overridepublic void onCreate(){super.onCreate();player=new MediaPlayer();//创建音乐播放器对象}public void addTimer(){ //添加计时器用于设置音乐播放器中的播放进度条if(timer==null){timer=new Timer();//创建计时器对象TimerTask task=new TimerTask() {@Overridepublic void run() {if (player==null) return;int duration=player.getDuration();//获取歌曲总时长int currentPosition=player.getCurrentPosition();//获取当前播放进度Message msg=Music_Activity.handler.obtainMessage();//创建消息对象//将音乐的总时长和播放进度封装至消息对象中//用getcurrentduration,和getduration获取时间,用bundle封装,handler线程传递Bundle bundle=new Bundle();bundle.putInt("duration",duration);bundle.putInt("currentPosition",currentPosition);msg.setData(bundle);//将消息发送到主线程的消息队列Music_Activity.handler.sendMessage(msg);}};//开始计时任务后的5毫秒,第一次执行task任务,以后每500毫秒执行一次timer.schedule(task,5,500);}}class MusicControl extends Binder{//Binder是一种跨进程的通信方式public void play(int i){//String pathUri uri=null;switch(i) {case 0:uri = Uri.parse("/song/media/outer/url?id=5316513.mp3");break;case 1:uri = Uri.parse("/song/media/outer/url?id=409646185.mp3");break;case 2:uri= Uri.parse("/song/media/outer/url?id=26125687.mp3");break;case 3:uri = Uri.parse("/song/media/outer/url?id=516358417.mp3");break;case 4: uri = Uri.parse("/song/media/outer/url?id=1492886765.mp3");break;case 5: uri = Uri.parse("/song/media/outer/url?id=1436910205.mp3");break;case 6: uri = Uri.parse("/song/media/outer/url?id=1399533630.mp3");break;case 7: uri = Uri.parse("/song/media/outer/url?id=32835565.mp3");break;case 8: uri = Uri.parse("/song/media/outer/url?id=1422992414.mp3");break;case 9: uri = Uri.parse("/song/media/outer/url?id=29004400.mp3");break;case 10: uri = Uri.parse("/song/media/outer/url?id=1439111141.mp3");break;case 11: uri = Uri.parse("/song/media/outer/url?id=29418041.mp3");break;case 12: uri = Uri.parse("/song/media/outer/url?id=472137749.mp3");break;case 13: uri = Uri.parse("/song/media/outer/url?id=507364050.mp3");break;case 14: uri = Uri.parse("/song/media/outer/url?id=426291338.mp3");break;case 15: uri = Uri.parse("/song/media/outer/url?id=34228112.mp3");break;case 16: uri = Uri.parse("/song/media/outer/url?id=1428605192.mp3");break;case 17: uri = Uri.parse("/song/media/outer/url?id=33190545.mp3");break;case 18: uri = Uri.parse("/song/media/outer/url?id=32619105.mp3");break;case 19: uri = Uri.parse("/song/media/outer/url?id=1425643256.mp3");break;case 20: uri = Uri.parse("/song/media/outer/url?id=1305366556.mp3");break;case 21: uri = Uri.parse("/song/media/outer/url?id=481859794.mp3");break;case 22: uri = Uri.parse("/song/media/outer/url?id=1424537185.mp3");break;case 23: uri = Uri.parse("/song/media/outer/url?id=1403445370.mp3");break;case 24: uri = Uri.parse("/song/media/outer/url?id=36668004.mp3");break;case 25: uri = Uri.parse("/song/media/outer/url?id=548650088.mp3");break;case 26: uri = Uri.parse("/song/media/outer/url?id=1409296047.mp3");break;case 27: uri = Uri.parse("/song/media/outer/url?id=1389152878.mp3");break;case 28: uri = Uri.parse("/song/media/outer/url?id=475279382.mp3");break;case 29: uri = Uri.parse("/song/media/outer/url?id=1464390595.mp3");break;case 30: uri = Uri.parse("/song/media/outer/url?id=1464389589.mp3");break;case 31: uri = Uri.parse("/song/media/outer/url?id=1464446728.mp3");break;case 32: uri = Uri.parse("/song/media/outer/url?id=1464389585.mp3");break;case 33: uri = Uri.parse("/song/media/outer/url?id=29343374.mp3");break;case 34: uri = Uri.parse("/song/media/outer/url?id=187564.mp3");break;case 35: uri = Uri.parse("/song/media/outer/url?id=26075355.mp3");break;case 36: uri = Uri.parse("/song/media/outer/url?id=187374.mp3");break;}try {player.reset();//重置音乐播放器//加载多媒体文件player = MediaPlayer.create(getApplicationContext(), uri);player.start();//播放音乐addTimer();//添加计时器} catch (Exception e) {e.printStackTrace();}}public boolean pausePlay(){player.pause();//暂停播放音乐return false;}public void continuePlay(){player.start();//继续播放音乐}public void seekTo(int progress){player.seekTo(progress);//设置音乐的播放位置}}@Overridepublic void onDestroy(){super.onDestroy();if(player==null) return;if(player.isPlaying()) player.stop();//停止播放音乐player.release();//释放占用的资源player=null;//将player置为空}}
Music_Activity.java
package com.ypc.xiaoxiongmusic;import android.animation.ObjectAnimator;import android.app.Activity;import ponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.Build;import android.os.Bundle;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.view.View;import android.view.animation.LinearInterpolator;import android.widget.Button;import android.widget.ImageView;import android.widget.SeekBar;import android.widget.TextView;import androidx.annotation.RequiresApi;import static java.lang.Integer.parseInt;public class Music_Activity extends Activity implements View.OnClickListener{private static SeekBar sb;private static TextView tv_progress,tv_total;private ObjectAnimator animator;//private MusicService .MusicControl musicControl;//private ImageView bt_1;private ImageView iv_music;private TextView tv_name;private int change;String name;Intent intent1,intent2;MyServiceConn conn;//private boolean isUnbind =false;//记录服务是否被解绑@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_music);intent1=getIntent();init();View v=findViewById(R.id.bg_1);// v.getBackground().setAlpha(180);tv_name=findViewById(R.id.song_name);iv_music=findViewById(R.id.iv_music);bt_1=findViewById(R.id.bt_1);bt_1.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {finish();}});}private void init(){tv_progress=(TextView)findViewById(R.id.tv_progress);tv_total=(TextView)findViewById(R.id.tv_total);sb=(SeekBar)findViewById(R.id.sb);TextView tv_name=(TextView)findViewById(R.id.song_name);ImageView iv_music=(ImageView)findViewById(R.id.iv_music);findViewById(R.id.btn_play).setOnClickListener(this);findViewById(R.id.btn_pause).setOnClickListener(this);findViewById(R.id.btn_continue_play).setOnClickListener(this);findViewById(R.id.btn_next).setOnClickListener(this);findViewById(R.id.btn_jixu).setOnClickListener(this);name=intent1.getStringExtra("name");tv_name.setText(name);intent2=new Intent(this,MusicService.class);//创建意图对象conn=new MyServiceConn();//创建服务连接对象bindService(intent2,conn,BIND_AUTO_CREATE);//绑定服务//为滑动条添加事件监听sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@RequiresApi(api = Build.VERSION_CODES.KITKAT)@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {//进度条改变时,会调用此方法if (progress==seekBar.getMax()){//当滑动条到末端时,结束动画animator.pause();//停止播放动画}}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {//滑动条开始滑动时调用}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {//滑动条停止滑动时调用//根据拖动的进度改变音乐播放进度int progress=seekBar.getProgress();//获取seekBar的进度musicControl.seekTo(progress);//改变播放进度}});animator= ObjectAnimator.ofFloat(iv_music,"rotation",0f,360.0f);animator.setDuration(15000);//动画旋转一周的时间为10秒animator.setInterpolator(new LinearInterpolator());//匀速animator.setRepeatCount(-1);//-1表示设置动画无限循环}public static Handler handler=new Handler(){//创建消息处理器对象//在主线程中处理从子线程发送过来的消息@Overridepublic void handleMessage(Message msg){Bundle bundle=msg.getData();//获取从子线程发送过来的音乐播放进度int duration=bundle.getInt("duration");int currentPosition=bundle.getInt("currentPosition");sb.setMax(duration);sb.setProgress(currentPosition);//歌曲总时长int minute=duration/1000/60;int second=duration/1000%60;String strMinute=null;String strSecond=null;if(minute<10){//如果歌曲的时间中的分钟小于10strMinute="0"+minute;//在分钟的前面加一个0}else{strMinute=minute+"";}if (second<10){//如果歌曲中的秒钟小于10strSecond="0"+second;//在秒钟前面加一个0}else{strSecond=second+"";}tv_total.setText(strMinute+":"+strSecond);//歌曲当前播放时长minute=currentPosition/1000/60;second=currentPosition/1000%60;if(minute<10){//如果歌曲的时间中的分钟小于10strMinute="0"+minute;//在分钟的前面加一个0}else{strMinute=minute+" ";}if (second<10){//如果歌曲中的秒钟小于10strSecond="0"+second;//在秒钟前面加一个0}else{strSecond=second+" ";}tv_progress.setText(strMinute+":"+strSecond);}};class MyServiceConn implements ServiceConnection {//创建一个自定义类用于实现连接服务@Overridepublic void onServiceConnected(ComponentName name, IBinder service){musicControl=(MusicService.MusicControl) service;}@Overridepublic void onServiceDisconnected(ComponentName name){}}private void unbind(boolean isUnbind){if(!isUnbind){//判断服务是否被解绑musicControl.pausePlay();//暂停播放音乐unbindService(conn);//解绑服务}}@RequiresApi(api = Build.VERSION_CODES.KITKAT)//如果注释掉,则需要手动在grideMouble里面把api从15调到更高如19@Overridepublic void onClick(View v) {String position=intent1.getStringExtra("position");int i=parseInt(position);switch (v.getId()){case R.id.btn_play://播放按钮点击事件musicControl.play(i);animator.start();break;case R.id.btn_pause://暂停按钮点击事件musicControl.pausePlay();animator.pause();break;case R.id.btn_jixu://继续按钮点击事件musicControl.continuePlay();animator.resume();break;case R.id.btn_continue_play://上一首if(( i +change)<1) {change=name.length()-1-i;musicControl.play(i+change);animator.resume();tv_name.setText(name);}else {change--;musicControl.play(i+change);animator.resume();break;}case R.id.btn_next://下一首按钮点击事件if((i+change)==name.length()-1) {//这里Name.length-1表示的最后一首歌的下标,即歌曲总数-1change=-i;musicControl.play(i+change);iv_music.setImageResource(musicFragment.icons[i+change]);// name_song.setText(name);animator.start();tv_name.setText((String)musicFragment.name[i+change]);}else {change++;iv_music.setImageResource(musicFragment.icons[i+change]);tv_name.setText(musicFragment.name[i+change]);musicControl.play(i+change);animator.resume();break;}}}//不注释,则返回上一界面,会摧毁暂停音乐/* @Overrideprotected void onDestroy(){super.onDestroy();unbind(isUnbind);//解绑服务}*/}
activity_music.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"xmlns:tools="/tools"tools:context=".Music_Activity"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:background="@drawable/tpbj"android:id="@+id/bg_1"><ImageViewandroid:src="@drawable/back1"android:id="@+id/bt_1"android:layout_width="50dp"android:layout_height="50dp"android:background="@drawable/back_layout"android:paddingLeft="10dp"></ImageView><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginTop="-100dp"android:gravity="center"android:orientation="vertical"><ImageViewandroid:id="@+id/iv_music"android:layout_width="200dp"android:layout_height="200dp"android:layout_gravity="center_horizontal"android:layout_margin="15dp"android:src="@drawable/musicx" /><TextViewandroid:id="@+id/song_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:text="歌曲名"android:textSize="18sp" /><SeekBarandroid:id="@+id/sb"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp" /><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:paddingLeft="8dp"android:paddingRight="8dp"><TextViewandroid:id="@+id/tv_progress"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="00:00" /><TextViewandroid:id="@+id/tv_total"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:text="00:00" /></RelativeLayout><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="2dp"android:orientation="horizontal"><ImageButtonandroid:id="@+id/btn_continue_play"android:layout_width="42dp"android:layout_height="42dp"android:layout_marginTop="8dp"android:background="@drawable/music_play"android:src="@drawable/xx1" /><ImageButtonandroid:id="@+id/btn_play"android:layout_width="42dp"android:layout_height="42dp"android:layout_marginLeft="40dp"android:layout_marginTop="8dp"android:background="@drawable/music_play"android:src="@drawable/xx4" /><ImageButtonandroid:id="@+id/btn_pause"android:layout_width="42dp"android:layout_height="42dp"android:layout_marginLeft="40dp"android:layout_marginTop="8dp"android:background="@drawable/music_play"android:src="@drawable/xx5" /><ImageButtonandroid:id="@+id/btn_jixu"android:layout_width="42dp"android:layout_height="42dp"android:layout_marginLeft="40dp"android:layout_marginTop="8dp"android:background="@drawable/music_nextplay"android:src="@drawable/xx2" /><ImageButtonandroid:id="@+id/btn_next"android:layout_width="42dp"android:layout_height="42dp"android:layout_marginLeft="40dp"android:layout_marginTop="8dp"android:background="@drawable/music_nextplay"android:src="@drawable/xx3" /></LinearLayout></LinearLayout></LinearLayout>
效果截图如下:
Android音乐播放器(四)音乐唱片的转盘 歌曲同步进度条 以及音乐的暂停/播放/继续/上下歌曲切换