Telephony

Cascades provides basic Phone APIs that you can use to show the dial pad, start a call, or listen to call-related notifications.

You can use the Phone class to show the dial pad on a BlackBerry device and make a call. You can use the Call, CallState, and CallType classes to learn about active calls on a device. For example, you can find out if the current call is connected, ringing, on hold, or disconnected. You can also find out what type of call it is, such as incoming, outgoing, multiparty, or emergency. You can use the Line and LineType classes to find out information about the line on a device, such as the device phone number or the BlackBerry ID of the participant in a BBM Video chat.

Screen showing the main screen of the Call a Pizza sample app.

If you are using an API level of 10.2 or later for your project, you can use the CallCommandResponse class to display information about an incoming call and details about the network response to a call command. For more information about setting an API level, see API levels.

You can use the Phone APIs to integrate the phone on a device with your app. For example, you could use Phone APIs to create a pizzeria finder app that finds and displays the phone numbers of the pizzerias in your area.

You can download the Call a pizza sample that demonstrates how to create a simple pizzeria finder app and import it into your workspace to follow along. For more information about importing projects, see Import an existing project.

Before you begin

Phone APIs are part of the system library. To include the Phone APIs in your app, add the following line to your .pro file:

LIBS += -lbbsystem

To enable your app to access the phone, you must add access_phone and control_phone permissions to your bar-descriptor.xml file.

The access_phone permission allows your app to access the phone app (for example, to request the dial pad).

The control_phone permission allows your app to control an ongoing call (for example, to send DTMF tones or end the call).

Depending on the API that you are using in your app, you may need one or both of these permissions. To learn more about the bar-descriptor.xml file, see The bar-descriptor.xml file. To learn more about permissions, see App permissions.

Showing the dial pad

You can use the requestDialpad() function to display a dial pad in your app. All you need to do is supply an address to pre-populate the dial pad with a phone number to call. If you don't supply an address, the dial pad doesn't display a phone number. You can use the LineType enumeration to supply the type of line to use when a user initiates a call (for example, cellular, BlackBerry Mobile Voice System (BlackBerry MVS), or BBM Video chat). If you don't supply a type, the Cellular line type is used.

The QML code sample below displays a single button to call a specific phone number. A Phone object is added to the Container using attachedObjects. When the user taps the button, the clicked() signal is emitted and the requestDialpad() function is called.

Screen showing the example app UI and the displayed dialpad.
import bb.cascades 1.2
import bb.system.phone 1.0

// Creates one page with a button. When you tap the button,
// a dial pad with a specific phone number is displayed.

Page {
    Container {
        layout: StackLayout {
        }
        
        Button {
            id: callButton
            text: "Call me"
            verticalAlignment: VerticalAlignment.Center
            horizontalAlignment: HorizontalAlignment.Center
            
            onClicked: {
                phone.requestDialpad("(519) 555-0100")

            }
        }

    }
    attachedObjects: [
        Phone {
            id: phone
        }
    ]
}

Making an outgoing call

The call button on the dialpad. When you use the requestDialpad() function, your app presents a dial pad on the user's device, but your app doesn't make a phone call. The user must tap the Call button on the device to initiate the call.

Using the example of the pizzeria finder app, you might want to include the option for users to call to reserve seats at the selected pizzeria. You can initiate the call by simply changing requestDialpad() to initiateCall(). By default, initiateCall() makes a Cellular call if you do not supply a line type.

If you make this change to the code sample above, a dialog box is presented when a user taps the button. This dialog box is a SystemDialog that the Phone app creates. For more information about system dialog boxes, see System dialog boxes.

Screen showing the SystemDialog that is displayed when calls are initiated.

When a user makes an outgoing call from your app, you can control the type of call that the user makes. You can restrict your app to make cellular calls by using the initiateCellularCall() function, or you can supply a BlackBerry ID to the initiateCall() function to start a BBM Video chat.

Before you use these functions, you should learn more about which line types are supported on the user's device. The lines() function returns a QMap of lines that are supported on a device. You can use the lines() function to find all the Line types that are available on the device, as well as information about each line, such as the id, the type, the address, and a description of the line.

  • If the line type is Cellular, the address is the phone number of the line.

  • If the line type is VideoChat, the address is the BlackBerry ID of the device.

  • If the line type is MVS, the address is the work phone number used by the device in BlackBerry MVS.

You can use the activeLine() function to find out which line on a device is active. Then, your app can send an outgoing call to an alternate line. You can use the isLineAvailable() function to check to see if a line is available for outgoing calls.

If you are using an API level of 10.2 or later for your project, you can use the availableLines() function to find all the lines that are currently available to make a call. You can use the endcall() function to end a call on a device. For more information about setting an API level, see API levels.

Finding call command details Since 10.2

You can listen for the callCommandResponseReceived() signal to learn about the details of the call command response.

bool res = (QObject::connect(m_pPhone, 
    SIGNAL(callCommandResponseReceived(
        const bb::system::phone::CallCommandResponse &)), 
    this, 
    SLOT(onCallCommandResponseReceived(
        const bb::system::phone::CallCommandResponse&))));

    Q_ASSERT(res);
    // Since the variable is not used in the app, 
    // this is added to avoid a compiler warning.
    Q_UNUSED(res);

Details about the call command response (such as the command the response is for, the call ID of the call the command was executed on, the error, and an error description) are provided by the CallCommandResponse object that is updated when the callCommandResponseReceived() signal is emitted.

