Android Studio 实现音乐播放器

目录

一、引言

视频效果展示:

1.启动页效果

2.登录页效果

3.注册页效果

4.歌曲列表页效果

5.播放页效果

 二、详细设计

1.登陆注册功能

2.音乐列表页面

2.音乐播放功能

三、源码获取


一、引言

        Android初学者开发第一个完整的实例项目应该就属《音乐播放器》了,项目包含SQLlit数据库的使用、listview、Fragment、等。话不多说先上成品:

视频效果展示:

Android Studio 音乐播放器

图片效果展示:

1.启动页效果

bdf383c204b04df8b20d3bf52630e838.png

2.登录页效果

62bad85a5697492faceb78a9ff260663.png

3.注册页效果

6954222d65b34b1494711fbf043aad89.png

4.歌曲列表页效果

f2343f9f53de4f429827d30fd9f0deb1.png

5.播放页效果

26cbc5b2ae874f3c879dc9304d1dd6fa.png

 二、详细设计

1.登陆注册功能

        用户进行注册数据使用SQLite存储,用户登录时根据数据库的内容来核对用户名和密码是否正确。

fb5231b97ce541b284fb99d7988388c8.pngf1e5f1ad2a484436bf50efb9910dca80.png

 Login.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#f9d7e7"tools:context=".Login.LoginActivity"><ImageViewandroid:id="@+id/imageView3"android:layout_width="200dp"android:layout_height="150dp"android:layout_marginTop="24dp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"app:srcCompat="@drawable/logo1" /><Viewandroid:id="@+id/view2"android:layout_width="0dp"android:layout_height="320dp"android:layout_marginTop="24dp"android:background="@drawable/login_view"app:layout_constraintEnd_toStartOf="@+id/guideline2"app:layout_constraintStart_toStartOf="@+id/guideline3"app:layout_constraintTop_toBottomOf="@+id/imageView3" /><Buttonandroid:id="@+id/login_button"android:layout_width="250dp"android:layout_height="55dp"android:layout_marginBottom="32dp"android:background="@drawable/login"android:text="立 即 登 录 "android:textColor="#fff"android:textSize="24sp"app:layout_constraintBottom_toBottomOf="@+id/view2"app:layout_constraintEnd_toStartOf="@+id/guideline2"app:layout_constraintStart_toStartOf="@+id/view2" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintGuide_percent="0.9" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintGuide_percent="0.1" /><Viewandroid:id="@+id/view3"android:layout_width="0dp"android:layout_height="45dp"android:layout_marginTop="40dp"android:background="@drawable/login_count"app:layout_constraintEnd_toEndOf="@+id/login_button"app:layout_constraintStart_toStartOf="@+id/login_button"app:layout_constraintTop_toTopOf="@+id/view2" /><Viewandroid:id="@+id/view4"android:layout_width="0dp"android:layout_height="45dp"android:layout_marginTop="24dp"android:background="@drawable/login_count"app:layout_constraintEnd_toEndOf="@+id/login_button"app:layout_constraintHorizontal_bias="0.0"app:layout_constraintStart_toStartOf="@+id/login_button"app:layout_constraintTop_toBottomOf="@+id/view3" /><TextViewandroid:id="@+id/textView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="24dp"android:text="忘 记 密 码"app:layout_constraintStart_toStartOf="@+id/view4"app:layout_constraintTop_toBottomOf="@+id/view4" /><TextViewandroid:id="@+id/login_register"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="立 即 注 册"app:layout_constraintBottom_toBottomOf="@+id/textView"app:layout_constraintEnd_toEndOf="@+id/view4"app:layout_constraintTop_toTopOf="@+id/textView" /><ImageViewandroid:id="@+id/imageView"android:layout_width="20dp"android:layout_height="20dp"app:layout_constraintBottom_toBottomOf="@+id/view4"app:layout_constraintEnd_toEndOf="@+id/imageView4"app:layout_constraintTop_toTopOf="@+id/view4"app:srcCompat="@drawable/mima" /><ImageViewandroid:id="@+id/imageView4"android:layout_width="20dp"android:layout_height="20dp"android:layout_marginStart="16dp"app:layout_constraintBottom_toBottomOf="@+id/view3"app:layout_constraintStart_toStartOf="@+id/view3"app:layout_constraintTop_toTopOf="@+id/view3"app:srcCompat="@drawable/zhanghao" /><Viewandroid:id="@+id/view5"android:layout_width="100dp"android:layout_height="1dp"android:layout_marginTop="40dp"android:background="#fff"app:layout_constraintStart_toStartOf="@+id/guideline3"app:layout_constraintTop_toBottomOf="@+id/view2" /><Viewandroid:id="@+id/view6"android:layout_width="100dp"android:layout_height="1dp"android:background="#fff"app:layout_constraintEnd_toStartOf="@+id/guideline2"app:layout_constraintTop_toTopOf="@+id/view5" /><TextViewandroid:id="@+id/textView3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="其它方式登陆"android:textColor="#fff"app:layout_constraintBottom_toBottomOf="@+id/view5"app:layout_constraintEnd_toStartOf="@+id/view6"app:layout_constraintStart_toEndOf="@+id/view5"app:layout_constraintTop_toTopOf="@+id/view5" /><ImageViewandroid:id="@+id/imageView6"android:layout_width="30dp"android:layout_height="30dp"app:layout_constraintBottom_toBottomOf="@+id/imageView5"app:layout_constraintEnd_toStartOf="@+id/imageView7"app:layout_constraintStart_toEndOf="@+id/imageView5"app:layout_constraintTop_toTopOf="@+id/imageView5"app:srcCompat="@drawable/qq" /><ImageViewandroid:id="@+id/imageView5"android:layout_width="30dp"android:layout_height="30dp"android:layout_marginStart="70dp"android:layout_marginTop="24dp"app:layout_constraintStart_toStartOf="@+id/guideline3"app:layout_constraintTop_toBottomOf="@+id/view5"app:srcCompat="@drawable/weixin" /><ImageViewandroid:id="@+id/imageView7"android:layout_width="30dp"android:layout_height="30dp"android:layout_marginEnd="70dp"app:layout_constraintBottom_toBottomOf="@+id/imageView6"app:layout_constraintEnd_toStartOf="@+id/guideline2"app:layout_constraintTop_toTopOf="@+id/imageView6"app:srcCompat="@drawable/weibo" /><EditTextandroid:id="@+id/user"android:layout_width="190dp"android:layout_height="0dp"android:layout_marginStart="5dp"android:ems="10"android:background="#eff4f2"android:inputType="textPersonName"android:hint="请输入账号"app:layout_constraintBottom_toBottomOf="@+id/view3"app:layout_constraintStart_toEndOf="@+id/imageView4"app:layout_constraintTop_toTopOf="@+id/view3" /><EditTextandroid:id="@+id/pass"android:layout_width="190dp"android:layout_height="0dp"android:layout_marginStart="5dp"android:ems="10"android:background="#eff4f2"android:inputType="textPassword"android:hint="请输入密码"app:layout_constraintBottom_toBottomOf="@+id/view4"app:layout_constraintStart_toEndOf="@+id/imageView"app:layout_constraintTop_toTopOf="@+id/view4"app:layout_constraintVertical_bias="0.0" /></androidx.constraintlayout.widget.ConstraintLayout>

