在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

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

(三)运行

(四)运行结果

相关推荐
_小马快跑_13 分钟前
ConstraintLayout之layout_constraintDimensionRatio属性详解
android
人猿泰飞1 小时前
【初识Trae】字节跳动推出的下一代AI原生IDE,重新定义智能编程
ide·ai-native·trae·ai原生ide
百锦再1 小时前
Android Studio开发 SharedPreferences 详解
android·ide·android studio
青春给了狗2 小时前
Android 14 修改侧滑手势动画效果
android
CYRUS STUDIO2 小时前
Android APP 热修复原理
android·app·frida·hotfix·热修复
timing9942 小时前
LVGL在VScode的WSL2中仿真
ide·vscode·编辑器
火柴就是我3 小时前
首次使用Android Studio时,http proxy,gradle问题解决
android
limingade3 小时前
手机打电话时电脑坐席同时收听对方说话并插入IVR预录声音片段
android·智能手机·电脑·蓝牙电话·电脑打电话
浩浩测试一下3 小时前
计算机网络中的DHCP是什么呀? 详情解答
android·网络·计算机网络·安全·web安全·网络安全·安全架构
未来之窗软件服务3 小时前
声音分离人声和配乐-从头设计数字生命第4课——仙盟创梦IDE
ide·仙盟创梦ide·数字生命