Expand Minimize Picture-in-picture Power Device Status Voice Recognition Skip Back Skip Forward Minus Plus Play Search
Internet Explorer alert
This browser is not recommended for use with smartdevicelink.com, and may not function properly. Upgrade to a different browser to guarantee support of all features.
close alert
To Top Created with Sketch. To Top
To Bottom Created with Sketch. To Bottom
iOS Guides
Setting the Navigation Destination

Setting the Navigation Destination

The SDLSendLocation RPC gives you the ability to send a GPS location to the active navigation app on the module.

When using the SDLSendLocation RPC, you will not have access to any information about how the user interacted with this location, only if the request was successfully sent. The request will be handled by the module from that point on using the active navigation system.

Checking Your App's Permissions

The SDLSendLocation RPC is restricted by most 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 send a location 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 *setSendLocationPermissionElement = [[SDLPermissionElement alloc] initWithRPCName:SDLRPCFunctionNameSendLocation parameterPermissions:nil];

id observerId = [self.sdlManager.permissionManager subscribeToRPCPermissions:@[setSendLocationPermissionElement] groupType:SDLPermissionGroupTypeAny withHandler:^(NSDictionary<SDLRPCFunctionName, SDLRPCPermissionStatus *> * _Nonnull updatedPermissionStatuses, SDLPermissionGroupStatus status) {
    if (status != SDLPermissionGroupStatusAllowed) {
        // Your app does not have permission to send the `SDLSendLocation` request for its current HMI level
        return;
    }

    // Your app has permission to send the `SDLSendLocation` request for its current HMI level
}];
let setSendLocationPermissionElement = SDLPermissionElement(rpcName: .sendLocation, parameterPermissions: nil)

let observerId = sdlManager.permissionManager.subscribe(toRPCPermissions: [setSendLocationPermissionElement], groupType: .any, withHandler: { (allChanges, groupStatus) in
    // This handler will be called whenever the permission status changes
    guard groupStatus == .allowed else {
        // Your app does not have permission to send the `SDLSendLocation` request for its current HMI level
        return
    }

    // Your app has permission to send the `SDLSendLocation` request for its current HMI level
})

Checking if the Module Supports Sending a Location

Since some modules will not support sending a location, you should check if the module supports this feature before trying to use it. 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 sending a location, 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).

Note

If you discover that the module does not support sending a location 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 SDLSendLocation request.

- (void)isSendLocationSupportedWithHandler:(void (^) (BOOL success, NSError * _Nullable error))handler {
    // Check if the module has navigation capabilities
    if (![self.sdlManager.systemCapabilityManager isCapabilitySupported:SDLSystemCapabilityTypeNavigation]) {
        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 `SDLSendLocation` 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 navigation capability has already been retrieved from the module
    SDLNavigationCapability *navigationCapability = self.sdlManager.systemCapabilityManager.navigationCapability;
    if (navigationCapability != nil) {
        return handler(navigationCapability.sendLocationEnabled.boolValue, nil);
    }

    // Retrieve the navigation capability from the module
    [self.sdlManager.systemCapabilityManager updateCapabilityType:SDLSystemCapabilityTypeNavigation completionHandler:^(NSError * _Nullable error, SDLSystemCapabilityManager * _Nonnull systemCapabilityManager) {
        if (error != nil) {
            return handler(NO, error);
        }

        return handler(systemCapabilityManager.navigationCapability.sendLocationEnabled.boolValue, nil);
    }];
}
func isSendLocationSupported(handler: @escaping (_ success: Bool, _ error: Error?) -> Void) {
    // Check if the module has navigation capabilities
    guard sdlManager.systemCapabilityManager.isCapabilitySupported(type: .navigation) 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 `SDLSendLocation` 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 navigation capability has already been retrieved from the module
    if let navigationCapability = sdlManager.systemCapabilityManager.navigationCapability {
        return handler(navigationCapability.sendLocationEnabled?.boolValue ?? false, nil)
    }

    // Retrieve the navigation capability from the module
    sdlManager.systemCapabilityManager.updateCapabilityType(.navigation) { (error, systemCapabilityManager) in
        if (error != nil) {
            return handler(false, error)
        }

        return handler(systemCapabilityManager.navigationCapability?.sendLocationEnabled?.boolValue ?? false, nil)
    }
}

Using Send Location

To use the SDLSendLocation request, you must at minimum include the longitude and latitude of the location.

SDLSendLocation *sendLocation = [[SDLSendLocation alloc] initWithLongitude:-97.380967 latitude:42.877737 locationName:@"The Center" locationDescription:@"Center of the United States" address:@[@"900 Whiting Dr", @"Yankton, SD 57078"] phoneNumber:nil image:nil];

[self.sdlManager sendRequest:sendLocation withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) {
    if (response == nil) {
        // Encountered an error sending `SendLocation`
        return;
    }

    SDLResult resultCode = response.resultCode;
    if (!response.success.boolValue) {
        if ([resultCode isEqualToEnum:SDLResultInvalidData]) {
            // `SDLSendLocation` was rejected. The request contained invalid data
        } else if ([resultCode isEqualToEnum:SDLResultDisallowed]) {
            // Your app is not allowed to use `SDLSendLocation`
        } else {
            // Some unknown error has occurred
        }
        return;
    }

    // `SDLSendLocation` successfully sent
}];
let sendLocation = SDLSendLocation(longitude: -97.380967, latitude: 42.877737, locationName: "The Center", locationDescription: "Center of the United States", address: ["900 Whiting Dr", "Yankton, SD 57078"], phoneNumber: nil, image: nil)

sdlManager.send(request: sendLocation) { (request, response, error) in
    guard let response = response as? SDLSendLocationResponse else {
        // Encountered an error sending `SendLocation`
        return
    }

    guard response.success.boolValue == true else {
        switch response.resultCode {
        case .invalidData:
        // `SDLSendLocation` was rejected. The request contained invalid data
        case .disallowed:
        // Your app is not allowed to use `SDLSendLocation`
        default:
            // Some unknown error has occurred
        }

        return
    }

    // `SDLSendLocation` successfully sent
}

Checking the Result of Send Location

The SDLSendLocation request has three possible responses that you should expect:

  1. SUCCESS - Successfully sent.
  2. INVALID_DATA - The request contains invalid data and was rejected.
  3. DISALLOWED - Your app does not have permission to use the SDLSendLocation request.
View on GitHub.com
Previous Section Next Section