这是去年大二做的一个简单音乐播放器项目:是尽可能模仿酷狗音乐写的,具体实现的功能如下:
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 android.net.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();
}
@Override
public void onCreate(){
super.onCreate();
player=new MediaPlayer();//创建音乐播放器对象
}
public void addTimer(){ //添加计时器用于设置音乐播放器中的播放进度条
if(timer==null){
timer=new Timer();//创建计时器对象
TimerTask task=new TimerTask() {
@Override
public 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 path
Uri uri=null;
switch(i) {
case 0:uri = Uri.parse("http://music.163.com/song/media/outer/url?id=5316513.mp3");
break;
case 1:uri = Uri.parse("http://music.163.com/song/media/outer/url?id=409646185.mp3");
break;
case 2:uri= Uri.parse("http://music.163.com/song/media/outer/url?id=26125687.mp3");
break;
case 3:uri = Uri.parse("http://music.163.com/song/media/outer/url?id=516358417.mp3");
break;
case 4: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=1492886765.mp3");
break;
case 5: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=1436910205.mp3");
break;
case 6: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=1399533630.mp3");
break;
case 7: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=32835565.mp3");
break;
case 8: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=1422992414.mp3");
break;
case 9: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=29004400.mp3");
break;
case 10: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=1439111141.mp3");
break;
case 11: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=29418041.mp3");
break;
case 12: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=472137749.mp3");
break;
case 13: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=507364050.mp3");
break;
case 14: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=426291338.mp3");
break;
case 15: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=34228112.mp3");
break;
case 16: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=1428605192.mp3");
break;
case 17: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=33190545.mp3");
break;
case 18: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=32619105.mp3");
break;
case 19: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=1425643256.mp3");
break;
case 20: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=1305366556.mp3");
break;
case 21: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=481859794.mp3");
break;
case 22: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=1424537185.mp3");
break;
case 23: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=1403445370.mp3");
break;
case 24: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=36668004.mp3");
break;
case 25: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=548650088.mp3");
break;
case 26: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=1409296047.mp3");
break;
case 27: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=1389152878.mp3");
break;
case 28: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=475279382.mp3");
break;
case 29: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=1464390595.mp3");
break;
case 30: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=1464389589.mp3");
break;
case 31: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=1464446728.mp3");
break;
case 32: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=1464389585.mp3");
break;
case 33: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=29343374.mp3");
break;
case 34: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=187564.mp3");
break;
case 35: uri = Uri.parse("http://music.163.com/song/media/outer/url?id=26075355.mp3");
break;
case 36: uri = Uri.parse("http://music.163.com/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);//设置音乐的播放位置
}
}
@Override
public void onDestroy(){
super.onDestroy();
if(player==null) return;
if(player.isPlaying()) player.stop();//停止播放音乐
player.release();//释放占用的资源
player=null;//将player置为空
}
}
Music_Activity.java
扫描二维码关注公众号,回复:
14547075 查看本文章
package com.ypc.xiaoxiongmusic;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.ComponentName;
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;//记录服务是否被解绑
@Override
protected 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() {
@Override
public 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)
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
//进度条改变时,会调用此方法
if (progress==seekBar.getMax()){//当滑动条到末端时,结束动画
animator.pause();//停止播放动画
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {//滑动条开始滑动时调用
}
@Override
public 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(){//创建消息处理器对象
//在主线程中处理从子线程发送过来的消息
@Override
public 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){//如果歌曲的时间中的分钟小于10
strMinute="0"+minute;//在分钟的前面加一个0
}else{
strMinute=minute+"";
}
if (second<10){//如果歌曲中的秒钟小于10
strSecond="0"+second;//在秒钟前面加一个0
}else{
strSecond=second+"";
}
tv_total.setText(strMinute+":"+strSecond);
//歌曲当前播放时长
minute=currentPosition/1000/60;
second=currentPosition/1000%60;
if(minute<10){//如果歌曲的时间中的分钟小于10
strMinute="0"+minute;//在分钟的前面加一个0
}else{
strMinute=minute+" ";
}
if (second<10){//如果歌曲中的秒钟小于10
strSecond="0"+second;//在秒钟前面加一个0
}else{
strSecond=second+" ";
}
tv_progress.setText(strMinute+":"+strSecond);
}
};
class MyServiceConn implements ServiceConnection {//创建一个自定义类用于实现连接服务
@Override
public void onServiceConnected(ComponentName name, IBinder service){
musicControl=(MusicService.MusicControl) service;
}
@Override
public 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
@Override
public 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表示的最后一首歌的下标,即歌曲总数-1
change=-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;
}
}
}
//不注释,则返回上一界面,会摧毁暂停音乐
/* @Override
protected void onDestroy(){
super.onDestroy();
unbind(isUnbind);//解绑服务
}*/
}
activity_music.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/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">
<ImageView
android: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>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="-100dp"
android:gravity="center"
android:orientation="vertical">
<ImageView
android: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" />
<TextView
android:id="@+id/song_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="歌曲名"
android:textSize="18sp" />
<SeekBar
android:id="@+id/sb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:paddingLeft="8dp"
android:paddingRight="8dp">
<TextView
android:id="@+id/tv_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00" />
<TextView
android:id="@+id/tv_total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="00:00" />
</RelativeLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:orientation="horizontal">
<ImageButton
android: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" />
<ImageButton
android: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" />
<ImageButton
android: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" />
<ImageButton
android: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" />
<ImageButton
android: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>
效果截图如下: