Java声音无法在可执行jar上播放

时间:2014-06-07 11:05:40

标签: java audio jar

我制作游戏,在将游戏导出到.jar文件后,我偶然发现了一个问题:我无法播放声音。

我对此进行了大量研究,我开始认为这是JAVA的一些问题。我也意识到我并不是唯一一个有这个问题的人,但没有给那些可以帮助我的人提供答案。

我研究了getClass()和getClassLoader()之间的区别,并尝试了两种情况,但仍然没有。但问题不在于加载资源,而是关于声音没有播放,即使它加载了。

游戏很好玩,加载所有的精灵,但没有任何声音。

在我研究这个过程中,我了解到我可以使用" java -jar file.jar"来执行游戏。在命令,声音开始工作。然而,这对我来说听起来不是一个好选择,因为我打算分发游戏。

这是我做的一个测试,它显示了我正在谈论的内容。 您可以添加任何图像和声音,并自行测试。

package testando;

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class Testando extends JFrame {

    private final LineListener myLineListener;

    public Testando() { 
        super();
        setLayout( new BorderLayout() );

        setBounds( 200, 200, 500, 500 );
        myLineListener = new MyLineListener();
        MultiSound multiSoundPanel = new MultiSound();

        addWindowListener( new WindowAdapter() {
            @Override public void windowClosing( WindowEvent e ) {
                System.exit( 0 );
            }
        });

        add( multiSoundPanel );


    }

    private class MultiSound extends JPanel {

        final BufferedImage desertImage;

        MultiSound(){
            super( null, true );
            final AudioInfo audioInfos = new AudioInfo( "testando/Iron_Click.wav" );

            addMouseListener( new MouseListener() {
                final AudioInfo audioInfo = audioInfos;

                @Override
                public void mousePressed( MouseEvent e ) {

                    Sound sound = new Sound( audioInfo );
                    new Thread(sound).start();

                }

                @Override public void mouseClicked( MouseEvent e ) {}
                @Override public void mouseReleased( MouseEvent e ) {}
                @Override public void mouseEntered( MouseEvent e ) {}
                @Override public void mouseExited( MouseEvent e ) {}
            });

            java.net.URL streamURL = Thread.currentThread().getContextClassLoader().getResource( "testando/Desert.jpg" );

            BufferedImage desertImagebuff = null;
            try {
                desertImagebuff = ImageIO.read( streamURL );
            }
            catch ( IOException ex ) {
                StringBuilder sb = new StringBuilder(ex.toString());
                for (StackTraceElement ste : ex.getStackTrace()) {
                    sb.append("\n\tat ");
                    sb.append(ste);
                }
                String trace = sb.toString();

                JOptionPane.showMessageDialog( null, trace, "ERROR", JOptionPane.INFORMATION_MESSAGE);
                System.exit( -1 );
            }

            desertImage = desertImagebuff;
        }

        @Override
        protected void paintComponent( Graphics g ) {
            super.paintComponent( g ); //To change body of generated methods, choose Tools | Templates.

            Graphics2D g2 = (Graphics2D)g.create();

            Rectangle rect = getVisibleRect();
            double desSx = ((rect.width*1.0d)/desertImage.getWidth());
            double desSy = ((rect.height*1.0d)/desertImage.getHeight());

            //To keep the image scalled to the panel;
            AffineTransform scale = AffineTransform.getScaleInstance( desSx, desSy );
            AffineTransformOp transformer = new AffineTransformOp( scale, null );
            g2.drawImage( desertImage, transformer , rect.x, rect.y );
            g2.dispose();
        }

    }

    private class AudioInfo {

        final AudioFormat audioFormat;
        final int size;
        final byte[] audio;
        final DataLine.Info info;

        AudioInfo( String path ){

            java.net.URL streamURL = Thread.currentThread().getContextClassLoader().getResource( path );


            AudioFormat toAudioFormat = null;
            int toSize = -1;
            byte[] toByte = null;
            DataLine.Info toInfo = null;

            try {

                InputStream stream = new BufferedInputStream( streamURL.openStream() );

                AudioInputStream audioInputStream   = AudioSystem.getAudioInputStream( stream );
                toAudioFormat                       = audioInputStream.getFormat();
                toSize                              = (int) ( toAudioFormat.getFrameSize() * audioInputStream.getFrameLength() );
                toByte                              = new byte[toSize];
                toInfo                              = new DataLine.Info(Clip.class, toAudioFormat, toSize);

                audioInputStream.read(toByte, 0, toSize);

            }
            catch ( UnsupportedAudioFileException | IOException ex ) {
                StringBuilder sb = new StringBuilder(ex.toString());
                for (StackTraceElement ste : ex.getStackTrace()) {
                    sb.append("\n\tat ");
                    sb.append(ste);
                }
                String trace = sb.toString();

                JOptionPane.showMessageDialog( null, trace, "ERROR", JOptionPane.INFORMATION_MESSAGE);
                System.exit( -1 );
            }

            audioFormat = toAudioFormat;
            size = toSize;
            audio = toByte;
            info = toInfo;
        }
    }

    private class MyLineListener implements LineListener {

        @Override
        public void update( LineEvent event ) {

            if ( event.getType( ) == LineEvent.Type.STOP )
                event.getLine().close();

        }

    }

    private class Sound implements Runnable {

        private final Clip sound;

        Sound( AudioInfo audioInfo ){

            AudioFormat audioFormat = audioInfo.audioFormat;
            int size = audioInfo.size;
            byte[] audio = audioInfo.audio;
            DataLine.Info info = audioInfo.info;

            Clip clip = null;

            try {
                clip = (Clip) AudioSystem.getLine( info );
                clip.open( audioFormat, audio, 0, size );
                clip.addLineListener( myLineListener );
            }
            catch ( LineUnavailableException ex ) {
                clip = null;
            }

            sound = clip;
        }

        @Override
        public void run() {
            sound.start();
        }

    }

    public static void main( String[] args ) {

        Testando testando = new Testando();
        testando.setVisible( true );
    }

}

如果你想更好地分析它,我还用它编译了带有源代码的可执行版本。 https://www.dropbox.com/s/328dr47i39vbart/testando_dist.zip

我不知道它是否有用,但我使用的是NetBeans 7.4。

有人可以帮帮我吗?

提前谢谢你, saclyr。

1 个答案:

答案 0 :(得分:0)

我刚刚发现为什么没有声音。

我试了很多次,包括更新JDK和JRE,但仍然没有。我尝试安装32位的JRE,但仍然没有,但在取消了64位版本后,我开始得到声音。

游戏现在很好,但出于某种原因,它无法用于64位。

问题在于64位版本。