Register.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#f9d7e7"tools:context=".Register.RegisterActivity"><ImageViewandroid:id="@+id/imageView3"android:layout_width="200dp"android:layout_height="150dp"android:layout_marginTop="40dp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"app:srcCompat="@drawable/logo1" /><Viewandroid:id="@+id/view2"android:layout_width="0dp"android:layout_height="270dp"android:background="@drawable/login_view"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toStartOf="@+id/guideline4"app:layout_constraintHorizontal_bias="0.0"app:layout_constraintStart_toStartOf="@+id/guideline"app:layout_constraintTop_toTopOf="@+id/imageView3"app:layout_constraintVertical_bias="0.501" /><Viewandroid:id="@+id/view3"android:layout_width="250dp"android:layout_height="45dp"android:layout_marginTop="32dp"android:background="@drawable/login_count"app:layout_constraintEnd_toStartOf="@+id/guideline4"app:layout_constraintStart_toStartOf="@+id/view2"app:layout_constraintTop_toTopOf="@+id/view2" /><Viewandroid:id="@+id/view4"android:layout_width="0dp"android:layout_height="45dp"android:layout_marginTop="32dp"android:background="@drawable/login_count"app:layout_constraintEnd_toEndOf="@+id/view3"app:layout_constraintStart_toStartOf="@+id/view3"app:layout_constraintTop_toBottomOf="@+id/view3" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintGuide_percent="0.1" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintGuide_percent="0.9" /><ImageViewandroid:id="@+id/imageView"android:layout_width="20dp"android:layout_height="20dp"android:layout_marginStart="8dp"app:layout_constraintBottom_toBottomOf="@+id/view3"app:layout_constraintStart_toStartOf="@+id/view3"app:layout_constraintTop_toTopOf="@+id/view3"app:srcCompat="@drawable/mima" /><ImageViewandroid:id="@+id/imageView4"android:layout_width="20dp"android:layout_height="20dp"app:layout_constraintBottom_toBottomOf="@+id/view4"app:layout_constraintStart_toStartOf="@+id/imageView"app:layout_constraintTop_toTopOf="@+id/view4"app:srcCompat="@drawable/zhanghao" /><Buttonandroid:id="@+id/register_button"android:layout_width="250dp"android:layout_height="55dp"android:text="立 即 注 册"android:layout_marginBottom="32dp"android:background="@drawable/login"app:layout_constraintBottom_toBottomOf="@+id/view2"app:layout_constraintEnd_toEndOf="@+id/view2"app:layout_constraintHorizontal_bias="0.497"app:layout_constraintStart_toStartOf="@+id/view2" /><EditTextandroid:id="@+id/username_edittext"android:layout_width="190dp"android:layout_height="0dp"android:layout_marginStart="5dp"android:ems="10"android:hint="请输入账号"android:background="#eff4f2"android:inputType="textPersonName"app:layout_constraintBottom_toBottomOf="@+id/view3"app:layout_constraintStart_toEndOf="@+id/imageView"app:layout_constraintTop_toTopOf="@+id/view3" /><EditTextandroid:id="@+id/password_edittext"android:layout_width="190dp"android:layout_height="0dp"android:layout_marginStart="5dp"android:ems="10"android:hint="请输入密码"android:background="#eff4f2"android:inputType="textPassword"app:layout_constraintBottom_toBottomOf="@+id/view4"app:layout_constraintStart_toEndOf="@+id/imageView4"app:layout_constraintTop_toTopOf="@+id/view4" /></androidx.constraintlayout.widget.ConstraintLayout>

