The SDLDialNumber
RPC allows you make a phone call via the user's phone. In order to dial a phone number you must be sure that the device is connected via Bluetooth (even if your device is also connected using a USB cord) for this request to work. If the phone is not connected via Bluetooth, you will receive a result of REJECTED
from the module.
SDLDialNumber
is an RPC that is usually restricted by OEMs. As a result, a module may reject your request if your app does not have the correct permissions. Your SDL app may also be restricted to only being allowed to making a phone call when your app is open (i.e. the hmiLevel
is non-NONE
) or when it is the currently active app (i.e. the hmiLevel
is FULL
).
SDLPermissionElement *setDialNumberPermissionElement = [[SDLPermissionElement alloc] initWithRPCName:SDLRPCFunctionNameDialNumber parameterPermissions:nil]; id observerId = [self.sdlManager.permissionManager subscribeToRPCPermissions:@[setDialNumberPermissionElement] groupType:SDLPermissionGroupTypeAny withHandler:^(NSDictionary<SDLPermissionRPCName, NSNumber *> * _Nonnull allChanges, SDLPermissionGroupStatus groupStatus) { if (groupStatus != SDLPermissionGroupStatusAllowed) { // Your app does not have permission to send the `SDLDialNumber` request for its current HMI level return; } // Your app has permission to send the `SDLDialNumber` request for its current HMI level }];
let setDialNumberPermissionElement = SDLPermissionElement(rpcName: .dialNumber, parameterPermissions: nil) let observerId = sdlManager.permissionManager.subscribe(toRPCPermissions: [setDialNumberPermissionElement], groupType: .any, withHandler: { (individualStatuses, groupStatus) in guard groupStatus == .allowed else { // Your app does not have permission to send the `SDLDialNumber` request for its current HMI level return } // Your app has permission to send the `SDLDialNumber` request for its current HMI level })
Since making a phone call is a newer feature, there is a possibility that some legacy modules will reject your request because the module does not support the SDLDialNumber
request. Once you have successfully connected to the module, you can check the module's capabilities via the SDLManager.systemCapabilityManager
as shown in the example below. Please note that you only need to check once if the module supports calling a phone number, however you must wait to perform this check until you know that the SDL app has been opened (i.e. the hmiLevel
is non-NONE
).
If you discover that the module does not support calling a phone number or that your app does not have the right permissions, you should disable any buttons, voice commands, menu items, etc. in your app that would send the SDLDialNumber
request.
- (void)isDialNumberSupportedWithHandler:(void (^) (BOOL success, NSError * _Nullable error))handler { // Check if the module has phone capabilities if (![self.sdlManager.systemCapabilityManager isCapabilitySupported:SDLSystemCapabilityTypePhoneCall]) { return handler(false, nil); } // Legacy modules (pre-RPC Spec v4.5) do not support system capabilities, so for versions less than 4.5 we will assume `DialNumber` is supported if `isCapabilitySupported` returns true SDLMsgVersion *sdlMsgVersion = self.sdlManager.registerResponse.sdlMsgVersion; if (sdlMsgVersion == nil) { return handler(true, nil); } SDLVersion *rpcSpecVersion = [[SDLVersion alloc] initWithSDLMsgVersion:sdlMsgVersion]; if (![rpcSpecVersion isGreaterThanOrEqualToVersion:[[SDLVersion alloc] initWithMajor:4 minor:5 patch:0]]) { return handler(true, nil); } // Check if the phone capability has already been retrieved from the module SDLPhoneCapability *phoneCapability = self.sdlManager.systemCapabilityManager.phoneCapability; if (phoneCapability != nil) { return handler(phoneCapability.dialNumberEnabled.boolValue, nil); } // Retrieve the phone capability from the module [self.sdlManager.systemCapabilityManager updateCapabilityType:SDLSystemCapabilityTypePhoneCall completionHandler:^(NSError * _Nullable error, SDLSystemCapabilityManager * _Nonnull systemCapabilityManager) { if (error != nil) { return handler(NO, error); } return handler(systemCapabilityManager.phoneCapability.dialNumberEnabled.boolValue, nil); }]; }
func isDialNumberSupported(handler: @escaping (_ success: Bool, _ error: Error?) -> Void) { // Check if the module has phone capabilities guard sdlManager.systemCapabilityManager.isCapabilitySupported(type: .phoneCall) else { return handler(false, nil) } // Legacy modules (pre-RPC Spec v4.5) do not support system capabilities, so for versions less than 4.5 we will assume `SDLDialNumber` is supported if `isCapabilitySupported` returns true guard let sdlMsgVersion = sdlManager.registerResponse?.sdlMsgVersion, SDLVersion(sdlMsgVersion: sdlMsgVersion).isGreaterThanOrEqual(to: SDLVersion(major: 4, minor: 5, patch: 0)) else { return handler(true, nil) } // Check if the phone capability has already been retrieved from the module if let phoneCapability = sdlManager.systemCapabilityManager.phoneCapability { return handler(phoneCapability.dialNumberEnabled?.boolValue ?? false, nil) } // Retrieve the phone capability from the module sdlManager.systemCapabilityManager.updateCapabilityType(.phoneCall) { (error, systemCapabilityManager) in if (error != nil) { return handler(false, error) } return handler(systemCapabilityManager.phoneCapability?.dialNumberEnabled?.boolValue ?? false, nil) } }
Once you know that the module supports dialing a phone number and that your SDL app has permission to send the SDLDialNumber
request, you can create and send the request.
SDLDialNumber
strips all characters except for 0
-9
, *
, #
, ,
, ;
, and +
.
SDLDialNumber *dialNumber = [[SDLDialNumber alloc] initWithNumber: @"1238675309"]; [self.sdlManager sendRequest:dialNumber withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) { if (error != nil || ![response isKindOfClass:SDLDialNumberResponse.class]) { // Encountered error sending `SDLDialNumber` return; } SDLDialNumberResponse *dialNumber = (SDLDialNumberResponse *)response; SDLResult resultCode = dialNumber.resultCode; if (!resultCode.boolValue) { if ([resultCode isEqualToEnum:SDLResultRejected]) { // `SDLDialNumber` was rejected. Either the call was sent and cancelled or there is no device connected } else if ([resultCode isEqualToEnum:SDLResultDisallowed]) { // Your app is not allowed to use `SDLDialNumber` } else { // Some unknown error has occurred } return; } // `SDLDialNumber` successfully sent }];
let dialNumber = SDLDialNumber(number: "1238675309") sdlManager.send(request: dialNumber) { (request, response, error) in guard let response = response as? SDLDialNumberResponse, error == nil else { // Encountered error sending `SDLDialNumber` return } guard response.success.boolValue == true else { switch response.resultCode { case .rejected: // `SDLDialNumber` was rejected. Either the call was sent and cancelled or there is no device connected case .disallowed: // Your app is not allowed to use `SDLDialNumber` default: // Some unknown error has occurred } return } // `SDLDialNumber` successfully sent }
The SDLDialNumber
request has three possible responses that you should expect:
SUCCESS
- The request was successfully sent, and a phone call was initiated by the user.REJECTED
- This can mean either:
DISALLOWED
- Your app does not have permission to use the SDLDialNumber
request.