在Android Studio中如何实现综合实验MP3播放器(保姆级教程)

目录

一.本章要学习的内容

二.代码部分

(一)创建项目

(二)项目结构

(三)MainActivity

(四)MusicService

(五)activity_main.xml

(六)q.xml

(七)AndroidManifest.xml

三.运行部分

[(一)打开Device Manager](#(一)打开Device Manager)

(二)选择上次创建的虚拟机

(三)运行

(四)运行结果

一.本章要学习的内容

  1. 掌握 Android 程序的整体的设计;
  2. 融合Android的知识点;
  3. 理解Android工程的架构;
    MP 3 播放器

二.代码部分

(一)创建项目

(二)项目结构

++这里的raw包下面的china.mp3可以替换为任意的歌曲++

(三)MainActivity

package com.example.demo8;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

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 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 org.w3c.dom.Text;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private ImageView iv_cover;
    private static SeekBar sb;
    private static TextView tv_progress, tv_total;
    private Button btn_play, btn_pause, btn_continue, btn_exit;
    private ObjectAnimator animator;

    private MusicService.MusicController musicController;//音乐服务控制器 Binder实例
    private MyserviceConn myserviceConn; //连接实例
    private Intent intent; //全局亿图
    private boolean isUnbind = false;  //记录是否被解绑

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();

    }
    private void initView(){
        iv_cover = findViewById(R.id.iv_cover);
        animator = ObjectAnimator.ofFloat(iv_cover,"rotation",0f,360.0f);
        animator.setDuration(10000); //旋转一周的时长
        animator.setInterpolator(new LinearInterpolator());  //匀速转动
        animator.setRepeatCount(-1);  //-1表示无限循环播放

        sb = findViewById(R.id.sb);
        sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            //滑动条变化的处理
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                if( i == seekBar.getMax()){  //滑动最大值,结束动画
                    animator.pause();
                }
            }
            //开始滑动时的处理
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }
            //停止滑动的处理
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                int progress = seekBar.getProgress();  //获取进度值
                //调用服务的seekTo方法改进音乐进度
                musicController.seekTo(progress);
            }
        });

        tv_progress = findViewById(R.id.tv_progress);
        tv_total = findViewById(R.id.tv_total);

        btn_play = findViewById(R.id.play);
        btn_pause = findViewById(R.id.pause);
        btn_continue = findViewById(R.id.continue2);
        btn_exit = findViewById(R.id.stop);

        intent = new Intent(MainActivity.this,MusicService.class);
        myserviceConn = new MyserviceConn();
        bindService(intent,myserviceConn,BIND_AUTO_CREATE);

        btn_play.setOnClickListener(this);
        btn_pause.setOnClickListener(this);
        btn_continue.setOnClickListener(this);
        btn_exit.setOnClickListener(this);
    }

    //自定义解绑方法
    private void myUnbind(boolean isUnbind){
        if(!isUnbind){
            isUnbind = true;
            musicController.pausePlay();  //暂停播放
            unbindService(myserviceConn); //解绑
            stopService(intent);
        }
    }

    //用于实现连接服务的自定义类
    class MyserviceConn implements ServiceConnection{

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            musicController = (MusicService.MusicController)iBinder;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.play:
                musicController.play();
                animator.start();
                break;
            case R.id.pause:
                musicController.pausePlay();
                animator.pause();
                break;
            case R.id.continue2:
                musicController.continePlay();
                animator.start();
                break;
            case R.id.stop:
                myUnbind(isUnbind);
                finish();

                break;
        }
    }

    //创建消息处理的对象、
    public static Handler handler = new Handler(){
        //处理子线程传来的消息
        @Override
        public void handleMessage(@NonNull Message msg) {
            Bundle bundle = msg.getData(); //获取信息
            int duration = bundle.getInt("duration");
            int currentDuration = bundle.getInt("currentDuration");

            sb.setProgress(currentDuration);
            sb.setMax(duration);


            //显示总时长
            int minute = duration/1000/60;
            int second = duration/1000%60;
            String strMinute = "";
            String strSecond = "";
            if(minute<10){
                strMinute = "0"+minute;
            }else{
                strMinute = minute + "";
            }
            if(second<10){
                strSecond = "0"+second;
            }else{
                strSecond = second + "";
            }
            //显示总时长结束
            tv_total.setText(strMinute+":"+strSecond);


            //显示播放时长开始
            minute = currentDuration/1000/60;
            second = currentDuration/1000%60;
            if(minute<10){
                strMinute = "0"+minute;
            }else{
                strMinute = minute + "";
            }
            if(second<10){
                strSecond = "0"+second;
            }else{
                strSecond = second + "";
            }
            tv_progress.setText(strMinute+":"+strSecond);
            //播放时长结束

        }
    };

}

