在写Java程序的时候常常需要播放背景音乐,其实实现只需两步即可。
1.首先需要下载一个jar包
最近有许多网友反应说原来的下载地址不能用了,这里提供一个最新下载地址:jlayer-1.0.1.jar,下载完成直接导入jar即可,亲测可用。
网址:http://www.javazoom.net/javalayer/javalayer.html
下载完成,解压后找到如图所示的包导入到项目中去。
2.然后, 只需将下面的几行代码粘入程序中即可,即粘即用,如果出现错误多半是jar包没有正确导入。
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.*;
class Play0 extends Thread{
Player player;
String music;
public Play0(String file) {
this.music = file;
}
public void run() {
try {
play();
} catch (FileNotFoundException | JavaLayerException e) {
e.printStackTrace();
}
}
public void play() throws FileNotFoundException, JavaLayerException {
BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(music));
player = new Player(buffer);
player.play();
}
}
上面的代码实则是将播放程序放入线程中去,然后再在需要播放音乐的地方写入如下代码,开启线程。
new Play0("C:\\Users\\ds_surk\\Desktop\\My soul.mp3").start();
如需结束播放则需要这样写。
Play0 play0 = new Play0("C:\\Users\\ds_surk\\Desktop\\My soul.mp3");
play0.start(); //开启
play0.stop(); //结束
如果看不懂,直接粘即可,只需将 "C:\\Users\\ds_surk\\Desktop\\My soul.mp3" 替换成自己想要播放的音乐即可,格式为MP3。
后记:
由于原有代码过期,现根据已有的问题,特作统一回复。
1.Java多线程的stop方法过期,如何停止播放?
直接放代码吧,简单粗暴。
public class Music {
public static void main(String[] args) {
String file = "C:\\Users\\surk\\Desktop\\1.mp3";
Play play = new Play(file);
Player player = play.getPlayer();
// 开启
play.start();
try {
Thread.sleep(2000);
// 输出当前播放的位置(时间)
System.out.println(player.getPosition());
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 输出是否播放完毕
System.out.println(player.isComplete());
//结束
play.stop();
}
}
class Play implements Runnable {
private Player player = null;
private Thread thread = null;
public Play(String file) {
try {
player = new Player(new FileInputStream(file));
} catch (JavaLayerException | FileNotFoundException e) {
e.printStackTrace();
}
}
public void run() {
try {
player.play();
} catch (JavaLayerException ex) {
System.err.println("Problem playing audio: " + ex);
}
}
public void start() {
thread = new Thread(this, "Player thread");
thread.start();
}
public void stop() {
player.close();
thread = null;
}
public Player getPlayer() {
return player;
}
}
2.如何暂停?
首先现有的Player类是没有提供暂停方法的,所以想要暂停播放,需要一些技巧。
Player只提供了播放和停止方法,然后还有一个AdvancedPlayer类,它提供的方法会多些,
于是根据AdvancedPlayer类有如下代码,来实现暂停播放。
public class Music {
public static void main(String[] args) {
String file = "C:\\Users\\surk\\Desktop\\1.mp3";
Play play = new Play(file);
// 开启
play.start();
try {
Thread.sleep(5000);
// 暂停
play.stop();
Thread.sleep(2000);
// 重新播放
play.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
//结束
play.stop();
System.out.println("stop!");
}
}
class Play implements Runnable {
private final String file;
private AdvancedPlayer player = null;
private Thread thread = null;
public int pauseFrame = 0;
public Play(String file) {
this.file = file;
}
public void run() {
// 每次开始需要重新创建AdvancedPlayer,否则会报错
createPlayer();
play();
}
public void start() {
thread = new Thread(this, "Player thread");
thread.start();
}
public void stop() {
player.stop();
thread = null;
}
protected void play() {
try {
player.play(pauseFrame, Integer.MAX_VALUE);
} catch (JavaLayerException ex) {
System.err.println("Problem playing audio: " + ex);
}
}
protected void createPlayer() {
try {
player = new AdvancedPlayer(new FileInputStream(file));
// 这里设置一个监听器,来监听停止事件,记录停止帧
player.setPlayBackListener(new PlaybackListener() {
@Override
public void playbackFinished(PlaybackEvent event) {
pauseFrame = event.getFrame();
}
});
} catch (JavaLayerException | IOException e) {
e.printStackTrace();
}
}
}
大致思路是通过监听停止事件来记录停止时的帧,然后从停止帧继续播放。这样重新播放时就可以从上次暂停的地方继续。但是,这里有坑!!!我发现,无论是event.getFrame()还是Player类的player.getPosition()方法均不能正确的获取帧!
所以你会发现,当重新播放时,它播放的点并不是上次暂停的地方!!
不过,总归思路是行的通的!只要正确的找到帧,就可以成功实现暂停,在播放的需求。
来看AdvancedPlayer类源码,其中有一个decodeFrame()方法用来解析帧,不难发现,它每次只解析一帧,所以,可以继承AdvancedPlayer类,重写该方法,就可以达到记录帧的目的了!
直接放代码。
public class Music {
public static void main(String[] args) {
String file = "C:\\Users\\surk\\Desktop\\1.mp3";
Play play = new Play(file);
// 开启
play.start();
try {
Thread.sleep(14000);
// 暂停
play.stop();
Thread.sleep(1000);
// 重新播放
play.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
//结束
play.stop();
System.out.println("stop!");
}
}
class Play implements Runnable {
private final String file;
private MyPlayer player = null;
private Thread thread = null;
public int pauseFrame = 0;
public Play(String file) {
this.file = file;
}
public void run() {
// 每次开始需要重新创建AdvancedPlayer,否则会报错
createPlayer();
play();
}
public void start() {
thread = new Thread(this, "Player thread");
thread.start();
}
public void stop() {
// 在停止的时候,记录停止帧
pauseFrame = player.getFrame();
player.close();
thread = null;
}
protected void play() {
try {
player.play(pauseFrame, Integer.MAX_VALUE);
} catch (JavaLayerException ex) {
System.err.println("Problem playing audio: " + ex);
}
}
protected void createPlayer() {
try {
player = new MyPlayer(new FileInputStream(file));
} catch (FileNotFoundException | JavaLayerException e) {
e.printStackTrace();
}
}
}
class MyPlayer extends AdvancedPlayer {
/**
* 当前帧
*/
@Getter
private int frame = 0;
public MyPlayer(InputStream stream) throws JavaLayerException {
super(stream);
}
/**
* 重写decodeFrame方法,每次解析,记录帧+1
*/
protected boolean decodeFrame() throws JavaLayerException {
frame++;
return super.decodeFrame();
}
}
这里选择在停止时获取帧,没有使用监听器来获取帧,因为它记录的帧是不对的!
在测试时,发现重新播放时可能会丢失一两帧,不过影响不大,可以在停止时少记录两帧(pauseFrame = player.getFrame()-2;)就可以了。
3.如何循环播放?
同样的,无论是AdvancedPlayer类还是Player类,都没有提供循环播放的方法,所以,这个也需要自己去实现。
这个实现比较简单,直接放代码。
public class Music {
public static void main(String[] args) {
String file = "C:\\Users\\surk\\Desktop\\2.mp3";
Play play = new Play(file);
// 开启
play.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("stop!");
}
}
class Play implements Runnable {
private final String file;
private AdvancedPlayer player = null;
private Thread thread = null;
public Play(String file) {
this.file = file;
}
public void run() {
// 每次开始需要重新创建AdvancedPlayer,否则会报错
createPlayer();
play();
}
public void start() {
thread = new Thread(this, "Player thread");
thread.start();
}
public void stop() {
player.stop();
thread = null;
}
protected void play() {
try {
player.play();
} catch (JavaLayerException ex) {
System.err.println("Problem playing audio: " + ex);
}
}
protected void createPlayer() {
try {
player = new AdvancedPlayer(new FileInputStream(file));
// 这里设置一个监听器,来监听停止事件
player.setPlayBackListener(new PlaybackListener() {
@Override
public void playbackFinished(PlaybackEvent event) {
// 当播放完毕后,会触发该事件,再次调用start()即可!
start();
}
});
} catch (JavaLayerException | IOException e) {
e.printStackTrace();
}
}
}
可以通过监听停止事件,重新调用start()。就可以循环播放啦!
4.如何暂停播放+循环播放?
这个问题嘛,结合已有代码,自己实现吧!
提示一下。
1.你需要注意暂停帧(pauseFrame)的重置。
2.AdvancedPlayer类有两个停止方法,close()和stop(),其中stop会触发停止事件,close则不会触发停止事件。这样就可以通过close方法来实现暂停,通过stop方法来实现停止播放。
总体来说,jLayer这个jar包,年代过于久远,功能很有限,只能说凑合能用,它的源码读起来不是很困难,读读源码大概就知道怎么回事了,所以想要实现更多的功能,一是自己写:),二是寻找其他jar包。