Android studio implements a simple music player through a bound Service

Table of contents

Article directory

foreword

1. What is Service?

2. Demonstration video

3. Steps

1. Music files

2. Picture file

3. Code


foreword

I recently started to learn Android studio, and used a bound Service to make a music player that exits automatically and stops


1. What is Service?

  1. Service is one of the four major components of Android, and Service has a higher priority than Activity.
  2. Serive can run in the background for a long time without providing a user interface. Its application scenarios are writing service programs without a working interface and running across threads.
  3. Service can be divided into explicit startup and implicit startup according to the usage method;
  4. The design of the service class is related to its startup method. There are two startup methods: startService (non-binding method) and bindService (binding method);
  5. Service can be divided into local calls and remote service calls according to the host program. Remote service calls need the help of AIDL.

2. Demonstration video

Android implements a simple music player through a bound Service-CSDN Live

3. Steps

1. Music files

Add a raw folder under the res folder, and add music files. The naming rules can only be az, 0-9, and underscore _. Capital letters and - are not allowed.

2. Picture file

Paste the image file into the drawable folder under the res folder, and the naming rules are the same as above.

 

 

 

 

 

3. Code

xml layout file

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/y"
    android:gravity="center"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="456dp"
        android:layout_alignParentTop="true">

        <ImageButton
            android:layout_width="55dp"
            android:layout_height="55dp"
            android:background="@drawable/g"
            android:scaleType="centerCrop"
            android:id="@+id/btn_exit"/>

        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:text="The Fall"
            android:textColor="#FFFFFFFF"
            android:textSize="30dp" />

        <ImageButton
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_marginLeft="92dp"
            android:layout_toRightOf="@+id/textView"
            android:background="@drawable/h"
            android:scaleType="centerCrop" />

        <TextView
            android:id="@+id/gesou"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/textView"
            android:layout_centerHorizontal="true"
            android:text="Lovejoy>"
            android:textColor="#A8A8A8"
            android:textSize="20dp" />

        <ImageView
            android:id="@+id/iv_music"
            android:layout_width="260dp"
            android:layout_height="260dp"
            android:layout_below="@+id/gesou"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="55dp"
            android:scaleType="centerCrop"
            android:src="@drawable/b" />

        <RelativeLayout
            android:id="@+id/rl_title"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_alignParentBottom="true"
            android:layout_centerInParent="true">


            <SeekBar
                android:id="@+id/sb"
                android:layout_width="350dp"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="20dp"
                android:thumb="@null" />

            <RelativeLayout
                android:id="@+id/rl_time"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_above="@id/rl_title"
                android:layout_alignParentBottom="true"
                android:layout_marginTop="4dp"
                tools:ignore="NotSibling">

                <TextView
                    android:id="@+id/tv_progress"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="00:00"
                    android:textColor="#A8A8A8"
                    android:textSize="20sp" />

                <TextView
                    android:id="@+id/tv_total"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:text="00:00"
                    android:textColor="#A8A8A8"
                    android:textSize="20sp" />
            </RelativeLayout>
        </RelativeLayout>


    </RelativeLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_vertical">
        <Button
            android:id="@+id/btn_play"
            android:layout_width="82dp"
            android:layout_height="80dp"
            android:layout_margin="28dp"
            android:background="@drawable/bofang" />

        <Button
            android:id="@+id/btn_pause"
            android:layout_width="82dp"
            android:layout_height="80dp"
            android:layout_margin="28dp"
            android:background="@drawable/zanting" />

        <Button
            android:id="@+id/btn_continue_play"
            android:layout_width="82dp"
            android:layout_height="80dp"
            android:layout_margin="28dp"
            android:background="@drawable/jixv" />
    </LinearLayout>
</LinearLayout>

activity.java file

package cn.itcast.musicplayer;

import android.animation.ObjectAnimator;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener
{
    private static SeekBar sb;
    private static TextView tv_progress, tv_total;
    private ObjectAnimator animator;
    private MusicService.MusicControl musicControl;
    MyServiceConn conn;
    Intent intent;
    private boolean isUnbind = false;//记录服务是否被解绑
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }
    private void init() {
        tv_progress = findViewById(R.id.tv_progress);
        tv_total = findViewById(R.id.tv_total);
        sb = findViewById(R.id.sb);
        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_exit).setOnClickListener(this);
        intent = new Intent(this, MusicService.class);//创建意图对象
        conn = new MyServiceConn();                       //创建服务连接对象
        bindService(intent, conn, BIND_AUTO_CREATE);  //绑定服务
        //为滑动条添加事件监听
        sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @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);         //改变播放进度
            }
        });
        ImageView iv_music = findViewById(R.id.iv_music);
        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() {//创建消息处理器对象
        //在主线程中处理从子线程发送过来的消息
        @Override
        public void handleMessage(Message msg) {
            Bundle bundle = msg.getData(); //获取从子线程发送过来的音乐播放进度
            int duration = bundle.getInt("duration");                  //歌曲的总时长
            int currentPostition = bundle.getInt("currentPosition");//歌曲当前进度
            sb.setMax(duration);                //设置SeekBar的最大值为歌曲总时长
            sb.setProgress(currentPostition);//设置SeekBar当前的进度位置
            //歌曲的总时长
            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 = currentPostition / 1000 / 60;
            second = currentPostition / 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);      //解绑服务
            stopService(intent);      //停止服务
        }
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_play:                //播放按钮点击事件
                musicControl.play();           //播放音乐
                animator.start();             //播放动画
                break;
            case R.id.btn_pause:               //暂停按钮点击事件
                musicControl.pausePlay();     //暂停播放音乐
                animator.pause();              //暂停播放动画
                break;
            case R.id.btn_continue_play:     //继续播放按钮点击事件
                musicControl.continuePlay(); //继续播放音乐
                animator.start();              //播放动画
                break;
            case R.id.btn_exit:                //退出按钮点击事件
                unbind(isUnbind);               //解绑服务绑定
                isUnbind = true;                //完成解绑服务
                finish();                         //关闭音乐播放界面
                break;
        }
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbind(isUnbind); //解绑服务
    }
}

service file

package cn.itcast.musicplayer;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
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;
    public MusicService() {}
    @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 = MainActivity.handler.obtainMessage();//创建消息对象
                    //将音乐的总时长和播放进度封装至消息对象中
                    Bundle bundle = new Bundle();
                    bundle.putInt("duration", duration);
                    bundle.putInt("currentPosition", currentPosition);
                    msg.setData(bundle);
                    //将消息发送到主线程的消息队列
                    MainActivity.handler.sendMessage(msg);
                }
            };
            //开始计时任务后的5毫秒,第一次执行task任务,以后每500毫秒执行一次
            timer.schedule(task, 5, 500);
        }
    }
    class MusicControl extends Binder {
        public void play() {
            try {
                player.reset();//重置音乐播放器
                //加载多媒体文件
                player = MediaPlayer.create(getApplicationContext(), R.raw.music);
                player.start();//播放音乐
                addTimer();     //添加计时器
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        public void pausePlay() {
            player.pause();           //暂停播放音乐
        }
        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置为空
    }
}

 


 

Summarize

The above is the simple music player I made. I hope it can help Xiaobai who just started learning Android studio like me. The code in this article is relatively rough. Welcome to correct me :)

Guess you like

Origin blog.csdn.net/qq_51986572/article/details/127855273