Here's a code sample that shows a simple onCallCommandResponseReceived() slot that is invoked when the callCommandResponseReceived() signal is emitted.

void MyApp::onCallCommandResponseReceived( 
    const bb::system::phone::CallCommandResponse& response)
{

       qDebug() << "Executing onCallCommandResponse";

       mCallCommand = response.callCommand();
       qDebug() << "Response.callCommand() is " << mCallCommand;

       mResponseId = response.responseId();
       qDebug() << "Response.responseId() is " << mResponseId;

       mCallId = response.callId();
       qDebug() << "Response.callId() is " << mCallId;

       mError = response.error();
       qDebug() << "Error: " << response.error();
}

Listening for incoming calls

You can use the callUpdated() signal to listen for incoming and outgoing calls in your app. The callUpdated() signal is emitted when an incoming call is received or updated, or an outgoing call is updated. Here's a code sample that connects the callUpdated() signal to an onCallUpdated() slot that handles the incoming call.

bool success = connect(phone,
     SIGNAL(callUpdated(bb::system::phone::Call&)),
     this,
     SLOT(onCallUpdated(bb::system::phone::Call&)));

     if (success) {
        // Signal was successfully connected.
     } else {
        // Failed to connect to signal.
        // This is not normal in most cases and can be a critical 
        // situation for your app! Make sure you know exactly why
        // this has happened. Add some code to recover from the 
        // lost connection below this line.
     }

When the callUpdated() signal is emitted, the Call object is updated with information about the incoming call. You can use the callState() function to perform different actions in your app based on the state of the call.

Here's a code sample that shows a simple onCallUpdated() slot that is invoked when the callUpdated() signal is emitted. This function checks the state of the call before it performs an action.

void MyApp::onCallUpdated(const bb::system::phone::Call &call)
{
    CallState::Type state = call.callState();
    qDebug() << "call updated: callId=" 
        << call.callId() << " callState=" << state;

    if (bb::system::phone::CallState::Connected == state) {
        qDebug() << "call connected, do something ...";
    
        // Do something with this call now that you know
        // that it is connected and active.
    }
}

Sending DTMF tones

Dual Tone Multi-Frequency (DTMF) tones are the sounds used for touch-tone dialing. You can send DTMF tones to an active call on a device by using the sendDTMFTones() function. You can use this function to create an app that works with an interactive voice response system. If the user taps the dial pad during an active call, you can send the corresponding tones to the active call to select items in a directory or choices from a recorded menu. Here's a QML code sample that sends the tones of the numbers "12345" to the active call.

import bb.cascades 1.2
import bb.system.phone 1.0

// Creates one page with a button. When you tap the button,
// a dial pad with a specific phone number is displayed.

Page {
    Container {
        layout: StackLayout {
        }
        
        Button {
            id: sendDTMFTones_button
            text: "Send DTMF Tones"
            verticalAlignment: VerticalAlignment.Center
            horizontalAlignment: HorizontalAlignment.Center
            
            onClicked: {
                phone.sendDTMFTones("12345");
            }
        }
    }
    attachedObjects: [
        Phone {
            id: phone
        }
    ]
}

Here's how you can send DTMF tones using C++:

void MyApp::sendDTMF()
{
    if (phone != NULL) {
        qDebug() << "sendDTMF()" << endl;

        QByteArray tones("12345");
        bool ok = mPhone->sendDTMFTones(tones);

        qDebug() << (ok ? "tones sent." : "tones not sent.") << endl;
    }
}

When you test your app, you may not hear the DTMF tones on the device because they are sent directly to the device programmatically.

Retrieving the phone number of a device

Sometimes you need to know some information about the user's device, such as what type of hardware is available, which network is being used, or its phone number. You can use the HardwareInfo class to find general information about the device, such as its name, model, and physical attributes. Here's a sample that shows you how to extract the device name and the wireless network information in C++. In this sample, the output is sent to the console log file.

void ApplicationUI::RetrievePhoneNumber()
{
	HardwareInfo *hardwareInfo = new HardwareInfo(this);
	CellularNetworkInfo *cellularNetworkInfo = 
			new CellularNetworkInfo(0, this);

	qDebug() << "hardware: " 
			<< hardwareInfo->deviceName().toStdString() << endl;
	qDebug() << "cell network: " 
			<< cellularNetworkInfo->name().toStdString() << endl;
}

You can also find information about the user's wireless network using the Radio and SIM APIs. You can determine the capabilities and state of a connected wireless network, determine the specific services that the network supports, retrieve status information for an inserted micro SIM card, and more.

If you need only the phone number of the device, you can use the address() function. If the active line is a Cellular line, the line address is the phone number. If the active line is a BBM Video chat, the address is the user's BlackBerry ID. You can use the activeLine() function to find out which line is active on the user's device. Here's a code sample that finds the number of lines on a device, and then finds the address of each line on the device in C++. In this sample, the output is sent to the console log file.

void ApplicationUI::FindAddresses()
{
	Phone *phone = new Phone (this);

	QMap<QString,Line> lines = phone->lines();
	qDebug() << "phone lines count: " << lines.count() << endl;
	foreach(Line line, lines) {
	   qDebug() << "line address: " 
            << line.address().toStdString()  << endl;
	}
}

Invoking the Phone app

Cascades provides basic classes that let you interact with the phone on a device. You can also use the invocation framework to integrate your app with the Phone application. You can register your app with the invocation framework and invoke the Phone application to make a call, including emergency calls. For more information, see Invoking core applications.

Last modified: 2014-01-23

comments powered by Disqus