在本教程中,我们将使用MediaPlayer类在Android应用程序中实现一个基本的音频播放器。我们将添加播放/停止功能,并允许用户使用SeekBar.更改歌曲的位置
Android MediaPlayer
MediaPlayer类用于播放音视频文件。我们将使用的MediaPlayer类的常见方法是:
START()
停止()
Release()-防止内存泄漏。
isPlaying()-让我们知道这首歌是否正在播放。
getDuration()-用于获取总时长。使用这个,我们将知道我们的SeekBar的上限。此函数以毫秒为单位返回持续时间。
setDataSource(FileDescriptor Fd)-设置要播放的文件。
setVolume(Float leftVolume,Float rightVolume)-用于设置音量大小。
我们将播放存储在Android Studio项目的Assets文件夹中的mp3文件。从Assets文件夹中获取声音资产文件
1AssetFileDescriptor descriptor = getAssets().openFd("filename");
2 mediaPlayer.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength());
3 descriptor.close();
为了创建一个播放音频并允许您更改当前歌曲轨道位置的应用程序,我们需要实现三件事:
- MediaPlayer
- 带文本的SeekBar-除拇指外还显示当前进度时间。
- 可运行线程-更新Seekbar。
项目结构
1implementation 'com.android.support:design:28.0.0-alpha3'
代码
Active_main.xml的代码如下所示:
1<?xml version="1.0" encoding="utf-8"?>
2<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
3 xmlns:app="https://schemas.android.com/apk/res-auto"
4 xmlns:tools="https://schemas.android.com/tools"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 android:layout_gravity="center"
8 android:gravity="center"
9 android:layout_margin="16dp"
10 android:orientation="vertical"
11 tools:context=".MainActivity">
12
13 <TextView
14 android:layout_width="wrap_content"
15 android:layout_height="wrap_content"
16 android:gravity="center"
17 android:text="PLAY/STOP SONG.\nSCRUB WITH SEEKBAR"
18 android:textStyle="bold" />
19
20 <SeekBar
21 android:id="@+id/seekbar"
22 android:layout_margin="16dp"
23 android:layout_width="match_parent"
24 android:layout_height="wrap_content"
25 android:layout_gravity="center" />
26
27 <TextView
28 android:id="@+id/textView"
29 android:layout_width="wrap_content"
30 android:layout_height="wrap_content" />
31
32 <android.support.design.widget.FloatingActionButton
33 android:id="@+id/button"
34 android:layout_width="wrap_content"
35 android:layout_height="wrap_content"
36 android:layout_margin="16dp"
37 android:src="@android:drawable/ic_media_play"
38 android:text="PLAY SOUND" />
39
40</LinearLayout>
我们已经添加了一个FloatingActionButon,它将在单击时播放/停止。MainActivity.Java类的代码如下所示:
1package com.journaldev.androidmediaplayersong;
2
3import android.content.res.AssetFileDescriptor;
4import android.media.MediaPlayer;
5import android.support.design.widget.FloatingActionButton;
6import android.support.v4.content.ContextCompat;
7import android.support.v7.app.AppCompatActivity;
8import android.os.Bundle;
9import android.view.View;
10import android.widget.SeekBar;
11import android.widget.TextView;
12
13public class MainActivity extends AppCompatActivity implements Runnable {
14
15 MediaPlayer mediaPlayer = new MediaPlayer();
16 SeekBar seekBar;
17 boolean wasPlaying = false;
18 FloatingActionButton fab;
19
20 @Override
21 protected void onCreate(Bundle savedInstanceState) {
22 super.onCreate(savedInstanceState);
23 setContentView(R.layout.activity_main);
24
25 fab = findViewById(R.id.button);
26
27 fab.setOnClickListener(new View.OnClickListener() {
28 @Override
29 public void onClick(View view) {
30 playSong();
31 }
32 });
33
34 final TextView seekBarHint = findViewById(R.id.textView);
35
36 seekBar = findViewById(R.id.seekbar);
37
38 seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
39 @Override
40 public void onStartTrackingTouch(SeekBar seekBar) {
41
42 seekBarHint.setVisibility(View.VISIBLE);
43 }
44
45 @Override
46 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
47 seekBarHint.setVisibility(View.VISIBLE);
48 int x = (int) Math.ceil(progress / 1000f);
49
50 if (x 0 && mediaPlayer != null && !mediaPlayer.isPlaying()) {
51 clearMediaPlayer();
52 fab.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, android.R.drawable.ic_media_play));
53 MainActivity.this.seekBar.setProgress(0);
54 }
55
56 }
57
58 @Override
59 public void onStopTrackingTouch(SeekBar seekBar) {
60
61 if (mediaPlayer != null && mediaPlayer.isPlaying()) {
62 mediaPlayer.seekTo(seekBar.getProgress());
63 }
64 }
65 });
66 }
67
68 public void playSong() {
69
70 try {
71
72 if (mediaPlayer != null && mediaPlayer.isPlaying()) {
73 clearMediaPlayer();
74 seekBar.setProgress(0);
75 wasPlaying = true;
76 fab.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, android.R.drawable.ic_media_play));
77 }
78
79 if (!wasPlaying) {
80
81 if (mediaPlayer == null) {
82 mediaPlayer = new MediaPlayer();
83 }
84
85 fab.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, android.R.drawable.ic_media_pause));
86
87 AssetFileDescriptor descriptor = getAssets().openFd("suits.mp3");
88 mediaPlayer.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(), descriptor.getLength());
89 descriptor.close();
90
91 mediaPlayer.prepare();
92 mediaPlayer.setVolume(0.5f, 0.5f);
93 mediaPlayer.setLooping(false);
94 seekBar.setMax(mediaPlayer.getDuration());
95
96 mediaPlayer.start();
97 new Thread(this).start();
98
99 }
100
101 wasPlaying = false;
102 } catch (Exception e) {
103 e.printStackTrace();
104
105 }
106 }
107
108 public void run() {
109
110 int currentPosition = mediaPlayer.getCurrentPosition();
111 int total = mediaPlayer.getDuration();
112
113 while (mediaPlayer != null && mediaPlayer.isPlaying() && currentPosition < total) {
114 try {
115 Thread.sleep(1000);
116 currentPosition = mediaPlayer.getCurrentPosition();
117 } catch (InterruptedException e) {
118 return;
119 } catch (Exception e) {
120 return;
121 }
122
123 seekBar.setProgress(currentPosition);
124
125 }
126 }
127
128 @Override
129 protected void onDestroy() {
130 super.onDestroy();
131 clearMediaPlayer();
132 }
133
134 private void clearMediaPlayer() {
135 mediaPlayer.stop();
136 mediaPlayer.release();
137 mediaPlayer = null;
138 }
139}
在上面的代码中,点击FloatingActionButton,会触发PlaySong函数,在该函数中,我们每隔一秒就会停止歌曲并重置MediaPlayer和FloatingActionButton图标。一旦调用了mediaPlayer.preparate()
,就可以获得歌曲的详细信息。我们现在可以获取持续时间并将其设置为SeekBar最大位置。setLoooping
设置为FALSE可防止歌曲无限播放,直到用户停止播放。我们启动触发run
方法的线程,该方法是我们实现的Runnable接口的一部分。在run方法内部,我们每秒更新进度,这将触发SeekBar侦听器的onProgressChanged方法。在监听器内部,我们已将TextView偏移量设置为SeekBar的拇指下方。我们通过将毫秒转换为秒来设置持续时间。当移动搜索栏时,会触发相同的方法。当用户停止擦洗SeekBar时,会触发onStopTrackingTouch,其中使用earkTo
方法更新MediaPlayer实例上的歌曲位置。歌曲完成后,我们将SeekBar的位置更新回初始位置,并清除MediaPlayer实例。没有音频的应用程序的输出如下:这将结束本教程。你可以从下面的链接下载该项目,并为自己播放这首歌。