Would you like to tell us how we are doing?

You bet No thanks

Sorry about the red box, but we really need you to update your browser. Read this excellent article if you're wondering why we are no longer supporting this browser version. Go to Browse Happy for browser suggestions and how to update.

FM Radio

Some BlackBerry devices are equipped with FM radio receivers. You can create an application that receives FM radio broadcast signals and metadata transmitted using the Radio Data System (RDS) protocol. The user must have a wired headset connected to the device to receive any radio signal.

To start playing the FM audio, use the JSR-135 APIs ( javax.microedition.media.Manager , javax.microedition.media.Player ) to connect to the FM radio receiver and retrieve the audio stream. You can use the JSR-234 APIs ( javax.microedition.amms.control.tuner.TunerControl , javax.microedition.amms.control.tuner.RDSControl ) to tune the radio and retrieve RDS information. The BlackBerry Java SDK provides a functional superset of the TunerControl interface in the net.rim.device.api.amms.control.fmradio.FmTunerControl interface.

You can specify the FM radio receiver when you retrieve your Player object by using "capture://radio" as the locator string parameter in the Manager.createPlayer() method.
Player myPlayer = Manager.createPlayer("capture://radio");
After you retrieve your Player object, you must put your Player in the REALIZED state before you can retrieve the tuner control or RDS data.
myPlayer.realize( );
_fmTuner = ( FmTunerControl ) myPlayer.getControl( "TunerControl" );
_rds = ( RDSControl ) myPlayer.getControl( "RDSControl" );
Before you begin playing the FM audio stream, ensure that your Player object is in the PREFETCHED state.
myPlayer.prefetch( );

if(myPlayer.getState() == Player.PREFETCHED)
{
    try
    {
        myPlayer.start( );
    }catch( Exception e)
    {
        // process error
    }
}

Detecting FM radio capability

You can test whether a BlackBerry device has an FM radio receiver by retrieving the supports.mediacapabilities and tuner.modulations system properties.

The following code snippet demonstrates how to detect whether a device has an FM radio receiver:

String props = System.getProperty( "supports.mediacapabilities" );

if ( props.indexOf("tuner") >= 0 )
{
    if ( System.getProperty( "tuner.modulations" ).indexOf( "fm" ) >= 0 )
    {
        // This device can receive FM radio signal!
        return true;
    }
}
// This device cannot receive FM radio signal.
return false;

Code sample: Tuning the radio to a specific frequency

import net.rim.device.api.amms.control.fmradio.FmTunerControl;
import net.rim.device.api.command.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.UiApplication;

import javax.microedition.amms.control.tuner.RDSControl;
import javax.microedition.amms.control.tuner.TunerControl;
import javax.microedition.media.Manager;
import javax.microedition.media.Player;

//Declare your application class and start your application.  
class FMRadioApp extends UiApplication 
{
    public static void main(String args[])
    {
        FMRadioApp theApp = new FMRadioApp();
        theApp.enterEventDispatcher();
    }

//In your application's constructor, add a screen to the display stack 
//to provide a user interface to control the radio.    
    FMRadioApp() 
    {    
        pushScreen(new FMRadioScreen());
    }

//Declare the FMRadioScreen class. Create instance variables to 
//keep a reference to your UI controls and FM radio objects.      
    class FMRadioScreen extends MainScreen
    {
        // UI objects
        LabelField _lbl;
        BasicEditField _edtTuneToFreq;
        
