安卓学习日志 — Day05

概述

上次已经为 Miwok 应用的每个页面的列表项设置了单词图片和 主题色

接下来将 为 所有页面的 单词 和 词组 添加音频播放的功能,使在屏幕中单击 任意一个 单词或词组使,播放对应的音频文件。

不过在此之前,有必要 先创建一个与 Miwok 应用独立开来的 小型音频播放应用。

开发者通常会写一个小应用来测试下新技术,然后将该技术添加到自己的大型应用中。

目标

  • 新创建一个小型音频播放应用
  • 应用中有一个播放按钮用于播放音频
  • 应用中有一个暂停按钮用于暂停播放
  • 两个用于快进和后退的按钮

实现过程

应用布局

这个音频播放器的外观和 日常生活中所使用的音乐播放器 类似:

在这里插入图片描述

可以看出 音乐播放应用的界面基本分为上下两部分:

上部分显示音乐播放器的 名称和图片,下部分为 音频的控制区域 ,用于控制音频的 播放暂停快进后退,还有一个拖动条 用于实时显示 音频播放的文章。

下部分中还有三个文本其余,用于显示 音频的名称、总时长 和 播放的位置。

媒体播放器

在此之前我并不会在 Android 应用 中 播放 音频,经过在网上查阅之后 发现可以使用 MediaPlayer API 来实现音频的播放等操作,接着再查看 Android MediaPlayer 的相关文档,了解基本的使用方法(相关文章的链接为都放到了文末的参考链接当中)。

在 Android app 中 ,主要使用一下代码实现 音频的播放:

class MainActivity extends Activity {
    
    
	MediaPlayer mediaPlayer;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
    
    
	    super.onCreate(savedInstanceState);
	    setContentView(R.layout.activity_main);
        
	    mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.yoursong);	
	    mediaPlayer.start();	
	}
	
	@Override
	protected void onPause() {
    
    
	    super.onPause();
	    mediaPlayer.stop();
	    mediaPlayer.release();
	}
}
  • 2 行,在 Activity 中 声明 一个 MediaPlayer 类型的 媒体播放器 成员变量
  • 9 行,创建 MediaPlayer 对象 ,传入 上下文 context 和 音频资源文件的id
  • 10 行,启动 媒体播放器,即 开始播放音频
  • 13 ~ 18 行,当Activity 被暂停后,关掉 媒体播放器,并释放其占用的内存资源

在 第 9 行 为 媒体播放器 指定音频资源id,使用的是 raw 类型的资源(需要新建),在右侧的 res 目录上鼠标右键 --> 选择 New --> 选择 Android Resource Directory

接着 在弹出的窗口中 将 Resource type 选成 raw ,这时 Directory name 页面 变成 raw ,最后点击 ok 即可完成 raw 类型资源目录的创建。

在这里插入图片描述

然后将音频文件放到 raw 文件夹当中,就可以在代码中以 R.raw.song 的形式来访问 资源ID了。

在这里插入图片描述

由于版权原因,不提供任何音频文件。建议自己选择一个 可用且有趣的音频文件,并添加到自己的 Music Player 应用中。

进度条和时间显示

首先获取所有需要用到的控件的视图对象,并设置其初始状态

onCreate 方法中添加:

        playButton = (Button) findViewById(R.id.play_button);
        pauseButton = (Button) findViewById(R.id.pause_button);
        forwardButton = (Button) findViewById(R.id.forward_button);
        backwardButton = (Button) findViewById(R.id.backward_button);

        playedTime = (TextView) findViewById(R.id.played_time_text_view);
        totalTime = (TextView) findViewById(R.id.total_time_text_view);
        musicName = (TextView) findViewById(R.id.music_name_text_view);
        musicName.setText("Always With Me - Meja");

        mediaPlayer = MediaPlayer.create(this, R.raw.always_with_me_by_meja);
        seekbar = (SeekBar) findViewById(R.id.seekBar);
        seekbar.setClickable(false);
        pauseButton.setEnabled(false);
  • 9 行,设置默认显示的音频名称
  • 13 行,禁止拖动 音频的进度条(拖动条)
  • 14 行,禁用暂停按钮

不要往先在 MainActivity 中声明这些成员变量:

    private Button forwardButton, pauseButton, playButton, backwardButton;
    private MediaPlayer mediaPlayer;

    private double startTime = 0;
    private double finalTime = 0;

    private Handler myHandler = new Handler();

    private final int forwardTime = 5000;
    private final int backwardTime = 5000;
    private SeekBar seekbar;
    private TextView playedTime, totalTime, musicName;

    public static int oneTimeOnly = 0;

播放功能

