Android Studio 做一个 MP3 播放器

关于 Android Studio 做一个 MP3 播放器:

  1. Android Studio 本身提供了多个音频播放器组件,可以通过这些组件来实现音频播放功能,其中包括 MediaPlayer、SoundPool 和 ExoPlayer 等。官方推荐我们使用ExoPlayer因为功能更强大,但这里用MediaPlayer因为编写更简单。

  2. 在使用 MediaPlayer 实现 MP3 播放器时,需要注意以下几点:

    • 在使用 MediaPlayer 之前,需要申请 “android.permission.READ_EXTERNAL_STORAGE” 权限,以读取本地储存的 MP3 文件。

    • 在代码中,需要实例化一个 MediaPlayer 对象,并设置其数据源、音频焦点、循环播放等属性。

    • 然后,通过调用 MediaPlayer 对象的 start() 方法,就可以开启播放功能。

  3. 这里提供一些关于 MediaPlayer 的资源链接:

    • 官方文档:https://developer.android.com/reference/android/media/MediaPlayer
    • 实现 MP3 播放器的教程:https://www.androidhive.info/2012/03/android-building-audio-player-tutorial/
    • GitHub 上的相关代码:https://github.com/DeweyReed/android_media_player

开发一个基本的 MP3 播放器需要以下步骤:

1.创建一个新的 Android Studio 项目

2.在 layout 文件夹中创建 UI 布局,包括播放/暂停按钮、进度条和音乐信息

3.在 drawable 文件夹中添加播放/暂停图标

4.导入 jaudiotagger 库以读取 MP3 文件的元数据

5.使用 MediaPlayer 类实现 MP3 文件的播放与控制

下面是一个简单的代码示例来实现这些步骤:

1.创建一个新的 Android Studio 项目

在 Android Studio 中,选择 File -> New -> New Project。在弹出窗口中,输入应用名称、包名和项目位置等信息创建新项目。

2.创建 UI 布局

在 res/layout 文件夹中创建一个名为 activity_main.xml 的布局文件。

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

    <TextView
        android:id="@+id/song_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Song Title"
        android:textAppearance="?android:attr/textAppearanceLarge"/>

    <TextView
        android:id="@+id/song_artist"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Song Artist"
        android:layout_below="@id/song_title"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

    <ImageView
        android:id="@+id/song_album_art"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/song_artist"
        android:src="@drawable/default_album_art"
        android:scaleType="fitCenter"/>

    <SeekBar
        android:id="@+id/seek_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/song_album_art"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/seek_bar"
        android:orientation="horizontal">

        <ImageButton
            android:id="@+id/play_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/play_button"/>

        <ImageButton
            android:id="@+id/pause_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/pause_button"
            android:visibility="gone"/>
    </LinearLayout>

</RelativeLayout>

该布局中包括音乐标题、艺术家、专辑封面、进度条和播放/暂停按钮。

3.导入播放/暂停图标

在 res/drawable 文件夹中添加两个名为 play_button.png 和 pause_button.png 的图标。您可以在网上搜索并下载这些图标,然后将它们拖放到 Android Studio 项目中。

4.导入 jaudiotagger 库

在项目的 build.gradle 文件中添加以下依赖项:

dependencies {
    implementation 'org.jaudiotagger:jaudiotagger:2.0.4'
}

这个库可以用于读取 MP3 文件的元数据,例如标题、艺术家和专辑信息。

5.使用 MediaPlayer 类实现 MP3 文件的播放和控制

在 MainActivity.java 文件中添加以下代码:

public class MainActivity extends AppCompatActivity {

    private MediaPlayer mediaPlayer;
    private ImageButton playButton, pauseButton;
    private boolean isPlaying;
    private TextView songTitle, songArtist;
    private ImageView albumArt;
    private SeekBar seekBar;
    private Handler mHandler = new Handler();

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

        songTitle = findViewById(R.id.song_title);
        songArtist = findViewById(R.id.song_artist);
        albumArt = findViewById(R.id.song_album_art);
        seekBar = findViewById(R.id.seek_bar);
        playButton = findViewById(R.id.play_button);
        pauseButton = findViewById(R.id.pause_button);

