Audio not playing within thread Android - java

So i've got an audio file that i'd like to play within a thread, this is where i've left the comment // Tried playing audio here . But the even with the logic to make sure that it only plays once no audio is being played. Instead it seems like it's forcing the application to skip frames instead causing the game to have a few glitches because of the inconsistent frame rate.
Here's the code which i've been using.
while (isRunning) {
// Go back to the if statement and check if the surface still isn't valid
if (!mySurfaceHolder.getSurface().isValid())
continue;
// Lock the canvas for editing, make changes and unlock with new changes
final Canvas canvas = mySurfaceHolder.lockCanvas();
canvas.drawRect(0,0,canvas.getWidth(), canvas.getHeight(), pWhite);
// Create the block to check the answer
answerObject = new AnswerObject(canvas);
animalObject.move(canvas, tilt);
if(answerObject.onCollision(animalObject) != null){
// Inside of box else is outside of box
if (answerObject.onCollision(animalObject)) {
// If the animal is part of that enviroment
if (verifyEnviroment(enviromentObject.getAnimals())){
isCorrect = true;
} else {
isCorrect = false;
}
} else {
// If the animal is part of that enviroment
if (!verifyEnviroment(enviromentObject.getAnimals())){
// Tried playing audio here
isCorrect = true;
} else {
// Tried playing audio here
isCorrect = false;
}
}
gameActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
if (isCorrect){
scoreObject.setScore(10);
} else {
healthObject.setHealth(10);
healthObject.setHealthImgs(healthObject.getHealth());
if (healthObject.getHealth() <= 0){
isRunning = false;
}
}
resetGameObjects();
}
});
}
mySurfaceHolder.unlockCanvasAndPost(canvas);
}

Related

having pause/resume button on jpanel form java

I am trying to have one Button for pause and resume game background music on Jpanel form, what I have done below is just resets/repeats the sound from the beginning rather than pause and play. and I have look at few other examples here and tried to implement, same thing happened. or just paused it. any idea what to add to it to make it function? thanks
Boolean isPaused = false;
private void jButton6ActionPerformed(java.awt.event.ActionEvent evt) {
if (isPaused = false ) {
Game.gameMusic.pause();
isPaused = true;
}
else {
Game.gameMusic.resume();
isPaused = true;
}
}
if (isPaused = false ) { is an assignment, not an evaluation, you should be using ==
that will become
Boolean isPaused = false;
private void jButton6ActionPerformed(java.awt.event.ActionEvent evt) {
if (!isPaused ) {
Game.gameMusic.pause();
jButton6.setText("resume");
}
else {
Game.gameMusic.resume();
jButton6.setText("pause");
}
isPaused = !isPaused;
}

JAVA - Boolean correction - Still going on when pressing Play

So im pretty close to my end and I can't figure out why its doing like this. Maybe because im stupid right now after coding a while. however. So I have two files that should be allowed to my program. The first one is a MP3 and the Other one is Wav. I got them to work. By that I mean if I choose Wav file, the sound comes, if I choose the mp3 it works so there is no problem with that but the problem is right now is when pressing Open (-> browersing a file) and then press play, the sound should come, and yes it does. so when I open a another file for exemple a new song. then press play. the song is playing with the first song which makes it two tracks at the same time and I want it to make -> when one song is playing then play. and if I choose new song and press play, then the first song should go away. I think im pretty close but yeah. However I have done this
static boolean status = true;
btnPlay.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == btnPlay) {
if(!status) {
clip.start();
lblPlaying.setText("Enjoy the music!");
} else if(status == true) {
mp3_player.play();
lblPlaying.setText("Enjoy the music!");
}
}
}
});
public void Choose() throws IOException {
String userDir = System.getProperty("user.home");
JFileChooser fileChooser = new JFileChooser(userDir +"/Desktop");
int returnValue = fileChooser.showOpenDialog(null);
if (returnValue == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
System.out.println(selectedFile.getName());
String ext = selectedFile.getPath();
if(ext.endsWith(".mp3")) { // For mp3
status = true;
mp3_player = new MP3Player(selectedFile);
lblPlayURL.setText(selectedFile.getName());
}
else if(ext.endsWith(".wav")) {
status = false; //For .Wav
try {
AudioInputStream stream;
AudioFormat format;
DataLine.Info info;
clip = clip;
stream = AudioSystem.getAudioInputStream(selectedFile);
format = stream.getFormat();
info = new DataLine.Info(Clip.class, format);
clip = (Clip) AudioSystem.getLine(info);
clip.open(stream);
lblPlayURL.setText(selectedFile.getName());
}
catch(Exception e) {
//whatevers
}
}
}
}
}
To make the story shorter so what I have done is I have a variable that is set boolean to false. so whenever False is running it takes the Wav. when True its mp3. but as I said. the problem is sitting when.
Choose a song
Press play for the song
Choose new song
Press play for the new song (and here is where the 1st one song still going on which I don't want to)
Have I done something wrong with booleans?
EDIT: Forgot to add the open button:
btnOpen.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(e.getSource() == btnOpen) {
try {
Choose();
}
catch (IOException e1) {
e1.printStackTrace();
}
}
}
});
}
edit : Stop method
,
btnStop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(e.getSource() == btnStop) {
if(!status) {
clip.stop();
lblPlaying.setText("Nothing plays right now!");
} else if(status == true) {
mp3_player.stop();
lblPlaying.setText("Nothing plays right now!");
}
}
}
});
You need to have another flag which tells you if it's playing or not. Then before you start the song, check the flag, then STOP any music if it's true, then start the new one.
You essentially have a design flaw. The system is capable of playing multiple songs at once, it didn't know you wanted to stop one of them.