点击播放按钮时即播放音频,触发 OnClick 事件,因此为 播放按钮注册 OnClickListener 如下:

        playButton.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View v) {
    
    
                Toast.makeText(getApplicationContext(), "Playing sound", Toast.LENGTH_SHORT).show();

                mediaPlayer.start();

                finalTime = mediaPlayer.getDuration();
                startTime = mediaPlayer.getCurrentPosition();

                if (oneTimeOnly == 0) {
    
    
                    seekbar.setMax((int) finalTime);
                    oneTimeOnly = 1;
                }

                totalTime.setText(String.format("%02d:%02d",
                        TimeUnit.MILLISECONDS.toMinutes((long) finalTime),
                        TimeUnit.MILLISECONDS.toSeconds((long) finalTime) -
                                TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long)
                                        finalTime)))
                );

                playedTime.setText(String.format("%02d:%02d",
                        TimeUnit.MILLISECONDS.toMinutes((long) startTime),
                        TimeUnit.MILLISECONDS.toSeconds((long) startTime) -
                                TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long)
                                        startTime)))
                );

                seekbar.setProgress((int) startTime);
                myHandler.postDelayed(UpdateSongTime, 100);
                pauseButton.setEnabled(true);
                playButton.setEnabled(false);
            }
        });
  • 4 行,消息框提示
  • 6 行,启动媒体播放器,开始播放音频
  • 8 - 9 行,获取被播放音频的开始时间和 总时长
  • 11 - 14 行,判断是否为首次播放音频,并设置拖动条的最大值
  • 16 -21 行,在页面中显示 音频的总时长
  • 23 - 28行,在页面中显示 已经已经播放的音频时长
  • 30 行,设置 拖动条的焦点 到音频开始播放的位置
  • 32 行,启动暂停按钮
  • 33 行,禁用播放按钮

暂停功能

点击暂停按钮时即停止播放,触发 OnClick 事件,因此为 播放按钮注册 OnClickListener 如下:

	pauseButton.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View v) {
    
    
                Toast.makeText(getApplicationContext(), "Pausing sound", Toast.LENGTH_SHORT).show();
                mediaPlayer.pause();
                pauseButton.setEnabled(false);
                playButton.setEnabled(true);
            }
        });
  • 5 行,暂停媒体播放器
  • 6 行,禁用暂停按钮
  • 7 行,启用播放按钮

当点击暂停按钮后,自然不能再按暂停,而是等待 点击 播放按钮 播放音频。

快进功能

每点击快进按钮一次,将音频的播放位置快进 5 秒。

        forwardButton.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View v) {
    
    
                int temp = (int) startTime;

                if ((temp + forwardTime) <= finalTime) {
    
    
                    startTime = startTime + forwardTime;
                    mediaPlayer.seekTo((int) startTime);
//                    Toast.makeText(getApplicationContext(), "You have Jumped forward 5 seconds", Toast.LENGTH_SHORT).show();
                } else {
    
    
                    Toast.makeText(getApplicationContext(), "Cannot jump forward 5 seconds", Toast.LENGTH_SHORT).show();
                }
            }
        });

在 6- 12 行中,首先 判断 音频当前播放到的位置是否可以 快进 5秒 ,如可以,则使媒体播放器的播放位置 跳转 的当前时间 再加 5 秒的位置;反之则弹出提示,,表示不能快进。

后退功能

每点击后退按钮一次,将音频的播放位置后退 5 秒。

        backwardButton.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View v) {
    
    
                int temp = (int) startTime;
                if ((temp - backwardTime) > 0) {
    
    
                    startTime = startTime - backwardTime;
                    mediaPlayer.seekTo((int) startTime);
//                    Toast.makeText(getApplicationContext(), "You have Jumped backward 5 seconds", Toast.LENGTH_SHORT).show();
                } else {
    
    
                    Toast.makeText(getApplicationContext(), "Cannot jump backward 5 seconds", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

在 5- 11 行中,首先 判断 音频当前播放到的位置是否可以 后退 5秒 ,如可以,则使媒体播放器的播放位置 跳转 的当前时间 再减去 5 秒的位置;反之则弹出提示,,表示不能后退。

总结

音频的播放和暂停功能相对来说还是容易实现的,而 快进 和 后退 功能则稍难一点 ,主要是 获取音频实时播放到的位置。

最后遇到一个问题,我为媒体播放器 对象 绑定了一个 当音频播放完成十触发的监听器 OnCompletionListener,本打算当音频播放完成时回收音频暂用的内存资源,但当我使用 Toast 测试该功能时失败了,目前仍待解决。

参考

MediaPlayer | Android Developers

How to Play Music in Android Studio? - Stack Overflow

阿里巴巴矢量图标库: Iconfont

MediaPlayer 教程

OnCompletion listener with MediaPlayer - Stack Overflow

猜你喜欢

转载自blog.csdn.net/weixin_45075891/article/details/112503832