        //FM radio objects
        FmTunerControl _fmTuner;
        RDSControl _rds;

//In the screen object's constructor, create a variable for a 
//button to change the radio frequency. Instantiate your UI 
//objects and set the content of your frequency label.          
        public FMRadioScreen()
        {
            ButtonField btnTune;
            
            _edtTuneToFreq = new BasicEditField(
                  BasicEditField.FILTER_REAL_NUMERIC);
            btnTune = new ButtonField("Tune to this station");
            _lbl = new LabelField("Radio information unavailable.");
            
            _edtTuneToFreq.setText("88.1");

//Specify the code that should run when a user pushes your button. In 
//the command handler for the button, invoke the setFreq() method.            
            btnTune.setCommand( new Command( new CommandHandler()
            {
                public void execute(ReadOnlyCommandMetadata data, Object context)
                {
                    setFreq(_edtTuneToFreq.getText());
                }
            }));

//Create a vertical field manager to add your UI objects to the 
//screen, one below the other. Add the manager to the screen.              
            VerticalFieldManager mgr = new VerticalFieldManager();
            mgr.add(_lbl);
            mgr.add(_edtTuneToFreq);
            mgr.add(btnTune);
            add(mgr);

//Initialize your FM radio player.
            initPlayer();

//Tune the radio to a station.  
            setFreq(_edtTuneToFreq.getText());
        }

//Create your initPlayer() method. Create your Player object 
//and retrieve access to the FM radio on the BlackBerry device.        
        public void initPlayer()
        {
            Player myPlayer = null;
            
            try
            {
                myPlayer = Manager.createPlayer( "capture://radio" );

//Process any errors that occur.  
            } catch ( Exception e ) 
            {
                _lbl.setText(e.getMessage( ));
            }

//If you create the Player successfully, put it in the REALIZED state.            
            if(myPlayer != null)
            {        
                try
                {
                    myPlayer.realize( );

//Retrieve your FmTunerControl and RDSControl objects.
                    _fmTuner = ( FmTunerControl ) 
                                   myPlayer.getControl( "TunerControl" );
                    _rds = ( RDSControl ) myPlayer.getControl( "RDSControl" );

//Put your Player object in the PREFETCHED state.  
                    myPlayer.prefetch( );

//Process any errors that occur.  
                } catch ( Exception e ) 
                {
                    _lbl.setText(e.getMessage( ));
                }
            }

//If your Player successfully entered the PREFETCHED state, 
//start the FM audio stream. Otherwise, process the error that occurs.
            if(myPlayer.getState() == Player.PREFETCHED)
            {
                try
                {
                    myPlayer.start( );
                }catch( Exception e)
                {
                    _lbl.setText(e.getMessage( ));
                }
            }
        }

//Create the setFreq() method.          
        private void setFreq(String freq)
        {
            try
            {
                //Convert the String to an int in 100Hz.

//Convert the freq parameter from a String to an int value.
                int frequency = stringToFrequency(freq);
                //Send the frequency to the API for tuning.

//Tune the FM radio receiver to the requested frequency.  
                _fmTuner.setFrequency( frequency, TunerControl.MODULATION_FM );

//If RDS information is available, display it on the screen.
                _lbl.setText(getRadioData());

//If an error occurs, suggest a new frequency.
            }catch ( NumberFormatException n )
            {
                //The frequency is given in 100Hz. It may not be
                // valid in all locales.
                _edtTuneToFreq.setText( frequencyToString( 990000 ) );
            }                
        }
 
//Create the getRadioData() method. If the RDS object you created is valid, return 
//the station information. Otherwise indicate that RDS information is unavailable.         
        public String getRadioData( )
        {
            if ( _rds != null )
            {
                return _rds.getPS();
            }
            return "Radio information unavailable.";
        }

//Create the frequencyToString() method.          
        private String frequencyToString( int frequency )
        {
            // The frequency should have a maximum of 5 digits in MHz.
            // (except in Italy and Thailand where 50 kHz stepping is used)
            StringBuffer bf = new StringBuffer( 5 );
            // These are the MHz.
            bf.append( frequency / 10000 );
            bf.append( "." );
            // This is the digit after the comma.
            bf.append( ( frequency % 10000 ) / 1000 );
            return bf.toString( );
        }

//Create the stringToFrequency() method.  
        private int stringToFrequency( String fr ) 
        {
            //These are the MHz.
            int f = Integer.parseInt( fr.substring( 0, fr.indexOf( '.' ) ) ) * 10000;
            //Adding the rest after the comma.
            f += Integer.parseInt( fr.substring( fr.indexOf( '.' ) + 1 ) ) * 1000;
            return f;
        }
    }
} 

Seeking for a radio signal

You can search the FM radio spectrum for signals above a certain minimum signal strength. To search for a signal, invoke FmTunerControl.seek() and specify the starting frequency, the seek direction, and the minimum signal strength to search for. The seek() method returns 0 if no signal is found above the specified minimum signal strength.
int frequencyFound = myTuner.seek(startFreq, true, -90);

If a signal is found, the FmTunerControl object tunes the radio to the new frequency and returns it to your application.

Code sample: Seeking for a radio signal

import net.rim.device.api.amms.control.fmradio.FmTunerControl;
import net.rim.device.api.command.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.UiApplication;

import javax.microedition.amms.control.tuner.RDSControl;
import javax.microedition.amms.control.tuner.TunerControl;
import javax.microedition.media.Manager;
import javax.microedition.media.Player;

//Declare your application class and start your application.
class SeekApp extends UiApplication
{
    
    public static void main(String args[])
    {
        SeekApp theApp = new SeekApp();
        theApp.enterEventDispatcher();
    }
 
//In your application's constructor, add a screen to the 
//display stack to provide a user interface to control the radio.   
    SeekApp() 
    {
        pushScreen(new SeekScreen());
    }

//Declare the FMRadioScreen class. Create variables as a convenience 
//to remeber which direction the seek method searches for a signal.      
    class SeekScreen extends MainScreen
    {
        boolean UP = true;
        boolean DOWN = false;

//Create instance variables to keep a reference to your UI 
//controls and FM radio objects.          
        //UI objects.
        LabelField _lblRDS, _lblFreq, _lblRSSI;