Android app crashes on reopen

I made a 2D android game for android and the game works perfectly fine but upon reopening it after closing, the game crashes once (Unfortunately, game has stopped working appears) before working again. This only occurs on newer devices, as I tested it on an API level 8 smaller screen and this does not happen.
I suspect this has something to do with how I use the Bitmap resources for the game. I do not release the resources anywhere in the code, is this something that I should be doing or does the garbage collector automatically handle it?
The game reopens fine on all emulator devices except for the occasional
Exception locking surface
java.lang.IllegalStateException: Surface was already locked
that is thrown on reopen. I do not know the fix for this but it happens very rarely.
Here is the code in the MainThread.java class
while (running) {
startTime = System.nanoTime();
canvas = null;
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
// update game state
this.gamePanel.update();
// draws the canvas on the panel
this.gamePanel.draw(canvas);
}
} catch(Exception e){e.printStackTrace();}finally {
// in case of an exception the surface is not left in
// an inconsistent state
if (canvas != null) {
try {
surfaceHolder.unlockCanvasAndPost(canvas);
}
catch(Exception e){e.printStackTrace();}
}
}
method that starts the thread:
#Override
public void surfaceCreated(SurfaceHolder holder) {
player = new Player(BitmapFactory.decodeResource(getResources(), R.drawable.helicopter),65,25,3);
bg = new Background(BitmapFactory.decodeResource(getResources(), R.drawable.grassbg1));
smoke = new ArrayList<Smokepuff>();
missiles = new ArrayList<Missile>();
botborder = new ArrayList<BotBorder>();
topborder = new ArrayList<TopBorder>();
explosions = new ArrayList<Explosion>();
smokeStartTime = System.nanoTime();
missileStartTime = System.nanoTime();
thread.setRunning(true);
thread.start();
}
and method that shuts the thread down:
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
boolean retry = true;
while (retry) {
try {
thread.setRunning(false);
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
retry = false;
}
}
Any help would be greatly appreciated!

When my button is pressed, I get the error ViewRootImpl$CalledFromWrongThreadException

