4

I want to create a simple Blackberry app that plays an audio file whenever I charge my phone, and for the application to close when I unplug it.

Pseudocode

  1. Start application when battery cable plugged in,

  2. application plays sound continuously while charging

    could not make it loop without a gap of silence in between, instead play a sound

  3. if user unplugs cable, stop the stream, play a sound, stop the stream

  4. optional: if battery level falls to critical/done charging, play a sound

Looking through the docs I think there isn't a listener to tell you if battery is at 100%.

Edit: Found a way through batteryStatusChange, and thanks Nate for helping me out there

Having null exception errors.

Edit: Used InputStream and no more null exception errors. Added wav files to the res folder. New code below plays a sound at 100 and two different sounds, one for USB connect and another for USB disconnect.

public class HelloBlackBerryScreen extends MainScreen implements SystemListener2 {
    private BasicEditField basicEditField;
    private Player HEV;    
    private String wav;
    private InputStream stream;
    private int volume; //going to set volume from GUI using a drop down list, working on it currently

public HelloBlackBerryScreen() 
{
    super( MainScreen.VERTICAL_SCROLL | MainScreen.VERTICAL_SCROLLBAR );
    setTitle( "HelloBlackBerry" );
    add(new RichTextField("Battery", RichTextField.TEXT_ALIGN_HCENTER));

    Application.getApplication().addSystemListener(this);
    
    wav = "voice_on.wav";
    stream = (InputStream)this.getClass().getResourceAsStream("/" + wav);               
    try {
        HEV = Manager.createPlayer(stream, "audio/wav");
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (MediaException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

public void batteryGood() {
    // TODO Auto-generated method stub
    
}

public void batteryLow() {
    // TODO Auto-generated method stub
    
}

public void batteryStatusChange(int status) 
{
    // TODO Auto-generated method stub
    if ((status & DeviceInfo.BSTAT_LEVEL_CHANGED) != 0)
    {
        if(DeviceInfo.getBatteryLevel() == 100)
        {
            try 
            {
                setWav("power_level_is_100_percent.wav"); 
                HEV.start();
                stream.close();
            } 
            catch (MediaException e) 
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } 
            catch (IOException e) 
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }               

        }               

    }
}   

public void powerOff() {
    // TODO Auto-generated method stub
    
}

public void powerUp() {
    // TODO Auto-generated method stub
    
}

public void backlightStateChange(boolean on) {
    // TODO Auto-generated method stub
    
}

public void cradleMismatch(boolean mismatch) {
    // TODO Auto-generated method stub
    
}

public void fastReset() {
    // TODO Auto-generated method stub
    
}

public void powerOffRequested(int reason) {
    // TODO Auto-generated method stub
    
}

public void usbConnectionStateChange(int state) 
{
    // TODO Auto-generated method stub
    if (state == USB_STATE_CABLE_CONNECTED) 
    {           
        try 
        {
            setWav("suitchargeok1.wav"); 
            HEV.start();
            stream.close();
        } 
        catch (MediaException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        catch (IOException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }       
        
        } 
        else if (state == USB_STATE_CABLE_DISCONNECTED) 
        {
            try 
            {
                stream.close();
                setWav("battery_pickup.wav"); 
                HEV.start();
                stream.close();
            } catch (MediaException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();                    
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
}

public String getWav() {
    return wav;
}

public void setWav(String wav) {
    this.wav = wav;
    stream = (InputStream)this.getClass().getResourceAsStream("/" + this.wav);
    try {
        HEV = Manager.createPlayer(stream, "audio/wav");
        HEV.realize();
        VolumeControl volume = (VolumeControl) HEV.getControl("VolumeControl");
        volume.setLevel(25);
        HEV.prefetch();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (MediaException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

public boolean onClose()
{
    UiApplication.getUiApplication().requestBackground();
    return true;
}

}

Community
  • 1
  • 1
Dog
  • 595
  • 3
  • 11
  • 20
  • do you really want your app to have any graphical user interface at all, or could it purely be a background app that only plays sounds? – Nate Sep 15 '12 at 22:59

1 Answers1

2

I'd need a little more clarification on how you want the app to work (see my comment below your question), but I'm pretty sure you're going to need to implement a SystemListener (actually, a SystemListener2, which is a kind of SystemListener) to listen for USB state changes.

Something like this to detect the connection:

void usbConnectionStateChange(int state) {
   if (state == USB_STATE_CABLE_CONNECTED) {
      // start playing your sound
   } else if (state == USB_STATE_CABLE_DISCONNECTED) {
      // stop playing your sound, and exit, or just stay in the background
   }
}

Here is a link on how to add/register a System Listener on device startup

See this BlackBerry forums link on detecting USB connection

And the API docs on SystemListener2, too

Update: as I believe the poster already figured out (based on the code update in the question), the public void batteryStatusChange(int status) method is probably the more direct callback to use here. Everything else is the same, though, as that's just another callback in SystemListener.

Nate
  • 31,017
  • 13
  • 83
  • 207
  • Hi Nate, a background application would do. What about a code for detecting if phone is charging or not? This thread below shows how to do that, but I'm guessing its more appropiate to use systemListener2 ?http://stackoverflow.com/questions/8214231/blackberry-determine-if-using-external-power – Dog Sep 15 '12 at 23:32
  • Also, in order to implement this, I must start a background app after I restart the phone? Is there a way to start it like the "display clock option when charging" – Dog Sep 15 '12 at 23:37
  • 1
    @user1615805, that link you posted (with answer from Mister Smith) looks fine. However, that is just code to **ask** whether the device is charging. You really need **notification** when charging starts or stops, which is a little different. In general, charging occurs when USB connection is made, right? I guess if the phone is 100% charged, it can be connected without currently charging. If you want, you can implement the `SystemListener2`, and then inside the `usbConnectionStateChanged` callback, you could execute the code from Mr. Smith's answer to be sure that it's charging. – Nate Sep 16 '12 at 00:42
  • @user1615805, also regarding how to start an application in the background automatically, you can see [this other question](http://stackoverflow.com/a/3978232/119114), or [this one, too](http://stackoverflow.com/a/5772279/119114). This makes sure that as soon as the phone starts up, your listener can be registered. Your app stays in the background. Then, whenever USB is connected/disconnected, you get a callback via `usbConnectionStateChange()` and can take the opportunity to start or stop playing your sounds. – Nate Sep 16 '12 at 00:48
  • Could I omit the MySceen class since this is a background app? One class left, public class HelloWorld extends Application implements SystemListener2 {} – Dog Sep 16 '12 at 01:18
  • @user1615805, correct. If you don't planning on *showing* any UI, then you don't actually need to have any `Screen` subclasses. One `Application` subclass should be enough. – Nate Sep 16 '12 at 02:09
  • Ok, I got it to work with a single class, but I tried pluggin it in and out it plays the sound, but only after 3 tries. Afer the 4th plug in, no sound plays. I've edited the original code – Dog Sep 16 '12 at 02:10
  • @user1615805, It sounds like something isn't getting cleaned up. Are you sure you're not seeing exceptions thrown? I'm not sure that you can use `Dialog.alert()` in a non-graphical application. Maybe replace those with `println()` calls, or the `EventLogger`, to log the exceptions. Also, I would probably keep `Player p` as a *member variable* in your class, so that when you call `p.stop()`, you know for sure that you're stopping the same player that started. And, probably don't call `createPlayer()` unless the usb state is **connected**. – Nate Sep 16 '12 at 02:44
  • 1
    @user1615805, you might also need to play with whether or not you should call `createPlayer()` more than once (if USB is connected, then disconnected, then connected again). You might need to `createPlayer()` once, hold the `Player` instance as a member variable, and then just call `start()` and `stop()` on that single instance. Again, you'll have to experiment. – Nate Sep 16 '12 at 02:46
  • ok, will do, i'll post back soon if I can get it to work perfectly, thanks – Dog Sep 16 '12 at 02:54
  • 1
    yay got it to play perfectly now, tried in and out like 20 times and it plays every single time, although when I installed it at first, it gave me a java lang null exception error – Dog Sep 16 '12 at 18:27