(四)MusicService

package com.example.demo8;

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.sql.Time;
import java.util.Timer;
import java.util.TimerTask;


public class MusicService extends Service {
    private MediaPlayer player;  //播放组件
    private Timer timer;    //计时器

    public MusicService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        player = new MediaPlayer();  //实例化
    }

    @Override
    public IBinder onBind(Intent intent) {
        return  new MusicController();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if(player==null) return;
        if(player.isLooping()){
            player.stop();
        }
        player.release();  //释放资源
        player = null;
    }



    //添加计时器 用于进度条
    public void addTime(){
        if(timer == null){
            timer = new Timer();
            TimerTask taksk = new TimerTask() {
                @Override
                public void run() {
                    if(player==null){
                        return;
                    }
                    //分别获取总长度和播放进度
                    int duration = player.getDuration();
                    int currentDuration = player.getCurrentPosition();

                    //创建Message对象
                    Message msg = MainActivity.handler.obtainMessage();
                    //将音乐的总时长,播放时长封装到消息对象中
                    Bundle bundle = new Bundle();
                    bundle.putInt("duration",duration);
                    bundle.putInt("currentDuration",currentDuration);
                    msg.setData(bundle);
                    //将消息添加到主线程
                    MainActivity.handler.sendMessage(msg);
                }
            };
            //开始计时任务后 5毫秒 执行第一次任务 以后500毫秒执行一次任务
            timer.schedule(taksk,5,500);
        }
    }

    //自定义一个Binder类
    class MusicController extends Binder{
        public void play(){
            try{
                player.reset(); //重置音乐播放器
                //加载多媒体文件
                player = MediaPlayer.create(getApplicationContext(),R.raw.china);
                player.start();
                addTime(); //添加计时器
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        public void pausePlay(){
            player.pause();  //暂停音乐播放
        }
        public void continePlay(){
            player.start();  //暂停音乐播放
        }
        public void seekTo(int progress){
            player.seekTo(progress);  //设置音乐的播放位置
        }
    }

}

(五)activity_main.xml

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

    <ImageView
        android:id="@+id/iv_cover"
        android:layout_width="240dp"
        android:layout_height="240dp"
        android:layout_marginTop="100dp"
        android:layout_gravity="center_horizontal"
        android:src="@drawable/ic_launcher_foreground"/>

    <SeekBar
        android:id="@+id/sb"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp">

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

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

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:orientation="horizontal">
        <Button
            android:id="@+id/play"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="播放音乐"
            android:textSize="16sp"
            android:layout_margin="5dp"
            android:background="@drawable/btn_bg_selector"
            android:layout_weight="1"/>
        <Button
            android:id="@+id/pause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="暂停播放"
            android:textSize="16sp"
            android:layout_margin="5dp"
            android:background="@drawable/btn_bg_selector"
            android:layout_weight="1"/>
        <Button
            android:id="@+id/continue2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="继续播放"
            android:textSize="16sp"
            android:layout_margin="5dp"
            android:background="@drawable/btn_bg_selector"
            android:layout_weight="1"/>
        <Button
            android:id="@+id/stop"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="退出播放"
            android:textSize="16sp"
            android:layout_margin="5dp"
            android:background="@drawable/btn_bg_selector"
            android:layout_weight="1"/>
    </LinearLayout>
</LinearLayout>

(六)q.xml

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

</LinearLayout>

(七)AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.demo8">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Demo8">

        <activity android:name="com.example.demo8.MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name="com.example.demo8.MusicService"/>
    </application>

</manifest>

三.运行部分

(一)打开Device Manager

(二)选择上次创建的虚拟机

(三)运行

(四)运行结果

相关推荐
Dwyane031 小时前
Android实战经验篇-AndroidScrcpyClient投屏一
android
FlyingWDX1 小时前
Android 拖转改变视图高度
android
沉默的煎蛋1 小时前
前后端交互过程
java·开发语言·ide·vscode·eclipse·状态模式·交互
_可乐无糖1 小时前
Appium 检查安装的驱动
android·ui·ios·appium·自动化
吉吉安3 小时前
VSCode最新离线插件拓展下载方式
ide·vscode·编辑器
一名技术极客3 小时前
Python 进阶 - Excel 基本操作
android·python·excel
lichong9514 小时前
【Flutter&Dart】MVVM(Model-View-ViewModel)架构模式例子-http版本(30 /100)
android·flutter·http·架构·postman·win·smartapi
刘争Stanley4 小时前
Android系统开发(六):从Linux到Android:模块化开发,GKI内核的硬核科普
android·linux·运维·内核·镜像·gki·kmi
五味香4 小时前
Java学习,List截取
android·java·开发语言·python·学习·golang·kotlin