summaryrefslogtreecommitdiff
path: root/Example Apps
diff options
context:
space:
mode:
authorleonid lokhmatov, Luxoft <zaqqqqqqqq@gmail.com>2020-08-15 11:01:00 +0300
committerleonid lokhmatov, Luxoft <zaqqqqqqqq@gmail.com>2020-08-15 11:01:00 +0300
commitfda353d69c15082a72e5f10c463bc4d4f347d1e5 (patch)
tree31427747470b838857d8dfcaf43e3ac70bf30c7e /Example Apps
parent0d0382314049a0196a533723eb1525c21dbb597a (diff)
parent062957f2c2963b30f4719909a1f795dcb7ca5961 (diff)
downloadsdl_ios-fda353d69c15082a72e5f10c463bc4d4f347d1e5.tar.gz
Merge branch 'develop' into 0253_vehicle_data_StabilityControlsStatus, all conflicts resolved (merged)
# Conflicts: # SmartDeviceLink-iOS.xcodeproj/project.pbxproj # SmartDeviceLink/SDLGetVehicleData.h # SmartDeviceLink/SDLGetVehicleData.m # SmartDeviceLink/SDLGetVehicleDataResponse.h # SmartDeviceLink/SDLGetVehicleDataResponse.m # SmartDeviceLink/SDLOnVehicleData.h # SmartDeviceLink/SDLOnVehicleData.m # SmartDeviceLink/SDLSubscribeVehicleData.h # SmartDeviceLink/SDLSubscribeVehicleData.m # SmartDeviceLink/SDLSubscribeVehicleDataResponse.h # SmartDeviceLink/SDLSubscribeVehicleDataResponse.m # SmartDeviceLink/SDLUnsubscribeVehicleData.h # SmartDeviceLink/SDLUnsubscribeVehicleData.m # SmartDeviceLink/SDLUnsubscribeVehicleDataResponse.h # SmartDeviceLink/SDLUnsubscribeVehicleDataResponse.m # SmartDeviceLinkTests/RPCSpecs/NotificationSpecs/SDLOnVehicleDataSpec.m # SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLGetVehicleDataSpec.m # SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLSubscribeVehicleDataSpec.m # SmartDeviceLinkTests/RPCSpecs/RequestSpecs/SDLUnsubscribeVehicleDataSpec.m # SmartDeviceLinkTests/RPCSpecs/ResponseSpecs/SDLGetVehicleDataResponseSpec.m # SmartDeviceLinkTests/RPCSpecs/ResponseSpecs/SDLSubscribeVehicleDataResponseSpec.m # SmartDeviceLinkTests/RPCSpecs/ResponseSpecs/SDLUnsubscribeVehicleDataResponseSpec.m
Diffstat (limited to 'Example Apps')
-rw-r--r--Example Apps/Example ObjC/ProxyManager.m71
-rw-r--r--Example Apps/Example ObjC/RPCPermissionsManager.m41
-rw-r--r--Example Apps/Example ObjC/VehicleDataManager.m10
-rw-r--r--Example Apps/Example Swift/ProxyManager.swift82
-rw-r--r--Example Apps/Example Swift/RPCPermissionsManager.swift56
5 files changed, 127 insertions, 133 deletions
diff --git a/Example Apps/Example ObjC/ProxyManager.m b/Example Apps/Example ObjC/ProxyManager.m
index 2c5c05357..68e27ee2f 100644
--- a/Example Apps/Example ObjC/ProxyManager.m
+++ b/Example Apps/Example ObjC/ProxyManager.m
@@ -11,6 +11,7 @@
#import "ProxyManager.h"
#import "RPCPermissionsManager.h"
#import "SmartDeviceLink.h"
+#import "SubscribeButtonManager.h"
#import "VehicleDataManager.h"
NS_ASSUME_NONNULL_BEGIN
@@ -24,6 +25,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (strong, nonatomic) VehicleDataManager *vehicleDataManager;
@property (strong, nonatomic) PerformInteractionManager *performManager;
@property (strong, nonatomic) ButtonManager *buttonManager;
+@property (strong, nonatomic) SubscribeButtonManager *subscribeButtonManager;
@property (nonatomic, copy, nullable) RefreshUIHandler refreshUIHandler;
@end
@@ -66,6 +68,7 @@ NS_ASSUME_NONNULL_BEGIN
self.vehicleDataManager = [[VehicleDataManager alloc] initWithManager:self.sdlManager refreshUIHandler:self.refreshUIHandler];
self.performManager = [[PerformInteractionManager alloc] initWithManager:self.sdlManager];
self.buttonManager = [[ButtonManager alloc] initWithManager:self.sdlManager refreshUIHandler:self.refreshUIHandler];
+ self.subscribeButtonManager = [[SubscribeButtonManager alloc] initWithManager:self.sdlManager];
[weakSelf sdlex_updateProxyState:ProxyStateConnected];
[RPCPermissionsManager setupPermissionsCallbacksWithManager:weakSelf.sdlManager];
@@ -145,7 +148,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (SDLLogConfiguration *)sdlex_logConfiguration {
SDLLogConfiguration *logConfig = [SDLLogConfiguration debugConfiguration];
- SDLLogFileModule *sdlExampleModule = [SDLLogFileModule moduleWithName:@"SDL Obj-C Example App" files:[NSSet setWithArray:@[@"ProxyManager", @"AlertManager", @"AudioManager", @"ButtonManager", @"MenuManager", @"PerformInteractionManager", @"RPCPermissionsManager", @"VehicleDataManager"]]];
+ SDLLogFileModule *sdlExampleModule = [SDLLogFileModule moduleWithName:@"SDL Obj-C Example App" files:[NSSet setWithArray:@[@"ProxyManager", @"AlertManager", @"AudioManager", @"ButtonManager", @"SubscribeButtonManager", @"MenuManager", @"PerformInteractionManager", @"RPCPermissionsManager", @"VehicleDataManager"]]];
logConfig.modules = [logConfig.modules setByAddingObject:sdlExampleModule];
logConfig.targets = [logConfig.targets setByAddingObject:[SDLLogTargetFile logger]];
logConfig.globalLogLevel = SDLLogLevelDebug;
@@ -225,6 +228,7 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - SDLManagerDelegate
+/// Called when the connection beween this app and the module has closed.
- (void)managerDidDisconnect {
if (self.state != ProxyStateStopped) {
[self sdlex_updateProxyState:ProxyStateSearchingForConnection];
@@ -233,83 +237,68 @@ NS_ASSUME_NONNULL_BEGIN
self.firstHMILevel = SDLHMILevelNone;
}
+/// Called when the state of the SDL app has changed. The state limits the type of RPC that can be sent. Refer to the class documentation for each RPC to determine what state(s) the RPC can be sent.
+/// @param oldLevel The old HMI Level
+/// @param newLevel The new HMI Level
- (void)hmiLevel:(SDLHMILevel)oldLevel didChangeToLevel:(SDLHMILevel)newLevel {
if (![newLevel isEqualToEnum:SDLHMILevelNone] && ([self.firstHMILevel isEqualToEnum:SDLHMILevelNone])) {
// This is our first time in a non-NONE state
self.firstHMILevel = newLevel;
- // Send AddCommands
+ // Send static menu items.
[self sdlex_createMenus];
+
+ // Subscribe to vehicle data.
[self.vehicleDataManager subscribeToVehicleOdometer];
}
if ([newLevel isEqualToEnum:SDLHMILevelFull]) {
- // The SDL app is in the foreground
- SDLLogD(@"The HMI level is full");
+ // The SDL app is in the foreground. Always try to show the initial state to guard against some possible weird states. Duplicates will be ignored by Core.
+ [self sdlex_showInitialData];
+ [self.subscribeButtonManager subscribeToAllPresetButtons];
} else if ([newLevel isEqualToEnum:SDLHMILevelLimited]) {
// An active NAV or MEDIA SDL app is in the background
- SDLLogD(@"The HMI level is limited");
} else if ([newLevel isEqualToEnum:SDLHMILevelBackground]) {
// The SDL app is not in the foreground
- SDLLogD(@"The HMI level is background");
} else if ([newLevel isEqualToEnum:SDLHMILevelNone]) {
// The SDL app is not yet running
- SDLLogD(@"The HMI level is none");
- }
-
- if ([newLevel isEqualToEnum:SDLHMILevelFull]) {
- // We're always going to try to show the initial state. because if we've already shown it, it won't be shown, and we need to guard against some possible weird states
- [self sdlex_showInitialData];
}
}
+/// Called when the SDL app's HMI context changes.
+/// @param oldContext The old HMI context
+/// @param newContext The new HMI context
- (void)systemContext:(nullable SDLSystemContext)oldContext didChangeToContext:(SDLSystemContext)newContext {
if ([newContext isEqualToEnum:SDLSystemContextAlert]) {
- SDLLogD(@"The System Context is Alert");
+ // The SDL app's screen is obscured by an alert
} else if ([newContext isEqualToEnum:SDLSystemContextHMIObscured]) {
- SDLLogD(@"The System Context is HMI Obscured");
+ // The SDL app's screen is obscured
} else if ([newContext isEqualToEnum:SDLSystemContextMain]) {
- SDLLogD(@"The System Context is Main");
+ // The SDL app's main screen is open
} else if ([newContext isEqualToEnum:SDLSystemContextMenu]) {
- SDLLogD(@"The System Context is Menu");
+ // The SDL app's menu is open
} else if ([newContext isEqualToEnum:SDLSystemContextVoiceRecognitionSession]) {
- SDLLogD(@"The System Context is Voice Recognition Session");
+ // A voice recognition session is in progress
}
}
+/// Called when the audio state of the SDL app has changed. The audio state only needs to be monitored if the app is streaming audio.
+/// @param oldState The old audio streaming state
+/// @param newState The new audio streaming state
- (void)audioStreamingState:(nullable SDLAudioStreamingState)oldState didChangeToState:(SDLAudioStreamingState)newState {
if ([newState isEqualToEnum:SDLAudioStreamingStateAudible]) {
// The SDL app's audio can be heard
- SDLLogD(@"The Audio Streaming State is Audible");
} else if ([newState isEqualToEnum:SDLAudioStreamingStateNotAudible]) {
// The SDL app's audio cannot be heard
- SDLLogD(@"The Audio Streaming State is Not Audible");
} else if ([newState isEqualToEnum:SDLAudioStreamingStateAttenuated]) {
// The SDL app's audio volume has been lowered to let the system speak over the audio. This usually happens with voice recognition commands.
- SDLLogD(@"The Audio Streaming State is Not Attenuated");
- }
-}
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-implementations"
-- (nullable SDLLifecycleConfigurationUpdate *)managerShouldUpdateLifecycleToLanguage:(SDLLanguage)language {
- SDLLifecycleConfigurationUpdate *update = [[SDLLifecycleConfigurationUpdate alloc] init];
-
- if ([language isEqualToEnum:SDLLanguageEnUs]) {
- update.appName = ExampleAppName;
- } else if ([language isEqualToString:SDLLanguageEsMx]) {
- update.appName = ExampleAppNameSpanish;
- } else if ([language isEqualToString:SDLLanguageFrCa]) {
- update.appName = ExampleAppNameFrench;
- } else {
- return nil;
}
-
- update.ttsName = [SDLTTSChunk textChunksFromString:update.appName];
- return update;
}
-#pragma clang diagnostic pop
+/// Called when the car's head unit language is different from the default langage set in the SDLConfiguration AND the head unit language is supported by the app (as set in `languagesSupported` of SDLConfiguration). This method is only called when a connection to Core is first established. If desired, you can update the app's name and text-to-speech name to reflect the head unit's language.
+/// @param language The head unit's current VR+TTS language
+/// @param hmiLanguage The head unit's current HMI language
+/// @return A SDLLifecycleConfigurationUpdate object
- (nullable SDLLifecycleConfigurationUpdate *)managerShouldUpdateLifecycleToLanguage:(SDLLanguage)language hmiLanguage:(SDLLanguage)hmiLanguage {
SDLLifecycleConfigurationUpdate *update = [[SDLLifecycleConfigurationUpdate alloc] init];
@@ -323,7 +312,7 @@ NS_ASSUME_NONNULL_BEGIN
return nil;
}
- update.ttsName = @[[SDLTTSChunk textChunksFromString:update.appName]];
+ update.ttsName = [SDLTTSChunk textChunksFromString:update.appName];
return update;
}
diff --git a/Example Apps/Example ObjC/RPCPermissionsManager.m b/Example Apps/Example ObjC/RPCPermissionsManager.m
index d79bde3e2..93d2755e6 100644
--- a/Example Apps/Example ObjC/RPCPermissionsManager.m
+++ b/Example Apps/Example ObjC/RPCPermissionsManager.m
@@ -24,18 +24,23 @@ NS_ASSUME_NONNULL_BEGIN
[self sdlex_checkCurrentPermissionWithManager:manager rpcName:showRPCName];
// Checks if all the RPCs need to create menus are allowed right at this moment
- NSArray<SDLRPCFunctionName> *menuRPCNames = @[SDLRPCFunctionNameAddCommand, SDLRPCFunctionNameCreateInteractionChoiceSet, SDLRPCFunctionNamePerformInteraction];
- [self sdlex_checkCurrentGroupPermissionsWithManager:manager rpcNames:menuRPCNames];
-
- // Set up an observer for permissions changes to media template releated RPCs. Since the `groupType` is set to all allowed, this block is called when the group permissions changes from all allowed. This block is called immediately when created.
- NSArray<SDLRPCFunctionName> *mediaTemplateRPCs = @[SDLRPCFunctionNameSetMediaClockTimer, SDLRPCFunctionNameSubscribeButton];
- SDLPermissionObserverIdentifier allAllowedObserverId = [self sdlex_subscribeGroupPermissionsWithManager:manager rpcNames:mediaTemplateRPCs groupType:SDLPermissionGroupTypeAllAllowed];
+ SDLPermissionElement *addCommandPermissionElement = [[SDLPermissionElement alloc] initWithRPCName:SDLRPCFunctionNameAddCommand parameterPermissions:nil];
+ SDLPermissionElement *createInteractionPermissionElement = [[SDLPermissionElement alloc] initWithRPCName:SDLRPCFunctionNameCreateInteractionChoiceSet parameterPermissions:nil];
+ SDLPermissionElement *performInteractionPermissionElement = [[SDLPermissionElement alloc] initWithRPCName:SDLRPCFunctionNamePerformInteraction parameterPermissions:nil];
+ NSArray<SDLPermissionElement *> *menuRPCPermissions = @[addCommandPermissionElement, createInteractionPermissionElement, performInteractionPermissionElement];
+ [self sdlex_checkCurrentGroupPermissionsWithManager:manager permissionElements:menuRPCPermissions];
+
+ // Set up an observer for permissions changes to media template releated RPCs. Since the `groupType` is set to all allowed, this block is called when the group permissions changes to all-allowed or from all-allowed to some-not-allowed.
+ SDLPermissionElement *setMediaClockPermissionElement = [[SDLPermissionElement alloc] initWithRPCName:SDLRPCFunctionNameSetMediaClockTimer parameterPermissions:nil];
+ SDLPermissionElement *subscribeButtonPermissionElement = [[SDLPermissionElement alloc] initWithRPCName:SDLRPCFunctionNameSubscribeButton parameterPermissions:nil];
+ NSArray<SDLPermissionElement *> *mediaTemplateRPCPermissions = @[setMediaClockPermissionElement, subscribeButtonPermissionElement];
+ SDLPermissionObserverIdentifier allAllowedObserverId = [self sdlex_subscribeGroupPermissionsWithManager:manager permissionElements:mediaTemplateRPCPermissions groupType:SDLPermissionGroupTypeAllAllowed];
// Stop observing permissions changes for the media template releated RPCs
[self sdlex_unsubscribeGroupPermissionsWithManager:manager observerId:allAllowedObserverId];
// Set up an observer for permissions changes to media template releated RPCs. Since the `groupType` is set to any, this block is called when the permission status changes for any of the RPCs being observed. This block is called immediately when created.
- [self sdlex_subscribeGroupPermissionsWithManager:manager rpcNames:mediaTemplateRPCs groupType:SDLPermissionGroupTypeAny];
+ [self sdlex_subscribeGroupPermissionsWithManager:manager permissionElements:mediaTemplateRPCPermissions groupType:SDLPermissionGroupTypeAny];
}
/**
@@ -73,26 +78,26 @@ NS_ASSUME_NONNULL_BEGIN
* @param rpcNames The names of the RPCs
* @return The current permission status for all the RPCs in the group
*/
-+ (SDLPermissionGroupStatus)sdlex_checkCurrentGroupPermissionsWithManager:(SDLManager *)manager rpcNames:(NSArray<SDLRPCFunctionName> *)rpcNames {
- SDLPermissionGroupStatus groupPermissionStatus = [manager.permissionManager groupStatusOfRPCNames:rpcNames];
- NSDictionary<NSString *, NSNumber *> *individualPermissionStatuses = [manager.permissionManager statusesOfRPCNames:rpcNames];
- [self sdlex_logRPCGroupPermissions:rpcNames groupPermissionStatus:groupPermissionStatus individualPermissionStatuses:individualPermissionStatuses];
++ (SDLPermissionGroupStatus)sdlex_checkCurrentGroupPermissionsWithManager:(SDLManager *)manager permissionElements:(NSArray<SDLPermissionElement *> *)permissionElements {
+ SDLPermissionGroupStatus groupPermissionStatus = [manager.permissionManager groupStatusOfRPCPermissions:permissionElements];
+ NSDictionary<NSString *, SDLRPCPermissionStatus *> *individualPermissionStatuses = [manager.permissionManager statusesOfRPCPermissions:permissionElements];
+ [self sdlex_logRPCGroupPermissions:permissionElements groupPermissionStatus:groupPermissionStatus individualPermissionStatuses:individualPermissionStatuses];
return groupPermissionStatus;
}
#pragma mark Subscribe Permissions
/**
- * Sets up a block for observing permission changes for a group of RPCs. This block is called immediately when created and when the permission status changes for the group of RPCs being observed.
+ * Sets up a block for observing permission changes for a group of RPCs. This block is called when the group permissions become all-allowed or from all-allowed to some-not-allowed.
*
* @param manager The SDL Manager
* @param rpcNames The names of the RPCs to be subscribed
* @param groupType The type of changes you want to be notified about for the group
* @return A unique identifier for the subscription. This can be used to later to unsubscribe from the notifications.
*/
-+ (SDLPermissionObserverIdentifier)sdlex_subscribeGroupPermissionsWithManager:(SDLManager *)manager rpcNames:(NSArray<SDLRPCFunctionName> *)rpcNames groupType:(SDLPermissionGroupType)groupType {
- SDLPermissionObserverIdentifier observerId = [manager.permissionManager subscribeToRPCNames:rpcNames groupType:groupType withHandler:^(NSDictionary<SDLPermissionRPCName,NSNumber<SDLBool> *> * _Nonnull change, SDLPermissionGroupStatus status) {
- [self sdlex_logRPCGroupPermissions:rpcNames groupPermissionStatus:status individualPermissionStatuses:change];
++ (SDLPermissionObserverIdentifier)sdlex_subscribeGroupPermissionsWithManager:(SDLManager *)manager permissionElements:(NSArray<SDLPermissionElement *> *)permissionElements groupType:(SDLPermissionGroupType)groupType {
+ SDLPermissionObserverIdentifier observerId = [manager.permissionManager subscribeToRPCPermissions:permissionElements groupType:groupType withHandler:^(NSDictionary<SDLPermissionRPCName,SDLRPCPermissionStatus *> * _Nonnull change, SDLPermissionGroupStatus status) {
+ [self sdlex_logRPCGroupPermissions:permissionElements groupPermissionStatus:status individualPermissionStatuses:change];
}];
return observerId;
}
@@ -126,10 +131,10 @@ NS_ASSUME_NONNULL_BEGIN
* @param groupPermissionStatus The permission status for all RPCs in the group
* @param individualPermissionStatuses The permission status for each of the RPCs in the group
*/
-+ (void)sdlex_logRPCGroupPermissions:(NSArray<NSString *> *)rpcNames groupPermissionStatus:(SDLPermissionGroupStatus)groupPermissionStatus individualPermissionStatuses:(NSDictionary<NSString *, NSNumber *> *)individualPermissionStatuses {
++ (void)sdlex_logRPCGroupPermissions:(NSArray<SDLPermissionElement *> *)rpcNames groupPermissionStatus:(SDLPermissionGroupStatus)groupPermissionStatus individualPermissionStatuses:(NSDictionary<NSString *, SDLRPCPermissionStatus *> *)individualPermissionStatuses {
SDLLogD(@"The group status for %@ has changed to: %lu", rpcNames, (unsigned long)groupPermissionStatus);
- [individualPermissionStatuses enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSNumber * _Nonnull obj, BOOL * _Nonnull stop) {
- [self sdlex_logRPCPermission:key isRPCAllowed:obj.boolValue];
+ [individualPermissionStatuses enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, SDLRPCPermissionStatus * _Nonnull obj, BOOL * _Nonnull stop) {
+ [self sdlex_logRPCPermission:key isRPCAllowed:obj.rpcAllowed];
}];
}
diff --git a/Example Apps/Example ObjC/VehicleDataManager.m b/Example Apps/Example ObjC/VehicleDataManager.m
index 5c2d3bac2..afdca21e7 100644
--- a/Example Apps/Example ObjC/VehicleDataManager.m
+++ b/Example Apps/Example ObjC/VehicleDataManager.m
@@ -144,9 +144,11 @@ NS_ASSUME_NONNULL_BEGIN
SDLLogD(@"App has permission to access vehicle data. Requesting vehicle data...");
+ SDLGetVehicleData *getAllVehicleData = [[SDLGetVehicleData alloc] initWithGps:@YES speed:@YES rpm:@YES instantFuelConsumption:@YES fuelRange:@YES externalTemperature:@YES turnSignal:@YES vin:@YES prndl:@YES tirePressure:@YES odometer:@YES beltStatus:@YES bodyInformation:@YES deviceStatus:@YES driverBraking:@YES wiperStatus:@YES headLampStatus:@YES engineTorque:@YES accPedalPosition:@YES steeringWheelAngle:@YES engineOilLife:@YES electronicParkBrakeStatus:@YES cloudAppVehicleID:@YES stabilityControlsStatus:@YES eCallInfo:@YES airbagStatus:@YES emergencyEvent:@YES clusterModeStatus:@YES myKey:@YES handsOffSteering:@YES];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- SDLGetVehicleData *getAllVehicleData = [[SDLGetVehicleData alloc] initWithAccelerationPedalPosition:YES airbagStatus:YES beltStatus:YES bodyInformation:YES clusterModeStatus:YES deviceStatus:YES driverBraking:YES eCallInfo:YES electronicParkBrakeStatus:YES emergencyEvent:YES engineOilLife:YES engineTorque:YES externalTemperature:YES fuelLevel:YES fuelLevelState:YES fuelRange:YES gps:YES headLampStatus:YES instantFuelConsumption:YES myKey:YES odometer:YES prndl:YES rpm:YES speed:YES steeringWheelAngle:YES tirePressure:YES turnSignal:YES vin:YES wiperStatus:YES];
+ getAllVehicleData.fuelLevel = @YES;
+ getAllVehicleData.fuelLevel_State = @YES;
#pragma clang diagnostic pop
[manager sendRequest:getAllVehicleData withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) {
@@ -219,9 +221,15 @@ NS_ASSUME_NONNULL_BEGIN
} else if ([vehicleDataType isEqualToString:ACExternalTemperatureMenuName]) {
vehicleDataDescription = vehicleData.externalTemperature.description;
} else if ([vehicleDataType isEqualToString:ACFuelLevelMenuName]) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
vehicleDataDescription = vehicleData.fuelLevel.description;
+#pragma clang diagnostic pop
} else if ([vehicleDataType isEqualToString:ACFuelLevelStateMenuName]) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
vehicleDataDescription = vehicleData.fuelLevel_State.description;
+#pragma clang diagnostic pop
} else if ([vehicleDataType isEqualToString:ACFuelRangeMenuName]) {
vehicleDataDescription = vehicleData.fuelRange.description;
} else if ([vehicleDataType isEqualToString:ACGPSMenuName]) {
diff --git a/Example Apps/Example Swift/ProxyManager.swift b/Example Apps/Example Swift/ProxyManager.swift
index 3b7ed1ef5..fdad60360 100644
--- a/Example Apps/Example Swift/ProxyManager.swift
+++ b/Example Apps/Example Swift/ProxyManager.swift
@@ -21,13 +21,15 @@ enum ProxyState {
}
class ProxyManager: NSObject {
- fileprivate var sdlManager: SDLManager!
- fileprivate var buttonManager: ButtonManager!
- fileprivate var vehicleDataManager: VehicleDataManager!
- fileprivate var performInteractionManager: PerformInteractionManager!
- fileprivate var firstHMILevelState: SDLHMILevel
+ private var sdlManager: SDLManager!
+ private var buttonManager: ButtonManager!
+ private var subscribeButtonManager: SubscribeButtonManager!
+ private var vehicleDataManager: VehicleDataManager!
+ private var performInteractionManager: PerformInteractionManager!
+ private var firstHMILevelState: SDLHMILevel
weak var delegate: ProxyManagerDelegate?
+
// Singleton
static let sharedManager = ProxyManager()
private override init() {
@@ -43,12 +45,6 @@ extension ProxyManager {
///
/// - Parameter connectionType: The type of transport layer to use.
func start(with proxyTransportType: ProxyTransportType) {
- guard sdlManager == nil else {
- // Manager already created, just start it again.
- startManager()
- return
- }
-
delegate?.didChangeProxyState(ProxyState.searching)
sdlManager = SDLManager(configuration: proxyTransportType == .iap ? ProxyManager.connectIAP() : ProxyManager.connectTCP(), delegate: self)
startManager()
@@ -117,7 +113,7 @@ private extension ProxyManager {
/// - Returns: A SDLLogConfiguration object
class func logConfiguration() -> SDLLogConfiguration {
let logConfig = SDLLogConfiguration.default()
- let exampleLogFileModule = SDLLogFileModule(name: "SDL Swift Example App", files: ["ProxyManager", "AlertManager", "AudioManager", "ButtonManager", "MenuManager", "PerformInteractionManager", "RPCPermissionsManager", "VehicleDataManager"])
+ let exampleLogFileModule = SDLLogFileModule(name: "SDL Swift Example App", files: ["ProxyManager", "AlertManager", "AudioManager", "ButtonManager", "SubscribeButtonManager", "MenuManager", "PerformInteractionManager", "RPCPermissionsManager", "VehicleDataManager"])
logConfig.modules.insert(exampleLogFileModule)
_ = logConfig.targets.insert(SDLLogTargetFile()) // Logs to file
logConfig.globalLogLevel = .debug // Filters the logs
@@ -136,6 +132,7 @@ private extension ProxyManager {
self.delegate?.didChangeProxyState(ProxyState.connected)
self.buttonManager = ButtonManager(sdlManager: self.sdlManager, updateScreenHandler: self.refreshUIHandler)
+ self.subscribeButtonManager = SubscribeButtonManager(sdlManager: self.sdlManager)
self.vehicleDataManager = VehicleDataManager(sdlManager: self.sdlManager, refreshUIHandler: self.refreshUIHandler)
self.performInteractionManager = PerformInteractionManager(sdlManager: self.sdlManager)
@@ -149,8 +146,8 @@ private extension ProxyManager {
// MARK: - SDLManagerDelegate
extension ProxyManager: SDLManagerDelegate {
- /// Called when the connection beween this app and SDL Core has closed.
- func managerDidDisconnect() {
+ /// Called when the connection beween this app and the module has closed.
+ func managerDidDisconnect() {
if delegate?.proxyState != .some(.stopped) {
delegate?.didChangeProxyState(ProxyState.searching)
}
@@ -161,36 +158,43 @@ extension ProxyManager: SDLManagerDelegate {
/// Called when the state of the SDL app has changed. The state limits the type of RPC that can be sent. Refer to the class documentation for each RPC to determine what state(s) the RPC can be sent.
///
/// - Parameters:
- /// - oldLevel: The old SDL HMI Level
- /// - newLevel: The new SDL HMI Level
+ /// - oldLevel: The old HMI Level
+ /// - newLevel: The new HMI Level
func hmiLevel(_ oldLevel: SDLHMILevel, didChangeToLevel newLevel: SDLHMILevel) {
if newLevel != .none && firstHMILevelState == .none {
// This is our first time in a non-NONE state
firstHMILevelState = newLevel
- // Send static menu items. Menu related RPCs can be sent at all `hmiLevel`s except `NONE`
+ // Send static menu items.
createMenuAndGlobalVoiceCommands()
+
+ // Subscribe to vehicle data.
vehicleDataManager.subscribeToVehicleOdometer()
}
switch newLevel {
- case .full: // The SDL app is in the foreground
- // Always try to show the initial state to guard against some possible weird states. Duplicates will be ignored by Core.
+ case .full:
+ // The SDL app is in the foreground. Always try to show the initial state to guard against some possible weird states. Duplicates will be ignored by Core.
showInitialData()
- case .limited: break // An active NAV or MEDIA SDL app is in the background
- case .background: break // The SDL app is not in the foreground
- case .none: break // The SDL app is not yet running
+ subscribeButtonManager.subscribeToPresetButtons()
+ case .limited: break // An active NAV or MEDIA SDL app is in the background
+ case .background: break // The SDL app is not in the foreground
+ case .none: break // The SDL app is not yet running
default: break
}
}
+ /// Called when the SDL app's HMI context changes.
+ /// - Parameters:
+ /// - oldContext: The old HMI context
+ /// - newContext: The new HMI context
func systemContext(_ oldContext: SDLSystemContext?, didChangeToContext newContext: SDLSystemContext) {
switch newContext {
- case SDLSystemContext.alert: break
- case SDLSystemContext.hmiObscured: break
- case SDLSystemContext.main: break
- case SDLSystemContext.menu: break
- case SDLSystemContext.voiceRecognitionSession: break
+ case SDLSystemContext.alert: break // The SDL app's screen is obscured by an alert
+ case SDLSystemContext.hmiObscured: break // The SDL app's screen is obscured
+ case SDLSystemContext.main: break // The SDL app's main screen is open
+ case SDLSystemContext.menu: break // The SDL app's menu is open
+ case SDLSystemContext.voiceRecognitionSession: break // A voice recognition session is in progress
default: break
}
}
@@ -198,8 +202,8 @@ extension ProxyManager: SDLManagerDelegate {
/// Called when the audio state of the SDL app has changed. The audio state only needs to be monitored if the app is streaming audio.
///
/// - Parameters:
- /// - oldState: The old SDL audio streaming state
- /// - newState: The new SDL audio streaming state
+ /// - oldState: The old audio streaming state
+ /// - newState: The new audio streaming state
func audioStreamingState(_ oldState: SDLAudioStreamingState?, didChangeToState newState: SDLAudioStreamingState) {
switch newState {
case .audible: break // The SDL app's audio can be heard
@@ -211,26 +215,6 @@ extension ProxyManager: SDLManagerDelegate {
/// Called when the car's head unit language is different from the default langage set in the SDLConfiguration AND the head unit language is supported by the app (as set in `languagesSupported` of SDLConfiguration). This method is only called when a connection to Core is first established. If desired, you can update the app's name and text-to-speech name to reflect the head unit's language.
///
- /// - Parameter language: The head unit's current language
- /// - Returns: A SDLLifecycleConfigurationUpdate object
- func managerShouldUpdateLifecycle(toLanguage language: SDLLanguage) -> SDLLifecycleConfigurationUpdate? {
- var appName = ""
- switch language {
- case .enUs:
- appName = ExampleAppName
- case .esMx:
- appName = ExampleAppNameSpanish
- case .frCa:
- appName = ExampleAppNameFrench
- default:
- return nil
- }
-
- return SDLLifecycleConfigurationUpdate(appName: appName, shortAppName: nil, ttsName: [SDLTTSChunk(text: appName, type: .text)], voiceRecognitionCommandNames: nil)
- }
-
- /// Called when the car's head unit language is different from the default langage set in the SDLConfiguration AND the head unit language is supported by the app (as set in `languagesSupported` of SDLConfiguration). This method is only called when a connection to Core is first established. If desired, you can update the app's name and text-to-speech name to reflect the head unit's language.
- ///
/// - Parameter language: The head unit's current VR+TTS language
/// - Parameter hmiLanguage: The head unit's current HMI language
/// - Returns: A SDLLifecycleConfigurationUpdate object
diff --git a/Example Apps/Example Swift/RPCPermissionsManager.swift b/Example Apps/Example Swift/RPCPermissionsManager.swift
index 1efcbe129..144a636f6 100644
--- a/Example Apps/Example Swift/RPCPermissionsManager.swift
+++ b/Example Apps/Example Swift/RPCPermissionsManager.swift
@@ -20,18 +20,23 @@ class RPCPermissionsManager {
_ = checkCurrentPermission(with: manager, rpcName: showRPCName)
// Checks if all the RPCs need to create menus are allowed right at this moment
- let menuRPCNames = [SDLRPCFunctionName.addCommand, SDLRPCFunctionName.createInteractionChoiceSet, SDLRPCFunctionName.performInteraction]
- _ = checkCurrentGroupPermissions(with: manager, rpcNames: menuRPCNames)
-
- // Set up an observer for permissions changes to media template releated RPCs. Since the `groupType` is set to all allowed, this block is called when the group permissions changes from all allowed. This block is called immediately when created.
- let mediaTemplateRPCs = [SDLRPCFunctionName.setMediaClockTimer, SDLRPCFunctionName.subscribeButton]
- let allAllowedObserverId = subscribeGroupPermissions(with: manager, rpcNames: mediaTemplateRPCs, groupType: .allAllowed)
+ let addCommandPermissionElement = SDLPermissionElement(rpcName: SDLRPCFunctionName.addCommand, parameterPermissions: nil)
+ let createInteractionPermissionElement = SDLPermissionElement(rpcName: SDLRPCFunctionName.createInteractionChoiceSet, parameterPermissions: nil)
+ let performInteractionPermissionElement = SDLPermissionElement(rpcName: SDLRPCFunctionName.performInteraction, parameterPermissions: nil)
+ let menuRPCPermissions = [addCommandPermissionElement, createInteractionPermissionElement, performInteractionPermissionElement]
+ _ = checkCurrentGroupPermissions(with: manager, permissionElements: menuRPCPermissions)
+
+ // Set up an observer for permissions changes to media template releated RPCs. Since the `groupType` is set to all allowed, this block is called when the group permissions changes to all-allowed or from all-allowed to some-not-allowed.
+ let setMediaClockPermissionElement = SDLPermissionElement(rpcName: SDLRPCFunctionName.setMediaClockTimer, parameterPermissions: nil)
+ let subscribeButtonPermissionElement = SDLPermissionElement(rpcName: SDLRPCFunctionName.subscribeButton, parameterPermissions: nil)
+ let mediaTemplatePermissions = [setMediaClockPermissionElement, subscribeButtonPermissionElement]
+ let allAllowedObserverId = subscribeGroupPermissions(with: manager, permissionElements: mediaTemplatePermissions, groupType: .allAllowed)
// Stop observing permissions changes for the media template releated RPCs
unsubscribeGroupPermissions(with: manager, observerId: allAllowedObserverId)
// Sets up a block for observing permission changes for a group of RPCs. Since the `groupType` is set to any, this block is called when the permission status changes for any of the RPCs being observed. This block is called immediately when created.
- _ = subscribeGroupPermissions(with: manager, rpcNames: mediaTemplateRPCs, groupType: .any)
+ _ = subscribeGroupPermissions(with: manager, permissionElements: mediaTemplatePermissions, groupType: .any)
}
/// Checks if the `DialNumber` RPC is allowed
@@ -47,24 +52,26 @@ class RPCPermissionsManager {
// MARK: - Check Permissions
private extension RPCPermissionsManager {
- /// Checks if the `Show` RPC is allowed right at this moment
+ /// Checks if the RPC is allowed at the time of the call
///
/// - Parameter manager: The SDL Manager
+ /// - Parameter rpcName: The name of the RPC to check
/// - Returns: true if allowed, false if not
class func checkCurrentPermission(with manager: SDLManager, rpcName: SDLRPCFunctionName) -> Bool {
let isRPCAllowed = manager.permissionManager.isRPCNameAllowed(rpcName)
- logRPCPermission(rpcName: rpcName, isRPCAllowed: isRPCAllowed)
+ SDLLog.d("\(rpcName.rawValue.rawValue) RPC can be sent to SDL Core? \(isRPCAllowed ? "YES" : "NO")")
return isRPCAllowed
}
- /// Checks if all the RPCs need to create menus are allowed right at this moment
+ /// Checks if all the given RPCs are allowed or not at the time of the call
///
/// - Parameter manager: The SDL Manager
- /// - Returns: The rpc names, the group permission status and the permission status for each rpc in the group
- class func checkCurrentGroupPermissions(with manager: SDLManager, rpcNames: [SDLRPCFunctionName]) -> SDLPermissionGroupStatus {
- let groupPermissionStatus = manager.permissionManager.groupStatus(ofRPCNames: rpcNames)
- let individualPermissionStatuses = manager.permissionManager.statuses(ofRPCNames: rpcNames)
- logRPCGroupPermissions(rpcNames: rpcNames, groupPermissionStatus: groupPermissionStatus, individualPermissionStatuses: individualPermissionStatuses)
+ /// - Parameter permissionElements: The RPCs and parameters to be checked
+ /// - Returns: The group permission status
+ class func checkCurrentGroupPermissions(with manager: SDLManager, permissionElements: [SDLPermissionElement]) -> SDLPermissionGroupStatus {
+ let groupPermissionStatus = manager.permissionManager.groupStatus(ofRPCPermissions: permissionElements)
+ let individualPermissionStatuses = manager.permissionManager.statuses(ofRPCPermissions: permissionElements)
+ logRPCGroupPermissions(permissionElements: permissionElements, groupPermissionStatus: groupPermissionStatus, individualPermissionStatuses: individualPermissionStatuses)
return groupPermissionStatus
}
@@ -73,10 +80,11 @@ private extension RPCPermissionsManager {
/// - Parameters:
/// - manager: The SDL Manager
/// - groupType: The type of changes to get notified about
+ /// - permissionElements: The RPCs and parameters to be checked
/// - Returns: A unique id assigned to observer. Use the id to unsubscribe to notifications
- class func subscribeGroupPermissions(with manager: SDLManager, rpcNames: [SDLRPCFunctionName], groupType: SDLPermissionGroupType) -> UUID {
- let permissionAllAllowedObserverId = manager.permissionManager.subscribe(toRPCNames: rpcNames, groupType: groupType, withHandler: { (individualStatuses, groupStatus) in
- self.logRPCGroupPermissions(rpcNames: rpcNames, groupPermissionStatus: groupStatus, individualPermissionStatuses: individualStatuses)
+ class func subscribeGroupPermissions(with manager: SDLManager, permissionElements: [SDLPermissionElement], groupType: SDLPermissionGroupType) -> UUID {
+ let permissionAllAllowedObserverId = manager.permissionManager.subscribe(toRPCPermissions: permissionElements, groupType: groupType, withHandler: { (individualStatuses, groupStatus) in
+ self.logRPCGroupPermissions(permissionElements: permissionElements, groupPermissionStatus: groupStatus, individualPermissionStatuses: individualStatuses)
})
return permissionAllAllowedObserverId
@@ -100,8 +108,8 @@ private extension RPCPermissionsManager {
/// - Parameters:
/// - rpcName: The name of the RPC
/// - isRPCAllowed: The permission status for the RPC
- class func logRPCPermission(rpcName: SDLRPCFunctionName, isRPCAllowed: Bool) {
- SDLLog.d("\(rpcName.rawValue.rawValue) RPC can be sent to SDL Core? \(isRPCAllowed ? "yes" : "no")")
+ class func logRPCPermission(status: SDLRPCPermissionStatus) {
+ SDLLog.d("\(status.rpcName.rawValue.rawValue) RPC can be sent to SDL Core? \(status.isRPCAllowed ? "YES" : "NO"), parameters: \(status.rpcParameters ?? [:])")
}
/// Logs permissions for a group of RPCs
@@ -110,10 +118,10 @@ private extension RPCPermissionsManager {
/// - rpcNames: The names of the RPCs
/// - groupPermissionStatus: The permission status for all RPCs in the group
/// - individualPermissionStatuses: The permission status for each of the RPCs in the group
- class func logRPCGroupPermissions(rpcNames: [SDLRPCFunctionName], groupPermissionStatus: SDLPermissionGroupStatus, individualPermissionStatuses: [SDLRPCFunctionName:NSNumber]) {
- SDLLog.d("The group status for \(rpcNames.map { $0.rawValue.rawValue } ) has changed to: \(groupPermissionStatus.rawValue)")
- for (rpcName, rpcAllowed) in individualPermissionStatuses {
- logRPCPermission(rpcName: rpcName, isRPCAllowed: rpcAllowed.boolValue)
+ class func logRPCGroupPermissions(permissionElements: [SDLPermissionElement], groupPermissionStatus: SDLPermissionGroupStatus, individualPermissionStatuses: [SDLRPCFunctionName: SDLRPCPermissionStatus]) {
+ SDLLog.d("The group status for \(permissionElements.map { $0.rpcName.rawValue } ) has changed to: \(groupPermissionStatus.rawValue)")
+ for (_, status) in individualPermissionStatuses {
+ logRPCPermission(status: status)
}
}
}