LoginActivity完整代码:

package com.example.music.Login;import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;import com.example.music.MainActivity;
import com.example.music.R;
import com.example.music.Register.RegisterActivity;
import com.example.music.Data.DatabaseHelper;public class LoginActivity extends AppCompatActivity {private TextView loginRegister;private EditText user;private EditText pass;private Button mLoginButton;private DatabaseHelper mDatabaseHelper;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);user = findViewById(R.id.user);pass = findViewById(R.id.pass);mLoginButton = findViewById(R.id.login_button);loginRegister = findViewById(R.id.login_register);mDatabaseHelper = new DatabaseHelper(this);loginRegister.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent(LoginActivity.this, RegisterActivity.class);startActivity(intent);}});mLoginButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String username = user.getText().toString().trim();String password = pass.getText().toString().trim();if (username.isEmpty() || password.isEmpty()) {Toast.makeText(getApplicationContext(), "请输入账号或密码", Toast.LENGTH_SHORT).show();return;}boolean result = mDatabaseHelper.checkUser(username, password);if (result) {Toast.makeText(getApplicationContext(), "登陆成功", Toast.LENGTH_SHORT).show();Intent intent = new Intent(LoginActivity.this, MainActivity.class);startActivity(intent);} else {Toast.makeText(getApplicationContext(), "账号或密码错误", Toast.LENGTH_SHORT).show();}}});}
}

