1

I am porting a java game to mobile using Codename One, and have been trying to make an audio player with the framework using code from another thread. I'm running into lots of trouble doing so, mainly with using the MediaManager. Here is the code:

package com.example.audio;
import java.io.IOException;
import java.io.InputStream;

import com.codename1.io.FileSystemStorage;
import com.codename1.media.Media;
import com.codename1.media.MediaManager;
import com.codename1.ui.Display;

public class AudioPlayer {
    private Media MEDIA = null;
    public void playAudio(String fileName) {
        try {
            if (MEDIA == null) {
                InputStream is = FileSystemStorage.getInstance().openInputStream(fileName);
                MEDIA = MediaManager.createMedia(is, "audio/mp3", new Runnable() {
                    @Override
                    public void run() {
                        MEDIA = null;
                    }
                });
            }
            if (MEDIA != null && MEDIA.isPlaying() == false) {
                MEDIA.setVolume(100);
                MEDIA.play();
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}

Class where AudioPlayer is instantiated:

public AudioPlayer audioPlayer = new AudioPlayer(); //audio player 

public Game() {
    changeState(sceneNum);
    audioPlayer.playAudio(FileSystemStorage.getInstance().getAppHomePath() + "res/Sounds/fluffingADuck.wav");
...

This is what the stack trace gives me

java.io.IOException
    at com.codename1.impl.javase.JavaSEPort.createMedia(JavaSEPort.java:9535)
    at com.codename1.ui.Display.createMedia(Display.java:3705)
    at com.codename1.media.MediaManager.createMedia(MediaManager.java:306)
    at com.example.audio.AudioPlayer.playAudio(AudioPlayer.java:16)
    at com.example.myapp.Game.<init>(Game.java:32)
    at com.example.myapp.Game.getGame(Game.java:41)
    at com.example.myapp.MyApp.runApp(MyApp.java:14)
    at com.codename1.system.Lifecycle.start(Lifecycle.java:129)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at com.codename1.impl.javase.Executor$3$2.run(Executor.java:340)
    at com.codename1.ui.Display.executeSerialCall(Display.java:1395)
    at com.codename1.ui.Display.processSerialCalls(Display.java:1379)
    at com.codename1.ui.Display.mainEDTLoop(Display.java:1166)
    at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:120)
    at com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176)

Here is what the folder that holds the sounds looks like: My folder set up

I converted one of the sounds to mp3 because I thought maybe wav wasn't recognized by CN1 but that did not fix the issue either. I use pretty much the same method to retrieve images for the game and that works fine. Not sure what to do, if someone could point me in the right direction or give any assistance it would mean a lot. I'm still a bit of a noob at programming. Here is the github repo if anyone would want to take a look as well: https://github.com/stefancohn/DuckWorldMobile

1 Answers1

1

It seems you're confusing FileSystemStorage with resources. Those are separate concepts. Resources like your sounds, get packaged into your application as part of the final bundle (e.g. jar) and are available to you on the device using an API to fetch the resources.

FileSystemStorage accesses the file system available on the device. Here you first need to write or create the file in some way in order for it to be available for you.

There are additional problems:

  • Your resources are in a hierarchy. This isn't supported by Codename One since some packaging systems (iOS) behave somewhat differently. So you can't nest the files and need to put them all in one directory.

  • You named the directory res instead of resources.

  • It needs to be under main next to the java and css directory

To clarify, the file fluffingADuck.wav must be in common/src/main/resources/fluffingADuck.wav for the following code to work.

Now you need to fix the code to use resources which is actually pretty simple:

audioPlayer.playAudio("/fluffingADuck.wav");

Notice the / in the beginning. It's intentional.

Then all you need to do is change the InputStream line to:

InputStream is = CN.getResourceAsStream(fileName);
Shai Almog
  • 51,749
  • 5
  • 35
  • 65
  • Thank you so much for the reply. I understand FileSystemStorage and resources better now. It's just I'm running into this error now: Warning: com.example.audio.AudioPlayer: can't find referenced method 'java.io.InputStream getResourceAsStream(java.lang.String)' in library class java.lang.Class Sorry if the answer is obvious, but how do I get around this? I downloaded the recommended JDK from the manual (OpenJDK 17.0.8) because I thought that may be causing it but it did not fix. – Stefan Cohn Jul 25 '23 at 19:48
  • 1
    Sorry that probably broke with the maven migration. Changed it in the code to `CN.getResourceAsStream(fileName);` which should work. – Shai Almog Jul 26 '23 at 02:57
  • Hey Shai, i can confirm this worked because I changed my code to load all my images by using the instructions you gave me when you responded to my question. Now, however, I am running into an error regarding the createMedia method at com.codename1.impl.javase.JavaSEPort.createMedia(JavaSEPort.java:9535) at com.codename1.ui.Display.createMedia(Display.java:3705) at com.codename1.media.MediaManager.createMedia(MediaManager.java:306) Sorry to bother but would you know how to get past this? Thanks for all the help already. – Stefan Cohn Jul 26 '23 at 20:05
  • That's a [wrapper exception](https://github.com/codenameone/CodenameOne/blob/master/Ports/JavaSE/src/com/codename1/impl/javase/JavaSEPort.java#L9535C1-L9535C42) if you scroll up you will see the actual error that triggered it and ideally it should have a better error message. Ideally open a new question so you can have space to include the full details. – Shai Almog Jul 27 '23 at 04:22