        // Load the audio file from the asset folder into the MediaPlayer
        AssetFileDescriptor fileDescriptor = null;
        try {
            fileDescriptor = getAssets().openFd("sample_music.mp3");
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setDataSource(fileDescriptor.getFileDescriptor(), fileDescriptor.getStartOffset(), fileDescriptor.getLength());
        } catch (IOException e) {
            e.printStackTrace();
        }

        // Initialize the MediaPlayer and UI elements
        mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                int duration = mp.getDuration();
                seekBar.setMax(duration);
                songTitle.setText(mp.getMetadata("title"));
                songArtist.setText(mp.getMetadata("artist"));
                albumArt.setImageBitmap(mp.getMetadata("album art"));
                playButton.setVisibility(View.VISIBLE);
                pauseButton.setVisibility(View.GONE);
                isPlaying = false;
            }
        });

        // Update the seek bar progress as the audio is playing
        mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                playButton.setVisibility(View.VISIBLE);
                pauseButton.setVisibility(View.GONE);
                isPlaying = false;
            }
        });

        // Start the MediaPlayer when the play button is clicked
        playButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mediaPlayer != null && !isPlaying) {
                    mediaPlayer.start();
                    mHandler.postDelayed(updateSeekBar, 100);
                    playButton.setVisibility(View.GONE);
                    pauseButton.setVisibility(View.VISIBLE);
                    isPlaying = true;
                }
            }
        });

        // Pause the MediaPlayer when the pause button is clicked
        pauseButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mediaPlayer != null && isPlaying) {
                    mediaPlayer.pause();
                    mHandler.removeCallbacks(updateSeekBar);
                    pauseButton.setVisibility(View.GONE);
                    playButton.setVisibility(View.VISIBLE);
                    isPlaying = false;
                }
            }
        });

    }

    // Update the seek bar progress every second
    private Runnable updateSeekBar = new Runnable() {
        @Override
        public void run() {
            int currentPosition = mediaPlayer.getCurrentPosition();
            seekBar.setProgress(currentPosition);
            mHandler.postDelayed(this, 1000);
        }
    };

    // Release the MediaPlayer when the activity is destroyed
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }

}

该代码中加载了一个名为 sample_music.mp3 的 MP3 文件并将其作为 MediaPlayer 的数据源。在 MediaPlayer 准备好播放文件时,将更新 UI 元素,例如标题、艺术家、专辑封面和时长。另外,为了使播放和暂停按钮正常工作,我们需要检查 MediaPlayer 是否正在播放。