RegisterActivity完整代码:

package com.example.music.Register;import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;import com.example.music.Login.LoginActivity;
import com.example.music.R;
import com.example.music.Data.DatabaseHelper;public class RegisterActivity extends AppCompatActivity {private EditText mUserNameEditText;private EditText mPasswordEditText;private Button registerButton;private DatabaseHelper mDatabaseHelper;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_register);mUserNameEditText = findViewById(R.id.username_edittext);mPasswordEditText = findViewById(R.id.password_edittext);registerButton = findViewById(R.id.register_button);mDatabaseHelper = new DatabaseHelper(this);registerButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String username = mUserNameEditText.getText().toString().trim();String password = mPasswordEditText.getText().toString().trim();if (username.isEmpty() || password.isEmpty()) {Toast.makeText(getApplicationContext(), "请输入账号或密码", Toast.LENGTH_SHORT).show();return;}boolean result = mDatabaseHelper.insertData(username, password);if (result) {Toast.makeText(getApplicationContext(), "注册成功", Toast.LENGTH_SHORT).show();Intent intent = new Intent(RegisterActivity.this, LoginActivity.class);startActivity(intent);finish();} else {Toast.makeText(getApplicationContext(), "注册失败", Toast.LENGTH_SHORT).show();}}});}
}

2.音乐列表页面

         主要用于音乐的显示以及点击对应的音乐跳转到对应的音乐播放页面。

e0090aaa5285487fa8dae5ce3598c456.png

 Activity完整代码:

package com.example.music;import android.content.Intent;
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.ImageView;
import android.widget.ListView;
import android.widget.TextView;import androidx.fragment.app.Fragment;import com.example.music.Music.MusicActivity;public class SongPage extends Fragment {//声明视图变量viewprivate View view;//在这里添加歌曲名public String[] songname = {"Innocence", "刚刚好","不用去猜"};private String[] name={"A R L","薛之谦","Jony J"};//在这里添加歌曲图片public static int[] icons = {R.drawable.img_01, R.drawable.img_02, R.drawable.img_03};@Overridepublic View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {view = inflater.inflate(R.layout.music_list, null);//1、创建并绑定列表ListView listView = view.findViewById(R.id.lv);//2、创建适配器对象MyBaseAdapter adapter = new MyBaseAdapter();//3、给列表设置适配器listView.setAdapter(adapter);//设置列表条目监听器listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {//创建Intent对象,启动音乐播放界面Intent intent = new Intent(SongPage.this.getContext(), MusicActivity.class);//将数据存入Intent对象,利用键值对intent.putExtra("name", name[position]);intent.putExtra("songname", songname[position]);intent.putExtra("position", String.valueOf(position));//开启意图,进行跳转startActivity(intent);}});return view;}class MyBaseAdapter extends BaseAdapter {@Overridepublic int getCount() {return name.length;}@Overridepublic Object getItem(int i) {return name[i];}@Overridepublic long getItemId(int i) {return i;}@Overridepublic View getView(int i, View convertView, ViewGroup parent) {//绑定视图,并且显示歌曲名和歌曲图片View view = View.inflate(SongPage.this.getContext(), R.layout.item_music, null);TextView songName = view.findViewById(R.id.song_name);ImageView songPic = view.findViewById(R.id.song_pic);TextView name1=view.findViewById(R.id.name);songName.setText(songname[i]);name1.setText(name[i]);songPic.setImageResource(icons[i]);return view;}}}

相关的xml代码:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="wrap_content"android:padding="15dp"><ImageViewandroid:id="@+id/song_pic"android:layout_width="86dp"android:layout_height="86dp"android:src="@drawable/img_01"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><TextViewandroid:id="@+id/song_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="8dp"android:layout_marginTop="16dp"android:text="歌曲"android:textColor="#000"android:textSize="20sp"app:layout_constraintStart_toEndOf="@+id/song_pic"app:layout_constraintTop_toTopOf="@+id/song_pic" /><TextViewandroid:id="@+id/name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="8dp"android:text="歌曲"android:textColor="#000"android:textSize="14sp"app:layout_constraintStart_toStartOf="@+id/song_name"app:layout_constraintTop_toBottomOf="@+id/song_name" /><ImageViewandroid:id="@+id/song_enter"android:layout_width="30dp"android:layout_height="30dp"android:layout_marginEnd="8dp"android:src="@drawable/song_play"app:layout_constraintBottom_toBottomOf="@+id/song_pic"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintTop_toTopOf="@+id/song_pic" /></androidx.constraintlayout.widget.ConstraintLayout>

2.音乐播放功能

       用于播放音乐,对音乐进行暂停,上一首、下一首功能的实现。

c63266c89937447b82b5f69ce6c802a9.png

 具体MusicActivity代码:

public class MusicActivity extends AppCompatActivity implements View.OnClickListener{//定义歌曲名称的数组public String[] musicName={"Innocence", "刚刚好","不用去猜"};private static SeekBar sb;//定义进度条private static TextView tv_progress, tv_total, name_song;//定义开始和总时长,歌曲名控件private ObjectAnimator animator;//定义旋转的动画private MusicService.MusicControl musicControl;//音乐控制类private Button play;        //播放按钮private Button pause;       //暂停按钮private Button con;         //继续播放按钮private Button pre;         //上一首按钮private Button next;        //下一首按钮private ImageView exit;        //退出按钮private ImageView iv_music; //歌手图片框Intent intent1, intent2;    //定义两个意图MyServiceConn conn;         //服务连接private boolean isUnbind = false;//记录服务是否被解绑public int change = 0;      //记录下标的变化值@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_music);//去除标题栏ActionBar actionBar = getSupportActionBar();if(actionBar!= null){actionBar.hide();}//获得意图intent1 = getIntent();//初始化initView();}//初始化private void initView(){//依次绑定控件tv_progress = findViewById(R.id.tv_progress);tv_total = findViewById(R.id.tv_total);sb = findViewById(R.id.sb);name_song = findViewById(R.id.song_name);iv_music = findViewById(R.id.iv_music);play = findViewById(R.id.btn_play);pause = findViewById(R.id.btn_pause);con = findViewById(R.id.btn_continue_play);pre = findViewById(R.id.btn_pre);next = findViewById(R.id.btn_next);exit = findViewById(R.id.btn_exit);//依次设置监听器play.setOnClickListener(this);pause.setOnClickListener(this);con.setOnClickListener(this);pre.setOnClickListener(this);next.setOnClickListener(this);exit.setOnClickListener(this);//创建意图对象intent2 = new Intent(this, MusicService.class);conn = new MyServiceConn();//创建服务连接对象bindService(intent2, conn,BIND_AUTO_CREATE);//绑定服务//从歌曲列表传过来的歌曲名String name = intent1.getStringExtra("songname");//设置歌曲名显示name_song.setText(name);//定义歌曲列表传过来的下标positionString position = intent1.getStringExtra("position");//将字符串转化为整型iint i = parseInt(position);//图像框设置为frag1里面的图标数组,下标为iiv_music.setImageResource(SongPage.icons[i]);//为滑动条添加事件监听sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@RequiresApi(api = Build.VERSION_CODES.KITKAT)@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {//当滑动条到末端时,将message对象发送出去if (progress == sb.getMax()){}}@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(10000);//动画旋转一周的时间为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)@Overridepublic void onClick(View v) {//获取歌曲名的下标字符串String index = intent1.getStringExtra("position");//将字符串转为整数int i = parseInt(index);switch (v.getId()){case R.id.btn_play://播放按钮点击事件play.setVisibility(View.INVISIBLE);musicControl.play(i);animator.start();break;//这里musicName.length-1表示的最后一首歌的下标,即歌曲总数-1case R.id.btn_pre://播放上一首if((i + change) < 1) {change = musicName.length - 1 - i;iv_music.setImageResource(SongPage.icons[i + change]);name_song.setText(musicName[i + change]);musicControl.play(i + change);pause.setVisibility(View.VISIBLE);animator.start();break;} else {change--;iv_music.setImageResource(SongPage.icons[i + change]);name_song.setText(musicName[i + change]);musicControl.play(i + change);pause.setVisibility(View.VISIBLE);animator.start();break;}case R.id.btn_next://播放下一首if((i + change) == musicName.length - 1) {change = -i;iv_music.setImageResource(SongPage.icons[i + change]);name_song.setText(musicName[i + change]);musicControl.play(i + change);pause.setVisibility(View.VISIBLE);animator.start();break;} else {change++;iv_music.setImageResource(SongPage.icons[i + change]);name_song.setText(musicName[i + change]);musicControl.play(i + change);pause.setVisibility(View.VISIBLE);animator.start();break;}case R.id.btn_pause://暂停按钮点击事件pause.setVisibility(View.INVISIBLE);con.setVisibility(View.VISIBLE);musicControl.pausePlay();animator.pause();break;case R.id.btn_continue_play://继续播放按钮点击事件con.setVisibility(View.INVISIBLE);pause.setVisibility(View.VISIBLE);musicControl.continuePlay();animator.start();break;case R.id.btn_exit://退出按钮点击事件unbind(isUnbind);isUnbind = true;finish();break;}}@Overrideprotected void onDestroy(){super.onDestroy();unbind(isUnbind);//解绑服务}
}

相关的xml文件代码:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#f9d7e7"android:orientation="vertical"tools:context=".Music.MusicActivity"><ImageViewandroid:id="@+id/btn_exit"android:layout_width="20dp"android:layout_height="20dp"android:layout_marginStart="16dp"android:layout_marginTop="24dp"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"app:srcCompat="@drawable/back" /><TextViewandroid:id="@+id/song_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text="光年之外"android:textColor="#000"android:textSize="24sp"app:layout_constraintBottom_toBottomOf="@+id/btn_exit"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="@+id/btn_exit" /><ImageViewandroid:id="@+id/iv_music"android:layout_width="250dp"android:layout_height="250dp"android:layout_marginTop="80dp"android:src="@drawable/img_01"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/btn_exit" /><SeekBarandroid:id="@+id/sb"android:layout_width="250dp"android:layout_height="20dp"android:layout_marginTop="80dp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/iv_music" /><TextViewandroid:id="@+id/tv_progress"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginEnd="5dp"android:text="00:00"app:layout_constraintBottom_toBottomOf="@+id/sb"app:layout_constraintEnd_toStartOf="@+id/sb"app:layout_constraintTop_toTopOf="@+id/sb" /><TextViewandroid:id="@+id/tv_total"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="5dp"android:text="00:00"app:layout_constraintBottom_toBottomOf="@+id/sb"app:layout_constraintStart_toEndOf="@+id/sb"app:layout_constraintTop_toTopOf="@+id/sb" /><Buttonandroid:id="@+id/btn_continue_play"android:layout_width="60dp"android:layout_height="60dp"android:background="@drawable/play"app:layout_constraintBottom_toBottomOf="@+id/btn_pre"app:layout_constraintEnd_toStartOf="@+id/btn_next"app:layout_constraintStart_toEndOf="@+id/btn_pre"app:layout_constraintTop_toTopOf="@+id/btn_pre" /><Buttonandroid:id="@+id/btn_pause"android:layout_width="60dp"android:layout_height="60dp"android:background="@drawable/pause"app:layout_constraintBottom_toBottomOf="@+id/btn_next"app:layout_constraintEnd_toStartOf="@+id/btn_next"app:layout_constraintStart_toEndOf="@+id/btn_pre"app:layout_constraintTop_toTopOf="@+id/btn_next" /><Buttonandroid:id="@+id/btn_pre"android:layout_width="40dp"android:layout_height="40dp"android:layout_marginStart="24dp"android:background="@drawable/pre"app:layout_constraintBottom_toBottomOf="@+id/btn_next"app:layout_constraintStart_toStartOf="@+id/tv_progress"app:layout_constraintTop_toTopOf="@+id/btn_next" /><Buttonandroid:id="@+id/btn_next"android:layout_width="40dp"android:layout_height="40dp"android:layout_marginTop="100dp"android:layout_marginEnd="24dp"android:background="@drawable/next"app:layout_constraintEnd_toEndOf="@+id/tv_total"app:layout_constraintTop_toBottomOf="@+id/tv_total" /><Buttonandroid:id="@+id/btn_play"android:layout_width="60dp"android:layout_height="60dp"android:background="@drawable/play"app:layout_constraintBottom_toBottomOf="@+id/btn_pre"app:layout_constraintEnd_toStartOf="@+id/btn_next"app:layout_constraintStart_toEndOf="@+id/btn_pre"app:layout_constraintTop_toTopOf="@+id/btn_pre" /></androidx.constraintlayout.widget.ConstraintLayout>

三、源码获取

✨还可以关注我的公众号《编程乐学》,菜单栏,有很多优质的资料等你来学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/225829.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker中的常见命令

Docker开机自启 systemctl enable dockerDocker容器开机自启 docker update --restartalways [容器名/容器id]案例&#xff1a;docker操作nginx 拉取Nginx镜像 docker pull nginx查看镜像 docker images创建并运行Nginx容器 docker run -d --name nginx -p 80:80 nginx查…

LT8711HE方案《任天堂Switch底座方案》

LT8711HE Type-c转HDMI方案 LT8711HE是高性能的Type-C/DP1.2转HDMI2.0转换器&#xff0c;设计用于连接 USB Type-C 源或 DP1.2 源到 HDMI2.0 接收器。该LT8711HE集成了符合 DP1.2 标准的接收器和符合 HDMI2.0 标准的发射器。此外&#xff0c;两个 CC 控制器是包括用于 CC 通信以…

1.6 实战:Postman请求Get接口-获取用于登录的图形验证码

上一小节我们学习了Postman的布局,对Postman有了一个整体的认知,本小节我们就来实操一下Get接口。 我们打开Postman,点击我们之前创建的请求”获取登录页验证码“。我们在地址栏里填入获取登录页验证码的接口地址。怎么查看这个接口地址呢?我们打开校园二手交易系统,打开…

Leetcode—2414.最长的字母序连续子字符串的长度【中等】

2023每日刷题&#xff08;六十&#xff09; Leetcode—2414.最长的字母序连续子字符串的长度 实现代码 class Solution { public:int longestContinuousSubstring(string s) {int ans 1;int t 1;for(int i 1; i < s.size(); i) {if(s[i] - s[i - 1] 1) {t;ans max(an…

师兄啊师兄第二季开播:男主成海神?玄机是懂联动的!

《师兄啊师兄》动画第二季在12月14日终于正式开播&#xff0c;首播两集&#xff0c;还是很有诚意的。 这部动画改编自言归正传的小说《我师兄实在太稳健了》&#xff0c;原著的知名度不算很高&#xff0c;但玄机制作的动画让这个IP火出了圈。 动画第一季就凭借高颜值的人物建模…

spring boot 实现直播聊天室

spring boot 实现直播聊天室 技术方案: spring bootwebsocketrabbitmq 使用 rabbitmq 提高系统吞吐量 引入依赖 <dependencies><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.42&…

LeetCode 300最长递增子序列 674最长连续递增序列 718最长重复子数组 | 代码随想录25期训练营day52

动态规划算法10 LeetCode 300 最长递增子序列 2023.12.15 题目链接代码随想录讲解[链接] int lengthOfLIS(vector<int>& nums) {//创建变量result存储最终答案,设默认值为1int result 1;//1确定dp数组&#xff0c;dp[i]表示以nums[i]为结尾的子数组的最长长度ve…

VS Code连接远程Linux服务器调试C程序

1.在 VS Code 上安装扩展 C/C 2.通过 VS Code 连接远程 Linux 服务器 3.通过 VS Code 在远程 Linux 服务器上安装扩展 C/C 4.打开远程 Linux 服务器上的文件夹 【注】本文以 /root/ 为例。 5.创建项目文件夹&#xff0c;并在项目文件夹下创建C程序 6.按 F5&#xff0c;选…

mysql中的int(1)和int(10)的区别

今天偶然发现同事在写sql建表的时候把int类型括号后面的数字写成了1&#xff0c;但是我发现数据库里面的值已经远远超过了1位所能表示的范围&#xff0c;所以括号里面的数字肯定不是表示长度了&#xff08;印象中早期的navivat建表的时候&#xff0c;int类型如果默认不指定长度…

devc++如何建立一个c++项目?devc++提示源文件未编译?

打开devc APP后是这样的界面&#xff1b; 点击文件-> 新建->项目&#xff0c;这一点应该不难&#xff0c;主要是最后这个选择什么&#xff1f; 这样即可。 devc提示源文件未编译&#xff1f; 点击工具->编译选项&#xff1b; 如果不能解决&#xff0c;那就是可能路径…

文物数字化建模纹理贴图

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 1、文物3D数字化建模的特点 文物埋在地下历经千年&#xff0c;由于时…

转动惯量与惯性张量 的推导

从牛顿第二定律推出绕固定轴旋转的转动惯量&#xff0c;再用类似方法从牛顿第二定律推出绕固定点转动的惯性张量 基础定义 角速度 ω \omega ω是一个三维向量&#xff0c;方向表示旋转轴&#xff0c;用右手定则代表旋转方向&#xff0c;长度代表旋转弧度的速度 线速度&#…

WebGL+Three.js入门与实战——给画布换颜色、绘制一个点、三维坐标系

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

为了吃鸡苦练狙击,避免坑队友自己造一个狙击游戏!

引言 一文教会你造一个简易的狙击游戏。 说到狙击&#xff0c;相信大家都不陌生&#xff0c;无论是影视作品还是网络游戏&#xff0c;都经常能看到狙击枪的身影&#xff0c;最深刻的是它能够从百里之外&#xff0c;一枪爆头。 本文将介绍如何在Cocos Creator中造一个简易的狙…

UE5 动画 Sequencer-学习笔记

P2. 课程介绍 资料&#xff1a;https://www.bilibili.com/video/BV1Ag411873f?p2&vd_source707ec8983cc32e6e065d5496a7f79ee6 Sequencer不仅可以做互动动画&#xff0c;还可以导出视频与序列帧 P3-4. 界面介绍 https://www.bilibili.com/video/BV1Ag411873f?p3&spm_…

数据挖掘任务一般流程

数据挖掘是从大量数据中提取有价值信息的过程。它涉及多个步骤&#xff0c;每一步都对整个数据挖掘过程至关重要。以下是数据挖掘任务的一般流程&#xff1a; 业务理解&#xff1a; 确定业务目标。评估当前情况。定义数据挖掘问题。制定一个初步计划来达到这些目标。 数据理…

WPF-附加属性《十二》

非常重要 依赖属性和附加属性&#xff0c;两者是有关系的&#xff0c;也是有些区别的&#xff0c;很多时候&#xff0c;可能会把两者混淆了。 附加属性&#xff08;Attach Property&#xff09; 顾名思义&#xff0c;就是附加上面的属性&#xff0c;自身是没有的&#xff0c;…

人工智能在红斑狼疮应用主要以下4个方面

人工智能&#xff08;Artificial Intelligence, AI&#xff09;在医学领域的应用已取得了一定的进展。红斑狼疮&#xff08;Systemic Lupus Erythematosus, SLE&#xff09;是一种免疫系统性疾病&#xff0c;对该疾病进行诊断和治疗是一个复杂的过程。人工智能可以发挥作用&…

如何在Centos 7环境下安装MySQL并登录

目录 先获取MySQL官方yum源 然后正常使用yum命令下载mysql即可完成MySQL的下载 使用mysql客户端登录mysqld服务端 能够登录mysql客户端后&#xff0c;我们最后还需要做一点配置 先获取MySQL官方yum源&#xff08;包括对yum源的介绍&#xff09; 介绍一下yum源 yum源就是一…

瞳孔检测眼动追踪python实现(基于dlib)

效果展示&#xff1a; 原图&#xff1a;&#xff08;图片来自 b站up 借我300去洗牙&#xff09; dlib实现的特征点检测 瞳孔检测结果 完整代码&#xff1a; # encoding:utf-8import dlib import numpy as np import cv2def rect_to_bb(rect): # 获得人脸矩形的坐标信息x …