1. 写在前面
写一个MP3
播放器,支持播放和暂停。
2. PausablePlayer
PausablePlayer
集成开源项目JLayer
,支持音乐暂停与播放。
<dependency>
<groupId>javazoom</groupId>
<artifactId>jlayer</artifactId>
<version>1.0.1</version>
</dependency>
发现该资源的网址:http://www.voidcn.com/article/p-cucatrfz-buo.html
具体代码如下:(对源代码稍作修改)
package com.music.player;
import java.io.InputStream;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.AudioDevice;
import javazoom.jl.player.Player;
/**
* from http://www.voidcn.com/article/p-cucatrfz-buo.html
*
*/
public class PausablePlayer {
public final static int NOTSTARTED = 0;
public final static int PLAYING = 1;
public final static int PAUSED = 2;
public final static int FINISHED = 3;
// the player actually doing all the work
private final Player player;
// locking object used to communicate with player thread
private final Object playerLock = new Object();
// status variable what player thread is doing/supposed to do
private int playerStatus = NOTSTARTED;
public PausablePlayer(final InputStream inputStream) throws JavaLayerException {
this.player = new Player(inputStream);
}
public PausablePlayer(final InputStream inputStream, final AudioDevice audioDevice) throws JavaLayerException {
this.player = new Player(inputStream, audioDevice);
}
/**
* Starts playback (resumes if paused)
*/
public void play() throws JavaLayerException {
synchronized (playerLock) {
switch (playerStatus) {
case NOTSTARTED:
final Runnable r = new Runnable() {
public void run() {
playInternal();
}
};
final Thread t = new Thread(r);
t.setDaemon(true);
t.setPriority(Thread.MAX_PRIORITY);
playerStatus = PLAYING;
t.start();
break;
case PAUSED:
resume();
break;
default:
break;
}
}
}
/**
* Pauses playback. Returns true if new state is PAUSED.
*/
public boolean pause() {
synchronized (playerLock) {
if (playerStatus == PLAYING) {
playerStatus = PAUSED;
}
return playerStatus == PAUSED;
}
}
/**
* Resumes playback. Returns true if the new state is PLAYING.
*/
public boolean resume() {
synchronized (playerLock) {
if (playerStatus == PAUSED) {
playerStatus = PLAYING;
playerLock.notifyAll();
}
return playerStatus == PLAYING;
}
}
/**
* Stops playback. If not playing, does nothing
*/
public void stop() {
synchronized (playerLock) {
playerStatus = FINISHED;
playerLock.notifyAll();
}
}
private void playInternal() {
while (playerStatus != FINISHED) {
try {
if (!player.play(1)) {
break;
}
} catch (final JavaLayerException e) {
break;
}
// check if paused or terminated
synchronized (playerLock) {
while (playerStatus == PAUSED) {
try {
playerLock.wait();
} catch (final InterruptedException e) {
// terminate player
break;
}
}
}
}
close();
}
/**
* Closes the player, regardless of current state.
*/
public void close() {
synchronized (playerLock) {
playerStatus = FINISHED;
}
try {
player.close();
} catch (final Exception e) {
// ignore, we are terminating anyway
}
}
public int getPlayerStatus() {
return playerStatus;
}
public void setPlayerStatus(int playerStatus) {
this.playerStatus = playerStatus;
}
}
3. 制作图形界面
直接使用Swing
制作。
package com.music.player;
import java.awt.Container;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
public class PlayerFrame extends JFrame {
private static final long serialVersionUID = 9066225937591877119L;
private JButton btnBrowse, playBtn, pauseBtn;
private JTextField textPath;
public PlayerFrame() {
setTitle("音乐播放器");
setLayout(new GridLayout(4, 1));
Container container = getContentPane();
btnBrowse = new JButton("打开文件");
container.add(btnBrowse);
textPath = new JTextField();
container.add(textPath);
playBtn = new JButton("播放");
container.add(playBtn);
pauseBtn = new JButton("暂停");
container.add(pauseBtn);
setVisible(true);
setSize(400, 250);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public JButton getBtnBrowse() {
return btnBrowse;
}
public JButton getPlayBtn() {
return playBtn;
}
public JButton getPauseBtn() {
return pauseBtn;
}
public JTextField getTextPath() {
return textPath;
}
}
4. 成品
给图形界面的按钮添加事件,完成作品。
package com.music.player;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javax.swing.JFileChooser;
import javax.swing.JTextField;
import javazoom.jl.decoder.JavaLayerException;
/**
* 音乐播放示例:Swing + JLayler
*
*/
public class App {
// 声明一个全局变量,方便匿名内部类中使用
public static PausablePlayer pausablePlayer = null;
static File openFile = null;
static JTextField textPath = null;
public static void clear() {
if (pausablePlayer != null) {
pausablePlayer.close();
pausablePlayer = null;
}
}
public static void main(String[] args) {
create();
}
public static void create() {
PlayerFrame playerFrame = new PlayerFrame();
textPath = playerFrame.getTextPath();
// 打开文件按钮添加事件
playerFrame.getBtnBrowse().addActionListener(e -> {
JFileChooser chooser = new JFileChooser(); // 文件选择
chooser.showOpenDialog(chooser); // 打开文件选择窗
openFile = chooser.getSelectedFile(); // 获取选择的文件
// 如果未选择文件,不继续执行
if (openFile == null)
return;
clear(); // 停止上一次选择的音乐
textPath.setText(openFile.getPath()); // 获取选择文件的路径
initPlayer(); // 初始化播放器
});
// 播放按钮添加事件
playerFrame.getPlayBtn().addActionListener(e -> {
if (pausablePlayer == null) {
textPath.setText("请选择一首音乐!");
return;
}
// 如果音乐已播放完,再点击播放可重新开始播放
if (PausablePlayer.FINISHED == pausablePlayer.getPlayerStatus()) {
initPlayer();
}
try {
pausablePlayer.play();
} catch (JavaLayerException e1) {
e1.printStackTrace();
}
});
// 暂停按钮添加事件
playerFrame.getPauseBtn().addActionListener(e -> {
if (pausablePlayer == null) {
textPath.setText("请选择一首音乐!");
return;
}
pausablePlayer.pause();
});
}
public static void initPlayer() {
FileInputStream input = null;
try {
input = new FileInputStream(openFile);
} catch (FileNotFoundException e2) {
e2.printStackTrace();
}
try {
pausablePlayer = new PausablePlayer(input);
} catch (JavaLayerException e1) {
e1.printStackTrace();
}
}
}