MP3 播放器的基本功能已经实现了。当您点击播放按钮时,音乐会开始播放,并且进度条会随着音乐进度而更新。同样,当您点击暂停按钮时,音乐会暂停。您可以根据自己的需要修改 UI 和播放器的一些设置。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
很抱歉,由于篇幅限制,无法在此处提供完整的代码。但我可以为您提供一些核心代码片段和步骤: 1. 首先,在 build.gradle 中添加以下依赖: ``` dependencies { implementation 'com.google.android.exoplayer:exoplayer:2.12.1' } ``` 2. 在您的布局文件中创建一个用户界面,包含播放/暂停按钮,歌曲名称、歌手和播放进度条。 ``` <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/song_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Song Title" /> <TextView android:id="@+id/song_artist" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Song Artist" /> <SeekBar android:id="@+id/playback_seekbar" android:layout_width="match_parent" android:layout_height="wrap_content" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageButton android:id="@+id/play_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_play_arrow_black_24dp" /> <ImageButton android:id="@+id/pause_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_pause_black_24dp" /> </LinearLayout> </LinearLayout> ``` 3. 创建一个数据模型来存储歌曲的信息,例如歌曲名称、歌手、专辑、时长和文件路径。 ``` data class Song( val title: String, val artist: String, val album: String, val duration: Long, val uri: Uri ) ``` 4. 创建一个歌曲列表,并使用 RecyclerView 显示歌曲信息。 ``` class SongListAdapter( private val songs: List<Song>, private val onItemClick: (Song) -> Unit ) : RecyclerView.Adapter<SongListAdapter.ViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.item_song, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val song = songs[position] holder.titleTextView.text = song.title holder.artistTextView.text = song.artist holder.itemView.setOnClickListener { onItemClick(song) } } override fun getItemCount(): Int = songs.size class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val titleTextView: TextView = itemView.findViewById(R.id.song_title) val artistTextView: TextView = itemView.findViewById(R.id.song_artist) } } ``` 5. 创建一个音乐播放器服务,以便在后台播放音乐,并将其绑定到 Activity 中。 ``` class MusicService : Service() { private lateinit var exoPlayer: SimpleExoPlayer private var currentSong: Song? = null override fun onBind(intent: Intent): IBinder? = MusicBinder() inner class MusicBinder : Binder() { fun getService(): MusicService = this@MusicService } override fun onCreate() { super.onCreate() exoPlayer = SimpleExoPlayer.Builder(this).build() } override fun onDestroy() { super.onDestroy() exoPlayer.release() } fun play(song: Song) { if (song != currentSong) { currentSong = song val mediaItem = MediaItem.fromUri(song.uri) exoPlayer.setMediaItem(mediaItem) exoPlayer.prepare() } exoPlayer.play() } fun pause() { exoPlayer.pause() } fun seekTo(position: Long) { exoPlayer.seekTo(position) } fun getCurrentPosition(): Long = exoPlayer.currentPosition fun getDuration(): Long = exoPlayer.duration fun isPlaying(): Boolean = exoPlayer.isPlaying } ``` 6. 在音乐播放器服务中实现播放、暂停、跳转到下一首和上一首歌曲的功能。 ``` fun play(song: Song) { if (song != currentSong) { currentSong = song val mediaItem = MediaItem.fromUri(song.uri) exoPlayer.setMediaItem(mediaItem) exoPlayer.prepare() } exoPlayer.play() } fun pause() { exoPlayer.pause() } fun seekTo(position: Long) { exoPlayer.seekTo(position) } fun skipToNext() { val currentSongIndex = songs.indexOf(currentSong) val nextSongIndex = (currentSongIndex + 1) % songs.size val nextSong = songs[nextSongIndex] play(nextSong) } fun skipToPrevious() { val currentSongIndex = songs.indexOf(currentSong) val previousSongIndex = if (currentSongIndex == 0) { songs.size - 1 } else { currentSongIndex - 1 } val previousSong = songs[previousSongIndex] play(previousSong) } ``` 7. 在 Activity 中实现与音乐播放器服务的通信,以便更新用户界面和处理用户的输入。 ``` class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private lateinit var musicService: MusicService private var isBound = false private val connection = object : ServiceConnection { override fun onServiceConnected(name: ComponentName?, service: IBinder?) { val binder = service as MusicService.MusicBinder musicService = binder.getService() isBound = true } override fun onServiceDisconnected(name: ComponentName?) { isBound = false } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) val songList = listOf( Song("Song 1", "Artist 1", "Album 1", 180000, Uri.parse("path/to/song1.mp3")), Song("Song 2", "Artist 2", "Album 2", 240000, Uri.parse("path/to/song2.mp3")), Song("Song 3", "Artist 3", "Album 3", 300000, Uri.parse("path/to/song3.mp3")) ) val songListAdapter = SongListAdapter(songList) { song -> musicService.play(song) updateUI() } binding.songList.adapter = songListAdapter binding.playButton.setOnClickListener { musicService.play() updateUI() } binding.pauseButton.setOnClickListener { musicService.pause() updateUI() } binding.playbackSeekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { if (fromUser) { musicService.seekTo(progress.toLong()) } } override fun onStartTrackingTouch(seekBar: SeekBar?) {} override fun onStopTrackingTouch(seekBar: SeekBar?) {} }) } override fun onStart() { super.onStart() bindService(Intent(this, MusicService::class.java), connection, Context.BIND_AUTO_CREATE) } override fun onStop() { super.onStop() if (isBound) { unbindService(connection) isBound = false } } private fun updateUI() { binding.playButton.isEnabled = !musicService.isPlaying() binding.pauseButton.isEnabled = musicService.isPlaying() binding.playbackSeekbar.max = musicService.getDuration().toInt() binding.playbackSeekbar.progress = musicService.getCurrentPosition().toInt() } } ``` 以上是一个简单的步骤和代码示例,希望对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值