I tried to make a simple game on Android. The player is a blue ball and is supposed to avoid the moving objects. Once it hits it, the game is over. The game also ends if the player catches all the food objects. I got the collision detection working but when I tried to add a button afterwards to give the user the option to restart, I got the ViewRootImpl$CalledFromWrongThreadException error. The button is already declared in the onCreate method and the visibility is set to invisible, but when I change it to visible, I get the error. I have no idea how to fix it. I tried looking online and it wasn't much help. I understood that the error occcurs when you modify the UI in a non-UI thread, but how would you fix that? Any help would be appreciated. (:
Here is the run method:
#Override
public void run() {
// TODO Auto-generated method stub
while(locker==true){
//checks if the lockCanvas() method will be success,and if not, will check this statement again
if(!holder.getSurface().isValid()){
continue;
}
/** Start editing pixels in this surface.*/
Canvas canvas = holder.lockCanvas();
draw(canvas);
if (up==true){
y=y-3;
}
else if(down==true){
y=y+3;
}
else if (left==true){
x=x-3;
}
else if (right==true){
x=x+3;
}
int counter=0;
for(int i=0;i<listOfFs.length;i++)
{
foodCaught [i] = listOfFs [i].check (x,y,radiusBlack);
if (foodCaught [i] == true)
{
alive [i] = listOfFs [i].kill ();
}
else{
counter++;
}
}
if (counter==0){
win=true;
playAgain.setVisibility(View.VISIBLE);
}
for(int i=0;i<listOfCs.length;i++)
{
if (i<3){
listOfCs[i].changeX(listOfCs[i].getX()+increment[i]);
}
else{
listOfCs[i].changeY(listOfCs[i].getY()+increment[i]);
}
}
for(int i=0;i<listOfCs.length;i++){
if (y+radiusBlack>listOfCs[i].getY()&& y-radiusBlack<listOfCs[i].getY()+listOfCs[i].getSize()&& x-radiusBlack<listOfCs[i].getX()+listOfCs[i].getSize()&& x+radiusBlack>listOfCs[i].getX())
{
chaserCaught = true;
playAgain.setVisibility(View.VISIBLE);
}
}
// End of painting to canvas. system will paint with this canvas,to the surface.
holder.unlockCanvasAndPost(canvas);
}
}
You can't touch views outside UI thread (and your SurfaceView drawning happens on non-UI thread).
Just instead of doing this:
playAgain.setVisibility(View.VISIBLE);
do this:
playAgain.post(new Runnable() {
#Override
public void run() {
playAgain.setVisibility(View.VISIBLE);
}
});

AudioInputStream() does not stop

I have inserted a background audio into my program using AudioInputStream.
When I press the On, the background audio will play, and Off will stop playing the background audio.
Here is the part of my code for the audio playing part :
public void playSound(int i)
{
try
{
. //Others buttons sound
. //Others buttons sound
if(i == 3 || i == 4)
{
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("Background.wav"));
Clip clip3 = AudioSystem.getClip( );
clip3.open(audioInputStream);
if(i == 3)
{
clip3.loop(Clip.LOOP_CONTINUOUSLY);
clip3.start();
settingSubMenuItem3.setEnabled(false);
settingSubMenuItem4.setEnabled(true);
}
if(i == 4)
{
clip3.stop();
settingSubMenuItem3.setEnabled(true);
settingSubMenuItem4.setEnabled(false);
}
}
catch(Exception e)
{
System.out.println("Error with playing sound.");
e.printStackTrace();
}
}
And here is the ButtonListener part :
private class MenuItemListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == settingSubMenuItem3)
{
playSound(3);
}
if(e.getSource() == settingSubMenuItem4)
{
playSound(4);
}
}
}
My code can play the audio when I press On button, but when I press Off button, it does not work.
There is no error during compile and run.
What is the error of my code?
Your AudioInputStream variable, audioInputStream, and Clip variable, clip3, are local to the method. The object you are trying to stop is not the same as the one that's playing currently.
Make them class fields, check that they're not null before calling methods on them, don't create a new object if you're trying to stop the currently playing object, and you should be OK.
Something like:
public void playSound(int i) {
try {
// ...
if (i == 3 || i == 4) {
if (i == 3) {
audioInputStream = AudioSystem
.getAudioInputStream(new File("Background.wav"));
clip3 = AudioSystem.getClip();
clip3.open(audioInputStream);
clip3.loop(Clip.LOOP_CONTINUOUSLY);
clip3.start();
settingSubMenuItem3.setEnabled(false);
settingSubMenuItem4.setEnabled(true);
}
if (i == 4) {
if (clip3 != null && clip3.isActive()) {
clip3.stop();
settingSubMenuItem3.setEnabled(true);
settingSubMenuItem4.setEnabled(false);
}
}
}
} catch (Exception e) {
System.out.println("Error with playing sound.");
e.printStackTrace();
}
}
Again, making audioInputStream and clip3 non-static class fields.
As an aside, I would avoid using "magic" numbers such as 3 and 4 as you are doing as this may become a devil to debug 6 months from now. Instead give each JButton its own Action. It deserves no less.

Categories