        //FM radio objects.
        FmTunerControl _fmTuner;
        RDSControl _rds;
        int _rssi = -90;

//In the screen object's constructor, create variables for buttons to seek 
//up or down through the spectrum, and increase or decrease 
//the radio signal strength indication (RSSI).  
        public SeekScreen()
        {
            ButtonField btnSeekUp, btnSeekDown, btnRSSIUp, btnRSSIDown;

//Instantiate your UI objects.             
            _lblFreq = new LabelField();
            _lblRSSI = new LabelField();
            _lblRDS = new LabelField();
            
            btnSeekUp = new ButtonField("Seek up");
            btnSeekDown = new ButtonField("Seek down");
            btnRSSIUp = new ButtonField("Increase RSSI");
            btnRSSIDown = new ButtonField("Decrease RSSI");

//Specify the code that should execute when a user pushes the btnSeekUp button. 
//In the command handler for the button, invoke the seek() method. Specify 
//the diection to seek, and the current frequency.            
            btnSeekUp.setCommand(new Command(new CommandHandler()
            {
                public void execute(ReadOnlyCommandMetadata data, Object context)
                {
                    seek(UP, stringToFrequency(_lblFreq.getText()));
                }
            }));
 
//Specify the code that should execute when a user pushes the btnSeekDown 
//button. In the command handler for the button, invoke the seek() method. Specify 
//the diection to seek, and the current frequency.           
            btnSeekDown.setCommand(new Command(new CommandHandler()
            {
                public void execute(ReadOnlyCommandMetadata data, Object context)
                {
                    seek(DOWN, stringToFrequency(_lblFreq.getText()));
                }
            }));
  
//Specify the code that should execute when a user pushes the btnRSSIUp button. 
//In the command handler for the button, increment the _rssi variable and 
//update the RSSI label on the screen.          
            btnRSSIUp.setCommand(new Command(new CommandHandler()
            {
                public void execute(ReadOnlyCommandMetadata data, Object context)
                {
                    _lblRSSI.setText(Integer.toString(_rssi++));
                }
            }));
   
//Specify the code that should execute when a user pushes the btnRSSIDown button. 
//In the command handler for the button, decrement the _rssi variable and update 
//the RSSI label on the screen.           
            btnRSSIDown.setCommand(new Command(new CommandHandler()
            {
                public void execute(ReadOnlyCommandMetadata data, Object context)
                {
                    _lblRSSI.setText(Integer.toString(_rssi--));
                }
            }));

//Create a vertical field manager to add your UI objects to the screen, 
//one below the other. Add your RDS information and current frequency labels.  
            VerticalFieldManager mgr = new VerticalFieldManager();
            mgr.add(_lblRDS);
            
            mgr.add(_lblFreq);

//Create a horizontal field manger to add the buttons that control the 
//seek direction, one beside the other. 
            HorizontalFieldManager h1 = new HorizontalFieldManager();

//Add the seek buttons to the horizontal field manager. 
            h1.add(btnSeekUp);
            h1.add(btnSeekDown);

//Add the horizontal field manager to the vertical field manager. 
            mgr.add(h1);

//Add the RSSI label to the screen. 
            mgr.add(_lblRSSI);

//Create a horizontal field manager to add the buttons that control 
//the RSSI, one beside the other. 
            HorizontalFieldManager h2 = new HorizontalFieldManager();

//Add the RSSI control buttons to the horizontal field manager. 
            h2.add(btnRSSIUp);
            h2.add(btnRSSIDown);

//Add the horizontal field manager to the vertical field manager. 
            mgr.add(h2);
            
//Add the vertical field manager to the screen. 
            add(mgr);

//Set the initial text to display in your labels.             
            _lblRDS.setText("Initializing player...");
            _lblFreq.setText("Frequency");
            _lblRSSI.setText(Integer.toString(_rssi));
            
//Initialize your FM radio player.
            initPlayer();
            
//Tune the radio to a station.  
            setFreq("105.3");
        }
        
//Create your initPlayer() method. Create your Player object and retrieve 
//access to the FM radio on the BlackBerry device.  
        public void initPlayer()
        {
            Player myPlayer = null;
            
            try
            {
                myPlayer = Manager.createPlayer( "capture://radio" );

//Process any errors that occur.  
            } catch ( Exception e ) 
            {
                _lblRDS.setText(e.getMessage( ));
            }
            
//If you create the Player successfully, put it in the REALIZED state.  
            if(myPlayer != null)
            {        
                try
                {
                    myPlayer.realize( );

//Retrieve your FmTunerControl and RDSControl objects.  
                    _fmTuner = ( FmTunerControl ) myPlayer.getControl( "TunerControl" );
                    _rds = ( RDSControl ) myPlayer.getControl( "RDSControl" );

//Put your Player object in the PREFETCHED state.
                    myPlayer.prefetch( );

//Process any errors that occur.  
                } catch ( Exception e ) 
                {
                    _lblRDS.setText(e.getMessage( ));
                }
            }

//If your Player successfully entered the PREFETCHED state, start the FM 
//audio stream. Otherwise, process the error that occurs.
            if(myPlayer.getState() == Player.PREFETCHED)
            {
                try
                {
                    myPlayer.start( );
                }catch( Exception e)
                {
                    _lblRDS.setText(e.getMessage( ));
                }
            }
        }
        
//Create the seek() method. Declare variables to keep track of the current 
//frequency and the frequency returned from FmTunerControl.seek(). 
        private void seek(boolean direction, int startFrequency)
        {
            int found = 0;
            int freq = 0;

//If your FmTunerControl object is valid, offset the starting frequency from 
//your search. Otherwise the FmTunerControl.seek() method may return 
//the current frequency. 
            if (_fmTuner != null)
            {
                // add an offset to the startfrequency to get off a currently 
                // tuned frequency
                if (direction)
                {
                    freq = startFrequency + 2000;
                } else
                {
                    freq = startFrequency - 2000;
                }

//Invoke FmTunerControl.seek(). 
                try 
                {
                    // start a seek in the given direction with the used RSSI 
                    // value and a start frequency with a certain offset
                    
                    _lblRDS.setText("Seeking...");
                    found = ( _fmTuner.seek( freq, direction, _rssi ) )[ 0 ];

//If no signal is found, disable the radio mute enabled by the seek 
//operation and tune the radio back to the previous station.  
                    if ( found == 0 ) 
                    // this happens if no station is found and seek times out
                    // after 5 seconds
                    {
                        _lblRDS.setText("Sorry, seek failed");
                        _fmTuner.setMute(false); // seek without station stays muted 
                        setFreq(_lblFreq.getText()); // tune back to last one

//If a signal is found, update the freqency label, and display the RDS 
//information for this station if available. 
                    } else 
                    {
                        _lblFreq.setText(frequencyToString(found));
                        getRadioData();
                    }

//If an error occurs, tune the radio back to the previous station and disable 
//the mute enabled by the seek operation. If a secondary error occurs, display 
//the message in the RDS information label. 
                } catch (Exception e) 
                {
                    setFreq(_lblFreq.getText());
                    try 
                    {
                        _fmTuner.setMute(false); // seek without station stays muted 
                    } catch( Exception e1 ) 
                    { 
                        _lblRDS.setText(e.getMessage() + "\n" + e1.getMessage());
                    }
                }
            }
        }
        
//Create the setFreq() method.
        private void setFreq(String freq)
        {
            try
            {
//Convert the freq parameter from a String to an int value.
                int frequency = stringToFrequency(freq);

//Tune the FM radio receiver to the requested frequency. Update the 
//frequency label on the screen.  
                _fmTuner.setFrequency( frequency, TunerControl.MODULATION_FM );
                _lblFreq.setText(freq);

//If RDS information is available, display it on the screen.
                getRadioData();

//If an error occurs, suggest a new frequency.
            }catch ( NumberFormatException n )
            {
                _lblFreq.setText( frequencyToString( 990000 ) );
            }                
        }

//Create the getRadioData() method. If the RDS object you created is valid, display 
//the station information in _lblRDS. Otherwise indicate that RDS information 
//is unavailable.          
        public void getRadioData( )
        {
            if ( _rds != null )
            {
                _lblRDS.setText(_rds.getPS());                
            } else
            {
                _lblRDS.setText("Radio information unavailable.");
            }
        }
 
//Create the frequencyToString() method.       
        private String frequencyToString( int frequency )
        {
            // the frequency should have a maximum of 5 digits in MHz
            StringBuffer bf = new StringBuffer( 5 );
            // these are the MHz
            bf.append( frequency / 10000 );
            bf.append( "." );
            // this is the digit after the comma
            bf.append( ( frequency % 10000 ) / 1000 );
            return bf.toString( );
        }

//Create the stringToFrequency() method.
        private int stringToFrequency( String fr ) 
        {
            // these are the MHz
            int f = Integer.parseInt( fr.substring( 0, fr.indexOf( '.' ) ) ) * 10000;
            // adding the rest after the comma
            f += Integer.parseInt( fr.substring( fr.indexOf( '.' ) + 1 ) ) * 1000;
            return f;
        }
    }
}