summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorleonid lokhmatov, Luxoft <zaqqqqqqqq@gmail.com>2020-12-22 03:20:42 +0200
committerleonid lokhmatov, Luxoft <zaqqqqqqqq@gmail.com>2020-12-22 03:20:42 +0200
commit9b3f1472c3466abdcf0d9710b440d9717146f0e3 (patch)
tree6d5deed86d6b8747395f757003a971b01df43a9b
parent4f663c5bd27ff282ee36ba544e89c88726f3ea70 (diff)
downloadsdl_ios-9b3f1472c3466abdcf0d9710b440d9717146f0e3.tar.gz
[0296] 'upd video stream cap': reset example app to develop (2)
-rw-r--r--Example Apps/Example ObjC/AlertManager.h24
-rw-r--r--Example Apps/Example ObjC/AlertManager.m43
-rw-r--r--Example Apps/Example ObjC/AudioManager.m5
-rw-r--r--Example Apps/Example ObjC/Base.lproj/ConnectionTCPTableViewController.storyboard84
-rw-r--r--Example Apps/Example ObjC/Base.lproj/Main.storyboard156
-rw-r--r--Example Apps/Example ObjC/ButtonManager.h2
-rw-r--r--Example Apps/Example ObjC/ButtonManager.m94
-rw-r--r--Example Apps/Example ObjC/ConnectionContainerViewController.m32
-rw-r--r--Example Apps/Example ObjC/ConnectionIAPTableViewController.h3
-rw-r--r--Example Apps/Example ObjC/ConnectionTCPTableViewController.h4
-rw-r--r--Example Apps/Example ObjC/ConnectionTCPTableViewController.m84
-rw-r--r--Example Apps/Example ObjC/ConnectionTransitionContext.m6
-rw-r--r--Example Apps/Example ObjC/ExampleApps/OldStyleApp/SimpleAppViewController.h20
-rw-r--r--Example Apps/Example ObjC/ExampleApps/OldStyleApp/SimpleAppViewController.m140
-rw-r--r--Example Apps/Example ObjC/ExampleApps/OldStyleApp/SimpleRootView.h19
-rw-r--r--Example Apps/Example ObjC/ExampleApps/OldStyleApp/SimpleRootView.m84
-rw-r--r--Example Apps/Example ObjC/ExampleApps/OldStyleApp/TouchModel.h19
-rw-r--r--Example Apps/Example ObjC/ExampleApps/OldStyleApp/TouchModel.m25
-rw-r--r--Example Apps/Example ObjC/ExampleApps/Resources/ExampleApps.storyboard409
-rw-r--r--Example Apps/Example ObjC/ExampleApps/Resources/art.scnassets/ship.scnbin0 -> 220179 bytes
-rw-r--r--Example Apps/Example ObjC/ExampleApps/Resources/art.scnassets/texture.pngbin0 -> 349666 bytes
-rw-r--r--Example Apps/Example ObjC/ExampleApps/SC3DApp/GameViewController.h15
-rw-r--r--Example Apps/Example ObjC/ExampleApps/SC3DApp/GameViewController.m192
-rw-r--r--Example Apps/Example ObjC/ExampleApps/UIApp/TestUIAppViewController.h18
-rw-r--r--Example Apps/Example ObjC/ExampleApps/UIApp/TestUIAppViewController.m153
-rw-r--r--Example Apps/Example ObjC/MenuManager.m36
-rw-r--r--Example Apps/Example ObjC/Models/SDLTCPConfig.h22
-rw-r--r--Example Apps/Example ObjC/Models/SDLTCPConfig.m25
-rw-r--r--Example Apps/Example ObjC/Models/VideoStreamSettings.h22
-rw-r--r--Example Apps/Example ObjC/Models/VideoStreamSettings.m18
-rw-r--r--Example Apps/Example ObjC/ProxyManager.h12
-rw-r--r--Example Apps/Example ObjC/ProxyManager.m190
-rw-r--r--Example Apps/Example ObjC/RPCPermissionsManager.m2
-rw-r--r--Example Apps/Example ObjC/SmartDeviceLink-Example-ObjC-Info.plist2
-rw-r--r--Example Apps/Example ObjC/VehicleDataManager.m31
-rw-r--r--Example Apps/Example Swift/AlertManager.swift60
-rw-r--r--Example Apps/Example Swift/AudioManager.swift13
-rw-r--r--Example Apps/Example Swift/ButtonManager.swift107
-rw-r--r--Example Apps/Example Swift/MenuManager.swift48
-rw-r--r--Example Apps/Example Swift/ProxyManager.swift17
-rw-r--r--Example Apps/Example Swift/VehicleDataManager.swift22
-rw-r--r--Example Apps/Shared/AppConstants.h32
-rw-r--r--Example Apps/Shared/AppConstants.m34
-rw-r--r--Example Apps/Shared/Images.xcassets/AppIcon.appiconset/Contents.json55
-rw-r--r--Example Apps/Shared/resources/sdl_video.mp4bin0 -> 1048 bytes
45 files changed, 1968 insertions, 411 deletions
diff --git a/Example Apps/Example ObjC/AlertManager.h b/Example Apps/Example ObjC/AlertManager.h
index d7b42b655..10508261a 100644
--- a/Example Apps/Example ObjC/AlertManager.h
+++ b/Example Apps/Example ObjC/AlertManager.h
@@ -9,26 +9,20 @@
#import <Foundation/Foundation.h>
@class SDLAlert;
-@class SDLManager;
-@class SDLSubtleAlert;
NS_ASSUME_NONNULL_BEGIN
@interface AlertManager : NSObject
-/// Sends an alert with up to two lines of text, an image, and a close button that will dismiss the alert when tapped.
-/// @param imageName The name of the image to upload
-/// @param textField1 The first line of text in the alert
-/// @param textField2 The second line of text in the alert
-/// @param sdlManager The SDLManager
-+ (void)sendAlertWithManager:(SDLManager *)sdlManager image:(nullable NSString *)imageName textField1:(NSString *)textField1 textField2:(nullable NSString *)textField2;
-
-/// Sends a subtle alert with up to two lines of text, and an image.
-/// @param imageName The name of the image to upload
-/// @param textField1 The first line of text in the alert
-/// @param textField2 The second line of text in the alert
-/// @param sdlManager The SDLManager
-+ (void)sendSubtleAlertWithManager:(SDLManager *)sdlManager image:(nullable NSString *)imageName textField1:(NSString *)textField1 textField2:(nullable NSString *)textField2;
+/**
+ Creates an alert with up to two lines of text, an image, and a close button that will dismiss the alert when tapped.
+
+ @param textField1 The first line of the message to display in the alert
+ @param textField2 The second line of the message to display in the alert
+ @param iconName An image to show in the alert.
+ @return An SDLAlert object
+ */
++ (SDLAlert *)alertWithMessageAndCloseButton:(NSString *)textField1 textField2:(nullable NSString *)textField2 iconName:(nullable NSString *)iconName;
@end
diff --git a/Example Apps/Example ObjC/AlertManager.m b/Example Apps/Example ObjC/AlertManager.m
index df902dc0a..3efbba544 100644
--- a/Example Apps/Example ObjC/AlertManager.m
+++ b/Example Apps/Example ObjC/AlertManager.m
@@ -14,47 +14,12 @@ NS_ASSUME_NONNULL_BEGIN
@implementation AlertManager
-+ (void)sendAlertWithManager:(SDLManager *)sdlManager image:(nullable NSString *)imageName textField1:(NSString *)textField1 textField2:(nullable NSString *)textField2 {
- SDLSoftButton *okSoftButton = [[SDLSoftButton alloc] initWithType:SDLSoftButtonTypeText text:AlertOKButtonText image:nil highlighted:YES buttonId:10000 systemAction:nil handler:nil];
- SDLAlert *alert = [[SDLAlert alloc] initWithAlertText1:textField1 alertText2:textField2 alertText3:nil softButtons:@[okSoftButton] playTone:YES ttsChunks:nil duration:5000 progressIndicator:NO alertIcon:nil cancelID:0];
-
- if (imageName == nil) {
- [sdlManager sendRequest:alert];
- } else {
- [self sdlex_sendImageWithName:imageName sdlManager:sdlManager completionHandler:^(BOOL success, NSString * _Nullable artworkName) {
- if (success) {
- alert.alertIcon = [[SDLImage alloc] initWithName:artworkName isTemplate:YES];
- }
- [sdlManager sendRequest:alert];
- }];
- }
++ (SDLSoftButton *)sdlex_okSoftButton {
+ return [[SDLSoftButton alloc] initWithType:SDLSoftButtonTypeText text:AlertOKButtonText image:nil highlighted:YES buttonId:1 systemAction:nil handler:nil];
}
-+ (void)sendSubtleAlertWithManager:(SDLManager *)sdlManager image:(nullable NSString *)imageName textField1:(NSString *)textField1 textField2:(nullable NSString *)textField2 {
- SDLSubtleAlert *subtleAlert = [[SDLSubtleAlert alloc] initWithAlertText1:textField1 alertText2:textField2 alertIcon:nil ttsChunks:nil duration:nil softButtons:nil cancelID:0];
-
- if (imageName == nil) {
- [sdlManager sendRequest:subtleAlert];
- } else {
- [self sdlex_sendImageWithName:imageName sdlManager:sdlManager completionHandler:^(BOOL success, NSString * _Nullable artworkName) {
- if (success) {
- subtleAlert.alertIcon = [[SDLImage alloc] initWithName:artworkName isTemplate:YES];
- }
- [sdlManager sendRequest:subtleAlert];
- }];
- }
-}
-
-/// Helper method for uploading an image before it is shown in an alert
-/// @param imageName The name of the image to upload
-/// @param sdlManager The SDLManager
-/// @param completionHandler Handler called when the artwork has finished uploading with the success of the upload and the name of the uploaded image.
-+ (void)sdlex_sendImageWithName:(NSString *)imageName sdlManager:(SDLManager *)sdlManager completionHandler:(void (^)(BOOL success, NSString * _Nonnull artworkName))completionHandler {
- SDLArtwork *artwork = [SDLArtwork artworkWithImage:[[UIImage imageNamed:imageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG];
-
- [sdlManager.fileManager uploadArtwork:artwork completionHandler:^(BOOL success, NSString * _Nonnull artworkName, NSUInteger bytesAvailable, NSError * _Nullable error) {
- return completionHandler(success, artworkName);
- }];
++ (SDLAlert *)alertWithMessageAndCloseButton:(NSString *)textField1 textField2:(nullable NSString *)textField2 iconName:(nullable NSString *)iconName {
+ return [[SDLAlert alloc] initWithAlertText1:textField1 alertText2:textField2 alertText3:nil softButtons:@[[self.class sdlex_okSoftButton]] playTone:YES ttsChunks:nil duration:5000 progressIndicator:NO alertIcon:((iconName != nil) ? [[SDLImage alloc] initWithName:iconName isTemplate:YES] : nil) cancelID:0];
}
@end
diff --git a/Example Apps/Example ObjC/AudioManager.m b/Example Apps/Example ObjC/AudioManager.m
index dc1c77e41..cd6ec4ecf 100644
--- a/Example Apps/Example ObjC/AudioManager.m
+++ b/Example Apps/Example ObjC/AudioManager.m
@@ -7,7 +7,6 @@
//
#import "AlertManager.h"
-#import "AppConstants.h"
#import "AudioManager.h"
#import <AVFoundation/AVFoundation.h>
#import "SDLLogMacros.h"
@@ -87,7 +86,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)startRecording {
if (self.speechRecognitionAuthState != SpeechRecognitionAuthStateAuthorized) {
SDLLogW(@"This app does not have permission to access the Speech Recognition API");
- [AlertManager sendAlertWithManager:self.sdlManager image:nil textField1:AlertSpeechPermissionsWarningText textField2:nil];
+ [self.sdlManager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"You must give this app permission to access Speech Recognition" textField2:nil iconName:nil]];
return;
}
@@ -156,7 +155,7 @@ NS_ASSUME_NONNULL_BEGIN
// The `PerformAudioPassThru` timed out or the "Done" button was pressed in the pop-up.
SDLLogD(@"Audio Pass Thru ended successfully");
NSString *alertMessage = [NSString stringWithFormat:@"You said: %@", weakSelf.speechTranscription.length == 0 ? @"No speech detected" : weakSelf.speechTranscription];
- [AlertManager sendAlertWithManager:weakSelf.sdlManager image:nil textField1:alertMessage textField2:nil];
+ [weakSelf.sdlManager sendRequest:[AlertManager alertWithMessageAndCloseButton:alertMessage textField2:nil iconName:nil]];
} else if ([resultCode isEqualToEnum:SDLResultAborted]) {
// The "Cancel" button was pressed in the pop-up. Ignore this audio pass thru.
SDLLogD(@"Audio recording canceled");
diff --git a/Example Apps/Example ObjC/Base.lproj/ConnectionTCPTableViewController.storyboard b/Example Apps/Example ObjC/Base.lproj/ConnectionTCPTableViewController.storyboard
index e1b51b744..408c4710f 100644
--- a/Example Apps/Example ObjC/Base.lproj/ConnectionTCPTableViewController.storyboard
+++ b/Example Apps/Example ObjC/Base.lproj/ConnectionTCPTableViewController.storyboard
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15400" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="l5Q-ZP-1BO">
- <device id="retina4_7" orientation="portrait" appearance="light"/>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="l5Q-ZP-1BO">
+ <device id="retina4_0" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15404"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15510"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@@ -12,26 +12,46 @@
<objects>
<tableViewController id="l5Q-ZP-1BO" customClass="ConnectionTCPTableViewController" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="10" sectionFooterHeight="10" id="7ZH-AV-Zyf">
- <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
+ <view key="tableHeaderView" contentMode="scaleToFill" id="K0C-tf-9HD">
+ <rect key="frame" x="0.0" y="0.0" width="320" height="64"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <subviews>
+ <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" text="SDL 0296 - Possibility to update video streaming capabilities during ignition cycle #983" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="56Z-nY-c4O">
+ <rect key="frame" x="10" y="0.0" width="300" height="64"/>
+ <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+ <color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <fontDescription key="fontDescription" type="system" pointSize="14"/>
+ <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
+ </textView>
+ </subviews>
+ <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+ <constraints>
+ <constraint firstItem="56Z-nY-c4O" firstAttribute="top" secondItem="K0C-tf-9HD" secondAttribute="top" id="3ro-an-naY"/>
+ <constraint firstAttribute="trailing" secondItem="56Z-nY-c4O" secondAttribute="trailing" constant="10" id="6CV-0Q-rz0"/>
+ <constraint firstItem="56Z-nY-c4O" firstAttribute="leading" secondItem="K0C-tf-9HD" secondAttribute="leading" constant="10" id="9q0-VD-QET"/>
+ <constraint firstAttribute="bottom" secondItem="56Z-nY-c4O" secondAttribute="bottom" id="gwe-YJ-Lis"/>
+ </constraints>
+ </view>
<sections>
<tableViewSection headerTitle="TCP Server" id="bF6-yi-Ial">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="pbJ-oz-jNt">
- <rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
+ <rect key="frame" x="0.0" y="119.5" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="pbJ-oz-jNt" id="B7X-yY-lwJ">
- <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
+ <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
- <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="IP Address" clearsOnBeginEditing="YES" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="xqM-s4-9RV">
- <rect key="frame" x="16" y="0.0" width="343" height="44"/>
+ <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="IP Address" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="xqM-s4-9RV">
+ <rect key="frame" x="16" y="0.0" width="288" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="5Pw-mh-x83"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
- <textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" keyboardType="URL"/>
+ <textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" keyboardType="URL" smartDashesType="no" smartInsertDeleteType="no" textContentType="url"/>
</textField>
</subviews>
<constraints>
@@ -42,14 +62,14 @@
</tableViewCellContentView>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="C5b-fS-v3d">
- <rect key="frame" x="0.0" y="99.5" width="375" height="44"/>
+ <rect key="frame" x="0.0" y="163.5" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="C5b-fS-v3d" id="ZD4-xA-og5">
- <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
+ <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Port" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="hsI-ld-8xY">
- <rect key="frame" x="16" y="0.0" width="343" height="44"/>
+ <rect key="frame" x="16" y="0.0" width="288" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="FpG-5e-MHT"/>
</constraints>
@@ -66,17 +86,45 @@
</tableViewCell>
</cells>
</tableViewSection>
- <tableViewSection headerTitle="" id="rgl-Lm-uDH">
+ <tableViewSection headerTitle="App Kind" id="BPB-8S-l9t">
+ <cells>
+ <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="2JT-t9-quM" userLabel="play start/stop cell">
+ <rect key="frame" x="0.0" y="255.5" width="320" height="44"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="2JT-t9-quM" id="hlo-ge-ada">
+ <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <segmentedControl hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="UDP-rT-hdx">
+ <rect key="frame" x="10" y="0.0" width="300" height="45"/>
+ <segments>
+ <segment title="UI app"/>
+ <segment title="No UI app"/>
+ <segment title="(3D app)"/>
+ </segments>
+ </segmentedControl>
+ </subviews>
+ <constraints>
+ <constraint firstItem="UDP-rT-hdx" firstAttribute="leading" secondItem="hlo-ge-ada" secondAttribute="leading" constant="10" id="HCu-x2-J5S"/>
+ <constraint firstItem="UDP-rT-hdx" firstAttribute="top" secondItem="hlo-ge-ada" secondAttribute="top" id="HOn-tt-p8n"/>
+ <constraint firstAttribute="trailing" secondItem="UDP-rT-hdx" secondAttribute="trailing" constant="10" id="J9p-0A-FLN"/>
+ <constraint firstAttribute="bottom" secondItem="UDP-rT-hdx" secondAttribute="bottom" id="sG7-4A-xYp"/>
+ </constraints>
+ </tableViewCellContentView>
+ </tableViewCell>
+ </cells>
+ </tableViewSection>
+ <tableViewSection headerTitle="Connection Control" id="rgl-Lm-uDH" userLabel="Connect Section">
<cells>
- <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="ybX-Eh-Hbx">
- <rect key="frame" x="0.0" y="175.5" width="375" height="44"/>
+ <tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" id="ybX-Eh-Hbx" userLabel="Connect Cell">
+ <rect key="frame" x="0.0" y="347.5" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ybX-Eh-Hbx" id="uI9-fK-205">
- <rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
+ <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="t37-4W-6F4">
- <rect key="frame" x="16" y="0.0" width="343" height="44"/>
+ <rect key="frame" x="16" y="0.0" width="288" height="44"/>
<fontDescription key="fontDescription" type="system" pointSize="23"/>
<state key="normal" title="Connect">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -98,7 +146,6 @@
</tableViewSection>
</sections>
<connections>
- <outlet property="dataSource" destination="l5Q-ZP-1BO" id="kIY-aI-9y3"/>
<outlet property="delegate" destination="l5Q-ZP-1BO" id="nhW-OL-xIC"/>
</connections>
</tableView>
@@ -114,6 +161,7 @@
</segmentedControl>
</navigationItem>
<connections>
+ <outlet property="appSelector" destination="UDP-rT-hdx" id="fgT-Pk-aAM"/>
<outlet property="connectButton" destination="t37-4W-6F4" id="f6v-Q4-ggs"/>
<outlet property="connectTableViewCell" destination="ybX-Eh-Hbx" id="hyh-CW-oXx"/>
<outlet property="ipAddressTextField" destination="xqM-s4-9RV" id="daz-uN-Rxa"/>
diff --git a/Example Apps/Example ObjC/Base.lproj/Main.storyboard b/Example Apps/Example ObjC/Base.lproj/Main.storyboard
index 8097692ff..a3aa3eba6 100644
--- a/Example Apps/Example ObjC/Base.lproj/Main.storyboard
+++ b/Example Apps/Example ObjC/Base.lproj/Main.storyboard
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15400" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="mM3-m6-I5t">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="mM3-m6-I5t">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15404"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15510"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@@ -40,7 +40,7 @@
</view>
<navigationItem key="navigationItem" id="t1a-s2-nn6">
<nil key="title"/>
- <segmentedControl key="titleView" opaque="NO" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bar" selectedSegmentIndex="0" id="RYa-fE-Qek">
+ <segmentedControl key="titleView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bar" selectedSegmentIndex="0" id="RYa-fE-Qek">
<rect key="frame" x="67.5" y="6" width="240" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<segments>
@@ -51,6 +51,12 @@
<action selector="connectionTypeSegmentedControlSelectedIndexDidChange:" destination="cXb-Co-0MA" eventType="valueChanged" id="i3j-Ux-1be"/>
</connections>
</segmentedControl>
+ <barButtonItem key="rightBarButtonItem" systemItem="add" id="9Rv-u2-0S2">
+ <connections>
+ <action selector="actionEditSettings:" destination="cXb-Co-0MA" id="78X-Bm-9yk"/>
+ <segue destination="TxX-lo-zc5" kind="show" id="eSU-M4-H76"/>
+ </connections>
+ </barButtonItem>
</navigationItem>
<connections>
<outlet property="connectionTypeSegmentedControl" destination="RYa-fE-Qek" id="uda-9c-u0v"/>
@@ -60,5 +66,149 @@
</objects>
<point key="canvasLocation" x="1576" y="527"/>
</scene>
+ <!--Video Streaming Settings View Controller-->
+ <scene sceneID="tg7-tb-BYA">
+ <objects>
+ <viewController id="TxX-lo-zc5" customClass="VideoStreamingSettingsViewController" sceneMemberID="viewController">
+ <layoutGuides>
+ <viewControllerLayoutGuide type="top" id="C8G-fd-nHI"/>
+ <viewControllerLayoutGuide type="bottom" id="K4R-Z3-gZY"/>
+ </layoutGuides>
+ <view key="view" contentMode="scaleToFill" id="XWV-NZ-vfh">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="b9p-UF-1rG">
+ <rect key="frame" x="16" y="87" width="343" height="70"/>
+ <subviews>
+ <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="9hG-1Z-Ssk">
+ <rect key="frame" x="222" y="19.5" width="101" height="32"/>
+ <segments>
+ <segment title="6.2.0"/>
+ <segment title="7.0.0"/>
+ </segments>
+ <connections>
+ <action selector="actionSwitchSDLVersion:" destination="TxX-lo-zc5" eventType="valueChanged" id="v3e-s2-47S"/>
+ </connections>
+ </segmentedControl>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="SDL Version:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gf3-VA-YQe">
+ <rect key="frame" x="20" y="0.0" width="98" height="70"/>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <color key="backgroundColor" systemColor="separatorColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.28999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
+ <constraints>
+ <constraint firstItem="gf3-VA-YQe" firstAttribute="leading" secondItem="b9p-UF-1rG" secondAttribute="leading" constant="20" id="KrA-3y-4WS"/>
+ <constraint firstAttribute="height" constant="70" id="WoQ-jt-tIN"/>
+ <constraint firstItem="9hG-1Z-Ssk" firstAttribute="centerY" secondItem="b9p-UF-1rG" secondAttribute="centerY" id="c5c-jz-Gr1"/>
+ <constraint firstAttribute="trailing" secondItem="9hG-1Z-Ssk" secondAttribute="trailing" constant="20" id="cfj-Hn-X7O"/>
+ <constraint firstAttribute="bottom" secondItem="gf3-VA-YQe" secondAttribute="bottom" id="mT9-YN-xAE"/>
+ <constraint firstItem="gf3-VA-YQe" firstAttribute="top" secondItem="b9p-UF-1rG" secondAttribute="top" id="yuk-Vi-zRa"/>
+ </constraints>
+ </view>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fPY-dT-PPs" userLabel="View- Landscape">
+ <rect key="frame" x="16" y="177" width="343" height="90"/>
+ <subviews>
+ <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="DLo-aT-RSg">
+ <rect key="frame" x="204" y="29.5" width="119" height="32"/>
+ <segments>
+ <segment title="-1-"/>
+ <segment title="-2-"/>
+ <segment title="-3-"/>
+ </segments>
+ <connections>
+ <action selector="actionSwitchLandscapePreset:" destination="TxX-lo-zc5" eventType="valueChanged" id="Hdb-zg-egn"/>
+ </connections>
+ </segmentedControl>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Supported Landscape Streaming Range" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="KLP-Lq-BPg">
+ <rect key="frame" x="20" y="0.0" width="120" height="90"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="120" id="Tg7-6n-s16"/>
+ </constraints>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <color key="backgroundColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="90" id="75N-Gv-91y"/>
+ <constraint firstItem="KLP-Lq-BPg" firstAttribute="leading" secondItem="fPY-dT-PPs" secondAttribute="leading" constant="20" id="GjN-Eq-wlI"/>
+ <constraint firstAttribute="trailing" secondItem="DLo-aT-RSg" secondAttribute="trailing" constant="20" id="OUc-Wt-NFJ"/>
+ <constraint firstItem="DLo-aT-RSg" firstAttribute="centerY" secondItem="fPY-dT-PPs" secondAttribute="centerY" id="oC1-oF-asm"/>
+ <constraint firstAttribute="bottom" secondItem="KLP-Lq-BPg" secondAttribute="bottom" id="r5D-hx-oe8"/>
+ <constraint firstItem="KLP-Lq-BPg" firstAttribute="top" secondItem="fPY-dT-PPs" secondAttribute="top" id="s2p-jm-Jf7"/>
+ </constraints>
+ </view>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="B0H-J8-cLN" userLabel="View- Portrait">
+ <rect key="frame" x="16" y="287" width="343" height="90"/>
+ <subviews>
+ <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="GTs-nd-ywV">
+ <rect key="frame" x="204" y="29.5" width="119" height="32"/>
+ <segments>
+ <segment title="-1-"/>
+ <segment title="-2-"/>
+ <segment title="-3-"/>
+ </segments>
+ <connections>
+ <action selector="actionSwitchPortraitPreset:" destination="TxX-lo-zc5" eventType="valueChanged" id="Ewh-2D-plg"/>
+ </connections>
+ </segmentedControl>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Supported Portrait Streaming Range" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="n7R-QE-aoE">
+ <rect key="frame" x="20" y="0.0" width="120" height="90"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="120" id="6xi-uH-Qdq"/>
+ </constraints>
+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <color key="backgroundColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstItem="GTs-nd-ywV" firstAttribute="centerY" secondItem="B0H-J8-cLN" secondAttribute="centerY" id="Gtq-go-oE6"/>
+ <constraint firstAttribute="bottom" secondItem="n7R-QE-aoE" secondAttribute="bottom" id="WbG-G1-87z"/>
+ <constraint firstItem="n7R-QE-aoE" firstAttribute="leading" secondItem="B0H-J8-cLN" secondAttribute="leading" constant="20" id="Yep-eM-HA0"/>
+ <constraint firstItem="n7R-QE-aoE" firstAttribute="top" secondItem="B0H-J8-cLN" secondAttribute="top" id="gNl-yU-u6g"/>
+ <constraint firstAttribute="trailing" secondItem="GTs-nd-ywV" secondAttribute="trailing" constant="20" id="jW3-yY-jMu"/>
+ <constraint firstAttribute="height" constant="90" id="l5z-ks-kiE"/>
+ </constraints>
+ </view>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="description" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="74B-cS-mfh">
+ <rect key="frame" x="16" y="397" width="343" height="265"/>
+ <fontDescription key="fontDescription" type="system" pointSize="14"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+ <constraints>
+ <constraint firstItem="b9p-UF-1rG" firstAttribute="leading" secondItem="XWV-NZ-vfh" secondAttribute="leadingMargin" id="11c-kD-JD7"/>
+ <constraint firstItem="b9p-UF-1rG" firstAttribute="top" secondItem="C8G-fd-nHI" secondAttribute="bottom" constant="43" id="2D5-5C-7mX"/>
+ <constraint firstItem="K4R-Z3-gZY" firstAttribute="top" secondItem="74B-cS-mfh" secondAttribute="bottom" constant="5" id="9gJ-Su-CvP"/>
+ <constraint firstItem="b9p-UF-1rG" firstAttribute="trailing" secondItem="XWV-NZ-vfh" secondAttribute="trailingMargin" id="D4O-wU-6vR"/>
+ <constraint firstItem="fPY-dT-PPs" firstAttribute="top" secondItem="b9p-UF-1rG" secondAttribute="bottom" constant="20" id="WDe-X9-b6l"/>
+ <constraint firstItem="B0H-J8-cLN" firstAttribute="top" secondItem="fPY-dT-PPs" secondAttribute="bottom" constant="20" id="dfZ-96-yLq"/>
+ <constraint firstItem="fPY-dT-PPs" firstAttribute="trailing" secondItem="XWV-NZ-vfh" secondAttribute="trailingMargin" id="jgt-l2-889"/>
+ <constraint firstItem="B0H-J8-cLN" firstAttribute="trailing" secondItem="XWV-NZ-vfh" secondAttribute="trailingMargin" id="lKp-51-s5Q"/>
+ <constraint firstItem="B0H-J8-cLN" firstAttribute="leading" secondItem="XWV-NZ-vfh" secondAttribute="leadingMargin" id="mIX-AH-Z6q"/>
+ <constraint firstAttribute="trailingMargin" secondItem="74B-cS-mfh" secondAttribute="trailing" id="oGj-3r-cP9"/>
+ <constraint firstItem="74B-cS-mfh" firstAttribute="top" secondItem="B0H-J8-cLN" secondAttribute="bottom" constant="20" id="oWO-8I-1f9"/>
+ <constraint firstItem="74B-cS-mfh" firstAttribute="leading" secondItem="XWV-NZ-vfh" secondAttribute="leadingMargin" id="t6K-d2-3M3"/>
+ <constraint firstItem="fPY-dT-PPs" firstAttribute="leading" secondItem="XWV-NZ-vfh" secondAttribute="leadingMargin" id="yra-tt-vSX"/>
+ </constraints>
+ </view>
+ <navigationItem key="navigationItem" id="rI9-fr-Fma"/>
+ <connections>
+ <outlet property="labDescription" destination="74B-cS-mfh" id="1Dr-Eu-E3A"/>
+ <outlet property="toggleSDLVersion" destination="9hG-1Z-Ssk" id="gFQ-CR-tPt"/>
+ </connections>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="d7T-33-tPr" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="2336.8000000000002" y="513.19340329835086"/>
+ </scene>
</scenes>
</document>
diff --git a/Example Apps/Example ObjC/ButtonManager.h b/Example Apps/Example ObjC/ButtonManager.h
index 256ea8ee4..867f50c7c 100644
--- a/Example Apps/Example ObjC/ButtonManager.h
+++ b/Example Apps/Example ObjC/ButtonManager.h
@@ -18,12 +18,12 @@ typedef void(^RefreshUIHandler)(void);
@interface ButtonManager : NSObject
@property (assign, nonatomic, getter=isTextEnabled, readonly) BOOL textEnabled;
+@property (assign, nonatomic, getter=isHexagonEnabled, readonly) BOOL toggleEnabled;
@property (assign, nonatomic, getter=areImagesEnabled, readonly) BOOL imagesEnabled;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithManager:(SDLManager *)manager refreshUIHandler:(RefreshUIHandler)refreshUIHandler;
-/// An array of all the soft buttons
- (NSArray<SDLSoftButtonObject *> *)allScreenSoftButtons;
@end
diff --git a/Example Apps/Example ObjC/ButtonManager.m b/Example Apps/Example ObjC/ButtonManager.m
index 4ca86be0a..1809249db 100644
--- a/Example Apps/Example ObjC/ButtonManager.m
+++ b/Example Apps/Example ObjC/ButtonManager.m
@@ -19,6 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (strong, nonatomic) SDLManager *sdlManager;
@property (assign, nonatomic, getter=isTextEnabled, readwrite) BOOL textEnabled;
+@property (assign, nonatomic, getter=isHexagonEnabled, readwrite) BOOL toggleEnabled;
@property (assign, nonatomic, getter=areImagesEnabled, readwrite) BOOL imagesEnabled;
@end
@@ -36,6 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
_textEnabled = YES;
_imagesEnabled = YES;
+ _toggleEnabled = YES;
return self;
}
@@ -50,73 +52,61 @@ NS_ASSUME_NONNULL_BEGIN
- (void)setImagesEnabled:(BOOL)imagesEnabled {
_imagesEnabled = imagesEnabled;
- if (self.refreshUIHandler == nil) { return; }
- self.refreshUIHandler();
-}
-#pragma mark - Getters
+ SDLSoftButtonObject *object = [self.sdlManager.screenManager softButtonObjectNamed:AlertSoftButton];
+ [object transitionToNextState];
-- (BOOL)sdlex_isSubtleAlertAllowed {
- return [self.sdlManager.permissionManager isRPCNameAllowed:SDLRPCFunctionNameSubtleAlert];
+ if (self.refreshUIHandler == nil) { return; }
+ self.refreshUIHandler();
}
-- (BOOL)sdlex_isAlertAllowed {
- return [self.sdlManager.permissionManager isRPCNameAllowed:SDLRPCFunctionNameAlert];
+- (void)setToggleEnabled:(BOOL)toggleEnabled {
+ _toggleEnabled = toggleEnabled;
+ SDLSoftButtonObject *object = [self.sdlManager.screenManager softButtonObjectNamed:ToggleSoftButton];
+ [object transitionToStateNamed:(toggleEnabled ? ToggleSoftButtonImageOnState : ToggleSoftButtonImageOffState)];
}
#pragma mark - Custom Soft Buttons
- (NSArray<SDLSoftButtonObject *> *)allScreenSoftButtons {
- return @[[self sdlex_softButtonAlert], [self sdlex_softButtonSubtleAlert], [self sdlex_softButtonTextVisible], [self sdlex_softButtonImagesVisible]];
+ return @[[self sdlex_softButtonAlertWithManager:self.sdlManager], [self sdlex_softButtonToggleWithManager:self.sdlManager], [self sdlex_softButtonTextVisibleWithManager:self.sdlManager], [self sdlex_softButtonImagesVisibleWithManager:self.sdlManager]];
}
-/// Returns a soft button that shows an alert when tapped.
-/// @returns A SDLSoftButtonObject object
-- (SDLSoftButtonObject *)sdlex_softButtonAlert {
- SDLSoftButtonState *imageAndTextState = [[SDLSoftButtonState alloc] initWithStateName:AlertSoftButtonImageAndTextState text:AlertSoftButtonText artwork:[SDLArtwork artworkWithImage:[[UIImage imageNamed:AlertBWIconName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG]];
- SDLSoftButtonState *textState = [[SDLSoftButtonState alloc] initWithStateName:AlertSoftButtonTextState text:AlertSoftButtonText image:nil];
+- (SDLSoftButtonObject *)sdlex_softButtonAlertWithManager:(SDLManager *)manager {
+ SDLSoftButtonState *alertImageAndTextState = [[SDLSoftButtonState alloc] initWithStateName:AlertSoftButtonImageState text:AlertSoftButtonText artwork:[SDLArtwork artworkWithImage:[[UIImage imageNamed:CarBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] name:CarBWIconImageName asImageFormat:SDLArtworkImageFormatPNG]];
+ SDLSoftButtonState *alertTextState = [[SDLSoftButtonState alloc] initWithStateName:AlertSoftButtonTextState text:AlertSoftButtonText image:nil];
__weak typeof(self) weakself = self;
- SDLSoftButtonObject *alertSoftButton = [[SDLSoftButtonObject alloc] initWithName:AlertSoftButton states:@[imageAndTextState, textState] initialStateName:imageAndTextState.name handler:^(SDLOnButtonPress * _Nullable buttonPress, SDLOnButtonEvent * _Nullable buttonEvent) {
+ SDLSoftButtonObject *alertSoftButton = [[SDLSoftButtonObject alloc] initWithName:AlertSoftButton states:@[alertImageAndTextState, alertTextState] initialStateName:alertImageAndTextState.name handler:^(SDLOnButtonPress * _Nullable buttonPress, SDLOnButtonEvent * _Nullable buttonEvent) {
if (buttonPress == nil) { return; }
- if (self.sdlex_isAlertAllowed) {
- [AlertManager sendAlertWithManager:weakself.sdlManager image:CarBWIconImageName textField1:AlertMessageText textField2:nil];
- } else if (self.sdlex_isSubtleAlertAllowed) {
- [AlertManager sendSubtleAlertWithManager:weakself.sdlManager image:CarBWIconImageName textField1:AlertMessageText textField2:nil];
- } else {
- SDLLogW(@"The module does not support the Alert request or the Subtle Alert request");
- }
+ [weakself.sdlManager.fileManager uploadArtwork:[SDLArtwork artworkWithImage:[UIImage imageNamed:CarBWIconImageName] asImageFormat:SDLArtworkImageFormatPNG] completionHandler:^(BOOL success, NSString * _Nonnull artworkName, NSUInteger bytesAvailable, NSError * _Nullable error) {
+ [weakself.sdlManager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"You pushed the soft button!" textField2:nil iconName:artworkName] withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) {
+ NSLog(@"ALERT req: %@, res: %@, err: %@", request, response, error);
+ }];
+ }];
+
+ SDLLogD(@"Star icon soft button press fired");
}];
return alertSoftButton;
}
-/// Returns a soft button that shows a subtle alert when tapped. If the subtle alert is not supported, then a regular alert is shown.
-/// @returns A SDLSoftButtonObject object
-- (SDLSoftButtonObject *)sdlex_softButtonSubtleAlert {
- SDLSoftButtonState *imageAndTextState = [[SDLSoftButtonState alloc] initWithStateName:SubtleAlertSoftButtonImageAndTextState text:SubtleAlertSoftButtonText artwork:[SDLArtwork artworkWithImage:[[UIImage imageNamed:BatteryFullBWIconName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG]];
- SDLSoftButtonState *textState = [[SDLSoftButtonState alloc] initWithStateName:SubtleAlertSoftButtonTextState text:SubtleAlertSoftButtonText image:nil];
+- (SDLSoftButtonObject *)sdlex_softButtonToggleWithManager:(SDLManager *)manager {
+ SDLSoftButtonState *toggleImageOnState = [[SDLSoftButtonState alloc] initWithStateName:ToggleSoftButtonImageOnState text:nil image:[[UIImage imageNamed:ToggleOnBWIconName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];
+ SDLSoftButtonState *toggleImageOffState = [[SDLSoftButtonState alloc] initWithStateName:ToggleSoftButtonImageOffState text:nil image:[[UIImage imageNamed:ToggleOffBWIconName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]];
__weak typeof(self) weakself = self;
- SDLSoftButtonObject *subtleAlertSoftButton = [[SDLSoftButtonObject alloc] initWithName:SubtleAlertSoftButton states:@[imageAndTextState, textState] initialStateName:imageAndTextState.name handler:^(SDLOnButtonPress * _Nullable buttonPress, SDLOnButtonEvent * _Nullable buttonEvent) {
+ SDLSoftButtonObject *toggleButton = [[SDLSoftButtonObject alloc] initWithName:ToggleSoftButton states:@[toggleImageOnState, toggleImageOffState] initialStateName:toggleImageOnState.name handler:^(SDLOnButtonPress * _Nullable buttonPress, SDLOnButtonEvent * _Nullable buttonEvent) {
if (buttonPress == nil) { return; }
-
- if (self.sdlex_isSubtleAlertAllowed) {
- [AlertManager sendSubtleAlertWithManager:weakself.sdlManager image:BatteryEmptyBWIconName textField1:SubtleAlertHeaderText textField2:SubtleAlertSubheaderText];
- } else if (self.sdlex_isAlertAllowed) {
- [AlertManager sendAlertWithManager:weakself.sdlManager image:BatteryEmptyBWIconName textField1:SubtleAlertHeaderText textField2:SubtleAlertSubheaderText];
- } else {
- SDLLogW(@"The module does not support the Alert request or the Subtle Alert request");
- }
+ weakself.toggleEnabled = !weakself.toggleEnabled;
+ SDLLogD(@"Toggle icon button press fired %d", self.toggleEnabled);
}];
- return subtleAlertSoftButton;
+ return toggleButton;
}
-/// Returns a soft button that toggles the textfield visibility state.
-/// @returns A SDLSoftButtonObject object
-- (SDLSoftButtonObject *)sdlex_softButtonTextVisible {
+- (SDLSoftButtonObject *)sdlex_softButtonTextVisibleWithManager:(SDLManager *)manager {
SDLSoftButtonState *textOnState = [[SDLSoftButtonState alloc] initWithStateName:TextVisibleSoftButtonTextOnState text:TextVisibleSoftButtonTextOnText image:nil];
SDLSoftButtonState *textOffState = [[SDLSoftButtonState alloc] initWithStateName:TextVisibleSoftButtonTextOffState text:TextVisibleSoftButtonTextOffText image:nil];
@@ -125,34 +115,34 @@ NS_ASSUME_NONNULL_BEGIN
if (buttonPress == nil) { return; }
weakself.textEnabled = !weakself.textEnabled;
+ SDLSoftButtonObject *object = [weakself.sdlManager.screenManager softButtonObjectNamed:TextVisibleSoftButton];
+ [object transitionToNextState];
- SDLSoftButtonObject *textVisibleSoftButton = [weakself.sdlManager.screenManager softButtonObjectNamed:TextVisibleSoftButton];
- [textVisibleSoftButton transitionToNextState];
+ SDLLogD(@"Text visibility soft button press fired %d", weakself.textEnabled);
}];
return textButton;
}
-/// Returns a soft button that toggles the image visibility state.
-/// @returns A SDLSoftButtonObject object
-- (SDLSoftButtonObject *)sdlex_softButtonImagesVisible {
+- (SDLSoftButtonObject *)sdlex_softButtonImagesVisibleWithManager:(SDLManager *)manager {
SDLSoftButtonState *imagesOnState = [[SDLSoftButtonState alloc] initWithStateName:ImagesVisibleSoftButtonImageOnState text:ImagesVisibleSoftButtonImageOnText image:nil];
SDLSoftButtonState *imagesOffState = [[SDLSoftButtonState alloc] initWithStateName:ImagesVisibleSoftButtonImageOffState text:ImagesVisibleSoftButtonImageOffText image:nil];
__weak typeof(self) weakself = self;
SDLSoftButtonObject *imagesButton = [[SDLSoftButtonObject alloc] initWithName:ImagesVisibleSoftButton states:@[imagesOnState, imagesOffState] initialStateName:imagesOnState.name handler:^(SDLOnButtonPress * _Nullable buttonPress, SDLOnButtonEvent * _Nullable buttonEvent) {
- if (buttonPress == nil) { return; }
+ if (buttonPress == nil) {
+ return;
+ }
weakself.imagesEnabled = !weakself.imagesEnabled;
- SDLSoftButtonObject *imagesVisibleSoftButton = [weakself.sdlManager.screenManager softButtonObjectNamed:ImagesVisibleSoftButton];
- [imagesVisibleSoftButton transitionToNextState];
+ SDLSoftButtonObject *object = [weakself.sdlManager.screenManager softButtonObjectNamed:ImagesVisibleSoftButton];
+ [object transitionToNextState];
- SDLSoftButtonObject *alertSoftButton = [weakself.sdlManager.screenManager softButtonObjectNamed:AlertSoftButton];
- [alertSoftButton transitionToNextState];
+ SDLSoftButtonObject *textButton = [weakself.sdlManager.screenManager softButtonObjectNamed:TextVisibleSoftButton];
+ [textButton transitionToNextState];
- SDLSoftButtonObject *subtleAlertSoftButton = [weakself.sdlManager.screenManager softButtonObjectNamed:SubtleAlertSoftButton];
- [subtleAlertSoftButton transitionToNextState];
+ SDLLogD(@"Image visibility soft button press fired %d", weakself.imagesEnabled);
}];
return imagesButton;
diff --git a/Example Apps/Example ObjC/ConnectionContainerViewController.m b/Example Apps/Example ObjC/ConnectionContainerViewController.m
index 6075ccc8b..7d03e8b0f 100644
--- a/Example Apps/Example ObjC/ConnectionContainerViewController.m
+++ b/Example Apps/Example ObjC/ConnectionContainerViewController.m
@@ -9,6 +9,8 @@
#import "ConnectionTransitionContext.h"
#import "ConnectionAnimatedTransition.h"
#import "Preferences.h"
+#import "VideoStreamSettings.h"
+#import "VideoStreamingSettingsViewController.h"
@interface ConnectionContainerViewController ()
@@ -19,6 +21,10 @@
@property (strong, nonatomic) UIPanGestureRecognizer *panGestureRecognizer;
+@property (strong, nonatomic) ConnectionTCPTableViewController *tcpController;
+@property (strong, nonatomic) ConnectionIAPTableViewController *iapController;
+@property (strong, nonatomic) VideoStreamSettings *videoStreamSettings;
+
@end
@@ -29,13 +35,19 @@
[super viewDidLoad];
self.navigationController.navigationBar.translucent = NO;
+
+ self.videoStreamSettings = [VideoStreamSettings new];
// Setup the child VCs
- UIStoryboard *tcpControllerStoryboard = [UIStoryboard storyboardWithName:@"ConnectionTCPTableViewController" bundle:[NSBundle mainBundle]];
- UIStoryboard *iapControllerStoryboard = [UIStoryboard storyboardWithName:@"ConnectionIAPTableViewController" bundle:[NSBundle mainBundle]];
- ConnectionTCPTableViewController *tcpController = [tcpControllerStoryboard instantiateInitialViewController];
- ConnectionIAPTableViewController *iapController = [iapControllerStoryboard instantiateInitialViewController];
- self.viewControllers = @[tcpController, iapController];
+ UIStoryboard *tcpControllerStoryboard = [UIStoryboard storyboardWithName:@"ConnectionTCPTableViewController" bundle:nil];
+ self.tcpController = [tcpControllerStoryboard instantiateInitialViewController];
+ self.tcpController.videoStreamSettings = self.videoStreamSettings;
+
+ UIStoryboard *iapControllerStoryboard = [UIStoryboard storyboardWithName:@"ConnectionIAPTableViewController" bundle:nil];
+ self.iapController = [iapControllerStoryboard instantiateInitialViewController];
+ self.iapController.videoStreamSettings = self.videoStreamSettings;
+
+ self.viewControllers = @[self.tcpController, self.iapController];
// Setup the pan gesture
self.panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureRecognizerDidFire:)];
@@ -84,6 +96,16 @@
}
}
+#pragma mark - Navigation
+
+- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
+ // Get the new view controller using [segue destinationViewController].
+ // Pass the selected object to the new view controller.
+ NSLog(@"%s: %@", __PRETTY_FUNCTION__, segue);
+
+ VideoStreamingSettingsViewController *settingsController = [[segue destinationViewController] isKindOfClass:[VideoStreamingSettingsViewController class]] ? [segue destinationViewController] : nil;
+ settingsController.videoStreamSettings = self.videoStreamSettings;
+}
#pragma mark - Private API
diff --git a/Example Apps/Example ObjC/ConnectionIAPTableViewController.h b/Example Apps/Example ObjC/ConnectionIAPTableViewController.h
index 5ebb3801c..09440d371 100644
--- a/Example Apps/Example ObjC/ConnectionIAPTableViewController.h
+++ b/Example Apps/Example ObjC/ConnectionIAPTableViewController.h
@@ -3,7 +3,8 @@
// SmartDeviceLink-iOS
#import <UIKit/UIKit.h>
+#import "VideoStreamSettings.h"
@interface ConnectionIAPTableViewController : UITableViewController
-
+@property (strong, nonatomic, nullable) VideoStreamSettings *videoStreamSettings;
@end
diff --git a/Example Apps/Example ObjC/ConnectionTCPTableViewController.h b/Example Apps/Example ObjC/ConnectionTCPTableViewController.h
index 8414dfcfc..43db61a88 100644
--- a/Example Apps/Example ObjC/ConnectionTCPTableViewController.h
+++ b/Example Apps/Example ObjC/ConnectionTCPTableViewController.h
@@ -4,6 +4,8 @@
#import <UIKit/UIKit.h>
-@interface ConnectionTCPTableViewController : UITableViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
+@class VideoStreamSettings;
+@interface ConnectionTCPTableViewController : UITableViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
+@property (strong, nonatomic, nullable) VideoStreamSettings *videoStreamSettings;
@end
diff --git a/Example Apps/Example ObjC/ConnectionTCPTableViewController.m b/Example Apps/Example ObjC/ConnectionTCPTableViewController.m
index 7b497a591..45f4fb914 100644
--- a/Example Apps/Example ObjC/ConnectionTCPTableViewController.m
+++ b/Example Apps/Example ObjC/ConnectionTCPTableViewController.m
@@ -4,12 +4,29 @@
#import <AVFoundation/AVFoundation.h>
#import <MobileCoreServices/MobileCoreServices.h>
-
+#import <AVFoundation/AVFoundation.h>
+#import <AVKit/AVKit.h>
#import "ConnectionTCPTableViewController.h"
-
#import "Preferences.h"
#import "ProxyManager.h"
#import "SDLStreamingMediaManager.h"
+#import "SDLManager.h"
+#import "TestUIAppViewController.h"
+#import "SimpleAppViewController.h"
+#import "GameViewController.h"
+#import "SDLStreamingMediaDelegate.h"
+#import "SDLProxy.h"
+#import "VideoStreamSettings.h"
+
+
+typedef NS_ENUM(NSInteger, AppKind) {
+ AppKindUIApp,
+ AppKindSimple,
+ AppKind3DApp,
+ AppKindVideoApp,
+};
+
+@protocol SDLStreamingMediaDelegate;
@interface ConnectionTCPTableViewController ()
@@ -18,9 +35,12 @@
@property (weak, nonatomic) IBOutlet UITableViewCell *connectTableViewCell;
@property (weak, nonatomic) IBOutlet UIButton *connectButton;
+@property (weak, nonatomic) IBOutlet UISegmentedControl *appSelector;
-@end
+@property (strong, nonatomic, nullable) UIViewController<SDLStreamingMediaDelegate> *testAppViewController;
+@property (assign, nonatomic) AppKind appKind;
+@end
@implementation ConnectionTCPTableViewController
@@ -52,11 +72,22 @@
- (IBAction)connectButtonWasPressed:(UIButton *)sender {
[Preferences sharedPreferences].ipAddress = self.ipAddressTextField.text;
[Preferences sharedPreferences].port = self.portTextField.text.integerValue;
-
+
+ [self.view endEditing:YES]; // hide keyboard
+
ProxyState state = [ProxyManager sharedManager].state;
switch (state) {
case ProxyStateStopped: {
- [[ProxyManager sharedManager] startWithProxyTransportType:ProxyTransportTypeTCP];
+ SDLTCPConfig *tcpConfig = [SDLTCPConfig configWithHost:self.ipAddressTextField.text port:self.portTextField.text.integerValue];
+
+ if (!self.testAppViewController) {
+ self.appKind = AppKindSimple;
+ self.testAppViewController = [self createTestViewControllerOfType:self.appKind];
+ }
+ [ProxyManager sharedManager].videoVC = self.testAppViewController;
+ [ProxyManager sharedManager].videoStreamSettings = self.videoStreamSettings;
+
+ [[ProxyManager sharedManager] startProxyTCP:tcpConfig];
} break;
case ProxyStateSearchingForConnection: {
[[ProxyManager sharedManager] stopConnection];
@@ -68,6 +99,22 @@
}
}
+- (UIViewController<SDLStreamingMediaDelegate>*)createTestViewControllerOfType:(AppKind)appKind {
+ switch (appKind) {
+ case AppKindVideoApp:
+ return nil;
+
+ case AppKindSimple: // Video Player
+ return [SimpleAppViewController createViewController];
+
+ case AppKind3DApp: // 3D app
+ return [GameViewController createViewController];
+
+ default:
+ case AppKindUIApp: // UI app
+ return [TestUIAppViewController createViewController];
+ }
+}
#pragma mark - Table view delegate
@@ -93,7 +140,9 @@
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:NSStringFromSelector(@selector(state))]) {
ProxyState newState = [change[NSKeyValueChangeNewKey] unsignedIntegerValue];
- [self proxyManagerDidChangeState:newState];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self proxyManagerDidChangeState:newState];
+ });
}
}
@@ -105,6 +154,7 @@
case ProxyStateStopped: {
newColor = [UIColor redColor];
newTitle = @"Connect";
+ [self finishApp];
} break;
case ProxyStateSearchingForConnection: {
newColor = [UIColor blueColor];
@@ -113,6 +163,7 @@
case ProxyStateConnected: {
newColor = [UIColor greenColor];
newTitle = @"Disconnect";
+ [self startAppOfKind:self.appKind];
} break;
default: break;
}
@@ -125,4 +176,25 @@
}
}
+// start / stop client app
+
+- (void)startAppOfKind:(AppKind)kind {
+ NSLog(@"start AppKind:%d", (int)kind);
+ if (self.testAppViewController) {
+ if ([self.testAppViewController isKindOfClass:[SimpleAppViewController class]]) {
+ NSLog(@"%@ : is not supposed to be in the view stack", NSStringFromClass(self.testAppViewController.class));
+ } else {
+ [self.navigationController pushViewController:self.testAppViewController animated:YES];
+ }
+ } else {
+ NSLog(@"wrong app kind: %d", (int)kind);
+ }
+}
+
+- (void)finishApp {
+ if (self.testAppViewController) {
+ [self.navigationController popToViewController:self.parentViewController animated:YES];
+ }
+}
+
@end
diff --git a/Example Apps/Example ObjC/ConnectionTransitionContext.m b/Example Apps/Example ObjC/ConnectionTransitionContext.m
index 7275952c3..732344426 100644
--- a/Example Apps/Example ObjC/ConnectionTransitionContext.m
+++ b/Example Apps/Example ObjC/ConnectionTransitionContext.m
@@ -101,12 +101,12 @@
#pragma mark Interactive Transition
-
+// method stubs to supress compiler warnings
- (void)updateInteractiveTransition:(CGFloat)percentComplete {}
- (void)finishInteractiveTransition {}
- (void)cancelInteractiveTransition {}
- (void)pauseInteractiveTransition {}
-
-
+@synthesize animated;
+@synthesize interactive;
@end
diff --git a/Example Apps/Example ObjC/ExampleApps/OldStyleApp/SimpleAppViewController.h b/Example Apps/Example ObjC/ExampleApps/OldStyleApp/SimpleAppViewController.h
new file mode 100644
index 000000000..e80e5f2f6
--- /dev/null
+++ b/Example Apps/Example ObjC/ExampleApps/OldStyleApp/SimpleAppViewController.h
@@ -0,0 +1,20 @@
+//
+// SimpleAppViewController.h
+// SmartDeviceLink-iOS
+//
+// Created by Leonid Lokhmatov on 5/25/20.
+// Copyright © 2018 Luxoft. All rights reserved
+//
+
+#import <UIKit/UIKit.h>
+#import "SDLStreamingMediaDelegate.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface SimpleAppViewController<SDLStreamingMediaDelegate> : UIViewController
+
++ (instancetype)createViewController;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Example Apps/Example ObjC/ExampleApps/OldStyleApp/SimpleAppViewController.m b/Example Apps/Example ObjC/ExampleApps/OldStyleApp/SimpleAppViewController.m
new file mode 100644
index 000000000..5e1e5fa20
--- /dev/null
+++ b/Example Apps/Example ObjC/ExampleApps/OldStyleApp/SimpleAppViewController.m
@@ -0,0 +1,140 @@
+//
+// SimpleAppViewController.m
+// SmartDeviceLink-iOS
+//
+// Created by Leonid Lokhmatov on 5/25/20.
+// Copyright © 2018 Luxoft. All rights reserved
+//
+
+#import "SimpleAppViewController.h"
+#import "SDLTouchManagerDelegate.h"
+#import "SimpleRootView.h"
+#import "TouchModel.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+
+
+@interface SimpleAppViewController ()
+@property (strong, nonatomic, nullable) IBOutletCollection(UIButton) NSArray *buttons;
+@end
+
+
+@interface SimpleAppViewController (SDLTouchManagerDelegate) <SDLTouchManagerDelegate>
+@end
+
+
+@implementation SimpleAppViewController
+
++ (SimpleAppViewController*)createViewController {
+ UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"ExampleApps" bundle:nil];
+ SimpleAppViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"idSimpleAppViewController"];
+ return vc;
+}
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ for (UIButton *button in self.buttons) {
+ button.tag = 0;
+ }
+}
+
+- (SimpleRootView *)rootView {
+ return (SimpleRootView *)self.view;
+}
+
+- (void)updateOnTouchButton:(UIView * _Nullable)viewCandidate {
+ if (!viewCandidate) {
+ return;
+ }
+ for (UIButton *button in self.buttons) {
+ if (button == viewCandidate) {
+ button.tag += 1;
+ [button setTitle:[NSString stringWithFormat:@"%03d", (int)button.tag] forState:UIControlStateNormal];
+ break;
+ }
+ }
+}
+
+@end
+
+
+//#Touch_Input:
+@implementation SimpleAppViewController (SDLTouchManagerDelegate)
+
+static const CGFloat MinSz = -8.0;
+
+- (void)touchManager:(SDLTouchManager *)manager didReceiveSingleTapForView:(UIView *_Nullable)view atPoint:(CGPoint)point {
+ CGRect frame = view.frame;
+ if (nil == view) {
+ frame.origin = point;
+ frame = CGRectInset(frame, MinSz, MinSz);
+ }
+ self.rootView.singleTap = [TouchModel touchPoint:point inRect:frame];
+ [self updateOnTouchButton:view];
+ NSLog(@"%s: %@ > %@", __PRETTY_FUNCTION__, NSStringFromClass(view.class), self.rootView.singleTap);
+}
+
+- (void)touchManager:(SDLTouchManager *)manager didReceiveDoubleTapForView:(UIView *_Nullable)view atPoint:(CGPoint)point {
+ CGRect frame = view.frame;
+ if (nil == view) {
+ frame.origin = point;
+ frame = CGRectInset(frame, MinSz, MinSz);
+ }
+ self.rootView.doubleTap = [TouchModel touchPoint:point inRect:frame];
+ [self updateOnTouchButton:view];
+ NSLog(@"%s: %@ > %@", __PRETTY_FUNCTION__, NSStringFromClass(view.class), self.rootView.doubleTap);
+}
+
+// panning
+- (void)touchManager:(SDLTouchManager *)manager panningDidStartInView:(UIView *_Nullable)view atPoint:(CGPoint)point {
+ NSLog(@"%s: %@ > %@", __PRETTY_FUNCTION__, view, NSStringFromCGPoint(point));
+}
+
+- (void)touchManager:(SDLTouchManager *)manager didReceivePanningFromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint {
+ NSLog(@"%s: %@-->%@", __PRETTY_FUNCTION__, NSStringFromCGPoint(fromPoint), NSStringFromCGPoint(toPoint));
+}
+
+- (void)touchManager:(SDLTouchManager *)manager panningDidEndInView:(UIView *_Nullable)view atPoint:(CGPoint)point {
+ NSLog(@"%s: %@ > %@", __PRETTY_FUNCTION__, view, NSStringFromCGPoint(point));
+}
+
+- (void)touchManager:(SDLTouchManager *)manager panningCanceledAtPoint:(CGPoint)point {
+ NSLog(@"%s: %@", __PRETTY_FUNCTION__, NSStringFromCGPoint(point));
+}
+
+// pinch
+- (void)touchManager:(SDLTouchManager *)manager pinchDidStartInView:(UIView *_Nullable)view atCenterPoint:(CGPoint)point {
+ NSLog(@"%s: %@ > %@", __PRETTY_FUNCTION__, view, NSStringFromCGPoint(point));
+}
+
+- (void)touchManager:(SDLTouchManager *)manager didReceivePinchAtCenterPoint:(CGPoint)point withScale:(CGFloat)scale {
+ NSLog(@"%s: %@ : %2.2f", __PRETTY_FUNCTION__, NSStringFromCGPoint(point), scale);
+}
+
+- (void)touchManager:(SDLTouchManager *)manager didReceivePinchInView:(UIView *_Nullable)view atCenterPoint:(CGPoint)point withScale:(CGFloat)scale {
+ NSLog(@"%s: %@ > %@", __PRETTY_FUNCTION__, view, NSStringFromCGPoint(point));
+}
+
+- (void)touchManager:(SDLTouchManager *)manager pinchDidEndInView:(UIView *_Nullable)view atCenterPoint:(CGPoint)point {
+ NSLog(@"%s: %@ > %@", __PRETTY_FUNCTION__, view, NSStringFromCGPoint(point));
+}
+
+- (void)touchManager:(SDLTouchManager *)manager pinchCanceledAtCenterPoint:(CGPoint)point {
+ NSLog(@"%s: %@", __PRETTY_FUNCTION__, NSStringFromCGPoint(point));
+}
+
+#pragma mark - SDLStreamingMediaDelegate
+
+- (void)videoStreamingSizeDidUpdate:(CGSize)displaySize {
+ NSLog(@"%s: %@", __PRETTY_FUNCTION__, NSStringFromCGSize(displaySize));
+}
+
+- (void)videoStreamingSizeDoesNotMatch {
+ NSLog(@"%s", __PRETTY_FUNCTION__);
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Example Apps/Example ObjC/ExampleApps/OldStyleApp/SimpleRootView.h b/Example Apps/Example ObjC/ExampleApps/OldStyleApp/SimpleRootView.h
new file mode 100644
index 000000000..052822e84
--- /dev/null
+++ b/Example Apps/Example ObjC/ExampleApps/OldStyleApp/SimpleRootView.h
@@ -0,0 +1,19 @@
+//
+// SimpleRootView.h
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Leonid Lokhmatov on 5/27/20.
+// Copyright © 2018 Luxoft. All rights reserved
+//
+
+#import <UIKit/UIKit.h>
+#import "TouchModel.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface SimpleRootView : UIView
+@property (strong, nonatomic, nullable) TouchModel *singleTap;
+@property (strong, nonatomic, nullable) TouchModel *doubleTap;
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Example Apps/Example ObjC/ExampleApps/OldStyleApp/SimpleRootView.m b/Example Apps/Example ObjC/ExampleApps/OldStyleApp/SimpleRootView.m
new file mode 100644
index 000000000..dbf3ed933
--- /dev/null
+++ b/Example Apps/Example ObjC/ExampleApps/OldStyleApp/SimpleRootView.m
@@ -0,0 +1,84 @@
+//
+// SimpleRootView.m
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Leonid Lokhmatov on 5/27/20.
+// Copyright © 2018 Luxoft. All rights reserved
+//
+
+#import "SimpleRootView.h"
+
+@interface SimpleRootView ()
+@property (strong, nonatomic, nullable) IBOutlet UIView *singleTapView;
+@property (strong, nonatomic, nullable) IBOutlet UIView *doubleTapView;
+@end
+
+@implementation SimpleRootView
+
+- (void)awakeFromNib {
+ [super awakeFromNib];
+ [self prepareTapView:self.singleTapView];
+ [self prepareTapView:self.doubleTapView];
+}
+
+- (void)prepareTapView:(UIView*)view {
+ view.layer.borderColor = self.doubleTapView.backgroundColor.CGColor;
+ view.backgroundColor = [UIColor clearColor];
+ view.layer.borderWidth = 3;
+ view.layer.cornerRadius = 3;
+ view.hidden = YES;
+}
+
+- (void)layoutSubviews {
+ [super layoutSubviews];
+ if (self.singleTap) {
+ self.singleTapView.frame = self.singleTap.rect;
+ }
+ if (self.doubleTap) {
+ self.doubleTapView.frame = self.doubleTap.rect;
+ }
+}
+
+- (void)hideSingleTapViewDelayed {
+ [self.class cancelPreviousPerformRequestsWithTarget:self selector:@selector(doHideSingleTapView) object:nil];
+ [self performSelector:@selector(doHideSingleTapView) withObject:nil afterDelay:0.5];
+}
+
+- (void)doHideSingleTapView {
+ self.singleTapView.hidden = YES;
+}
+
+- (void)hideDoubleTapViewDelayed {
+ [self.class cancelPreviousPerformRequestsWithTarget:self selector:@selector(doHideDoubleTapView) object:nil];
+ [self performSelector:@selector(doHideDoubleTapView) withObject:nil afterDelay:0.5];
+}
+
+- (void)doHideDoubleTapView {
+ self.doubleTapView.hidden = YES;
+}
+
+- (void)setSingleTap:(TouchModel *)singleTap {
+ _singleTap = singleTap;
+ self.singleTapView.hidden = (nil == singleTap);
+ [self hideSingleTapViewDelayed];
+
+ if (self.window) {
+ [self setNeedsLayout];
+ } else {
+ [self layoutSubviews];
+ }
+}
+
+- (void)setDoubleTap:(TouchModel *)doubleTap {
+ _doubleTap = doubleTap;
+ self.doubleTapView.hidden = (nil == doubleTap);
+ [self hideDoubleTapViewDelayed];
+
+ if (self.window) {
+ [self setNeedsLayout];
+ } else {
+ [self layoutSubviews];
+ }
+}
+
+@end
diff --git a/Example Apps/Example ObjC/ExampleApps/OldStyleApp/TouchModel.h b/Example Apps/Example ObjC/ExampleApps/OldStyleApp/TouchModel.h
new file mode 100644
index 000000000..e592fbb44
--- /dev/null
+++ b/Example Apps/Example ObjC/ExampleApps/OldStyleApp/TouchModel.h
@@ -0,0 +1,19 @@
+//
+// TouchModel.h
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Leonid Lokhmatov on 5/27/20.
+// Copyright © 2018 Luxoft. All rights reserved
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface TouchModel : NSObject
+@property (assign, nonatomic) CGRect rect;
+@property (assign, nonatomic) CGPoint point;
++ (instancetype)touchPoint:(CGPoint)point inRect:(CGRect)rect;
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Example Apps/Example ObjC/ExampleApps/OldStyleApp/TouchModel.m b/Example Apps/Example ObjC/ExampleApps/OldStyleApp/TouchModel.m
new file mode 100644
index 000000000..33799973d
--- /dev/null
+++ b/Example Apps/Example ObjC/ExampleApps/OldStyleApp/TouchModel.m
@@ -0,0 +1,25 @@
+//
+// TouchModel.m
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Leonid Lokhmatov on 5/27/20.
+// Copyright © 2018 Luxoft. All rights reserved
+//
+
+#import "TouchModel.h"
+
+@implementation TouchModel
+
++ (instancetype)touchPoint:(CGPoint)point inRect:(CGRect)rect {
+ TouchModel *model = [self new];
+ model.point = point;
+ model.rect = rect;
+ return model;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"%@-->%@", NSStringFromCGPoint(self.point), NSStringFromCGRect(self.rect)];
+}
+
+@end
+
diff --git a/Example Apps/Example ObjC/ExampleApps/Resources/ExampleApps.storyboard b/Example Apps/Example ObjC/ExampleApps/Resources/ExampleApps.storyboard
new file mode 100644
index 000000000..cda238e5d
--- /dev/null
+++ b/Example Apps/Example ObjC/ExampleApps/Resources/ExampleApps.storyboard
@@ -0,0 +1,409 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+ <device id="retina4_0" orientation="portrait" appearance="light"/>
+ <dependencies>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15510"/>
+ <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <scenes>
+ <!--Test UI app-->
+ <scene sceneID="iuI-7D-x0R">
+ <objects>
+ <viewController storyboardIdentifier="idTestUIAppViewController" title="Test UI app" id="Hsq-Z0-fjm" customClass="TestUIAppViewController" sceneMemberID="viewController">
+ <view key="view" contentMode="scaleToFill" id="aQ7-UZ-Vsd">
+ <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="YpC-6N-2oc" userLabel="display view">
+ <rect key="frame" x="10" y="10" width="300" height="450"/>
+ <subviews>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" lineBreakMode="characterWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="6fY-J4-opr" userLabel="Sub-1 (LT)">
+ <rect key="frame" x="5" y="5" width="50" height="50"/>
+ <color key="backgroundColor" systemColor="systemPinkColor" red="1" green="0.1764705882" blue="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="50" id="6oN-eG-IdT"/>
+ <constraint firstAttribute="height" constant="50" id="fcY-Jm-t2x"/>
+ </constraints>
+ <string key="text">This is an overview of how SmartDeviceLink (SDL) works. It will go through higher level discussions about certain aspects of SDL to give an intro level of understanding. For more general information on SmartDeviceLink (SDL) as a technology, there is a white-paper available here.
+SmartDeviceLink is a connectivity protocol and set of associated libraries that allow third-party applications to communicate with cars. This allows drivers to safely access the content they want through their vehicle.
+There are different components to SDL that make everything work. The following diagram shows how some of those pieces are connected.</string>
+ <fontDescription key="fontDescription" type="system" pointSize="10"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" lineBreakMode="characterWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JmY-MF-9O1" userLabel="Sub-2 (RT)">
+ <rect key="frame" x="245" y="5" width="50" height="50"/>
+ <color key="backgroundColor" systemColor="systemGreenColor" red="0.20392156859999999" green="0.78039215689999997" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="50" id="QwI-dJ-2fu"/>
+ <constraint firstAttribute="height" constant="50" id="b00-Tt-3i3"/>
+ </constraints>
+ <string key="text">This is an overview of how SmartDeviceLink (SDL) works. It will go through higher level discussions about certain aspects of SDL to give an intro level of understanding. For more general information on SmartDeviceLink (SDL) as a technology, there is a white-paper available here.
+SmartDeviceLink is a connectivity protocol and set of associated libraries that allow third-party applications to communicate with cars. This allows drivers to safely access the content they want through their vehicle.
+There are different components to SDL that make everything work. The following diagram shows how some of those pieces are connected.</string>
+ <fontDescription key="fontDescription" type="system" pointSize="10"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" lineBreakMode="characterWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="B7P-Jy-76s" userLabel="Lab-3 (RB)">
+ <rect key="frame" x="245" y="395" width="50" height="50"/>
+ <color key="backgroundColor" systemColor="systemPurpleColor" red="0.68627450980000004" green="0.32156862749999998" blue="0.87058823529999996" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="50" id="ZSS-WH-lDG"/>
+ <constraint firstAttribute="height" constant="50" id="eep-Lt-Alt"/>
+ </constraints>
+ <string key="text">This is an overview of how SmartDeviceLink (SDL) works. It will go through higher level discussions about certain aspects of SDL to give an intro level of understanding. For more general information on SmartDeviceLink (SDL) as a technology, there is a white-paper available here.
+SmartDeviceLink is a connectivity protocol and set of associated libraries that allow third-party applications to communicate with cars. This allows drivers to safely access the content they want through their vehicle.
+There are different components to SDL that make everything work. The following diagram shows how some of those pieces are connected.</string>
+ <fontDescription key="fontDescription" type="system" pointSize="10"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" lineBreakMode="characterWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="6FH-6a-VDP" userLabel="Lab-4 (LB)">
+ <rect key="frame" x="5" y="395" width="50" height="50"/>
+ <color key="backgroundColor" systemColor="systemTealColor" red="0.35294117650000001" green="0.7843137255" blue="0.98039215690000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="50" id="GLW-6Q-9rK"/>
+ <constraint firstAttribute="width" constant="50" id="xEc-ex-OWB"/>
+ </constraints>
+ <string key="text">This is an overview of how SmartDeviceLink (SDL) works. It will go through higher level discussions about certain aspects of SDL to give an intro level of understanding. For more general information on SmartDeviceLink (SDL) as a technology, there is a white-paper available here.
+SmartDeviceLink is a connectivity protocol and set of associated libraries that allow third-party applications to communicate with cars. This allows drivers to safely access the content they want through their vehicle.
+There are different components to SDL that make everything work. The following diagram shows how some of those pieces are connected.</string>
+ <fontDescription key="fontDescription" type="system" pointSize="10"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" animating="YES" style="large" translatesAutoresizingMaskIntoConstraints="NO" id="Dee-Us-sqx">
+ <rect key="frame" x="131.5" y="206.5" width="37" height="37"/>
+ <color key="color" cocoaTouchSystemColor="darkTextColor"/>
+ </activityIndicatorView>
+ </subviews>
+ <color key="backgroundColor" systemColor="systemOrangeColor" red="1" green="0.58431372550000005" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <constraints>
+ <constraint firstItem="6fY-J4-opr" firstAttribute="leading" secondItem="YpC-6N-2oc" secondAttribute="leading" constant="5" id="9l8-Tl-Csb"/>
+ <constraint firstAttribute="trailing" secondItem="B7P-Jy-76s" secondAttribute="trailing" priority="750" constant="5" id="Ahm-fF-lmq"/>
+ <constraint firstItem="6FH-6a-VDP" firstAttribute="leading" secondItem="YpC-6N-2oc" secondAttribute="leading" constant="5" id="Ckt-UO-4I4"/>
+ <constraint firstAttribute="bottom" secondItem="B7P-Jy-76s" secondAttribute="bottom" priority="750" constant="5" id="JLE-bR-X9A"/>
+ <constraint firstAttribute="trailing" secondItem="JmY-MF-9O1" secondAttribute="trailing" priority="750" constant="5" id="LqK-xj-mCw"/>
+ <constraint firstAttribute="height" constant="450" id="OtQ-8k-485" userLabel="display height"/>
+ <constraint firstItem="Dee-Us-sqx" firstAttribute="centerY" secondItem="YpC-6N-2oc" secondAttribute="centerY" id="Xxx-Ht-bZp"/>
+ <constraint firstItem="6fY-J4-opr" firstAttribute="top" secondItem="YpC-6N-2oc" secondAttribute="top" constant="5" id="dBS-Di-mRh"/>
+ <constraint firstAttribute="bottom" secondItem="6FH-6a-VDP" secondAttribute="bottom" priority="750" constant="5" id="nfp-aX-Xqp"/>
+ <constraint firstItem="Dee-Us-sqx" firstAttribute="centerX" secondItem="YpC-6N-2oc" secondAttribute="centerX" id="sjC-3r-ByV"/>
+ <constraint firstItem="JmY-MF-9O1" firstAttribute="top" secondItem="YpC-6N-2oc" secondAttribute="top" constant="5" id="uxi-DE-lXh"/>
+ <constraint firstAttribute="width" constant="300" id="wet-vQ-1wB" userLabel="display width"/>
+ </constraints>
+ </view>
+ </subviews>
+ <color key="backgroundColor" cocoaTouchSystemColor="scrollViewTexturedBackgroundColor"/>
+ <constraints>
+ <constraint firstItem="YpC-6N-2oc" firstAttribute="top" secondItem="esS-VV-iMO" secondAttribute="top" constant="10" id="2ay-Z0-Y3t" userLabel="display y"/>
+ <constraint firstItem="YpC-6N-2oc" firstAttribute="leading" secondItem="esS-VV-iMO" secondAttribute="leading" constant="10" id="LKv-vf-kJx" userLabel="display x"/>
+ </constraints>
+ <viewLayoutGuide key="safeArea" id="esS-VV-iMO"/>
+ </view>
+ <connections>
+ <outlet property="displayConstraintH" destination="OtQ-8k-485" id="l0K-Jp-Gbb"/>
+ <outlet property="displayConstraintW" destination="wet-vQ-1wB" id="L8R-BT-GM6"/>
+ <outlet property="displayConstraintX" destination="LKv-vf-kJx" id="Sfc-0x-D6U"/>
+ <outlet property="displayConstraintY" destination="2ay-Z0-Y3t" id="ccZ-ws-5U1"/>
+ <outlet property="displayView" destination="YpC-6N-2oc" id="un0-Jd-ppS"/>
+ <outlet property="spinner" destination="Dee-Us-sqx" id="UoU-8o-1JG"/>
+ <outlet property="subview1" destination="6fY-J4-opr" id="pfm-30-XFr"/>
+ <outlet property="subview2" destination="JmY-MF-9O1" id="v75-c8-x1W"/>
+ <outlet property="subview3" destination="B7P-Jy-76s" id="pbH-L2-SEa"/>
+ <outlet property="subview4" destination="6FH-6a-VDP" id="hqS-1g-0gJ"/>
+ </connections>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="tCN-TA-ZPI" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="135" y="-174.29577464788733"/>
+ </scene>
+ <!--VideoWindow-->
+ <scene sceneID="hLm-cg-tNj">
+ <objects>
+ <avPlayerViewController storyboardIdentifier="idVideoWindow" title="VideoWindow" videoGravity="AVLayerVideoGravityResizeAspect" id="ReI-EM-aoQ" sceneMemberID="viewController"/>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="fBX-4X-Xn3" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="823" y="-174"/>
+ </scene>
+ <!--Simple VC-->
+ <scene sceneID="sXf-8T-TkQ">
+ <objects>
+ <viewController storyboardIdentifier="idSimpleAppViewController" title="Simple VC" id="afi-yv-teE" customClass="SimpleAppViewController" sceneMemberID="viewController">
+ <view key="view" contentMode="scaleToFill" id="ro5-P9-ro3" customClass="SimpleRootView">
+ <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ey4-1z-FIR" userLabel="display view">
+ <rect key="frame" x="10" y="10" width="300" height="548"/>
+ <subviews>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" lineBreakMode="characterWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="TJT-oW-v24" userLabel="All text area">
+ <rect key="frame" x="9" y="9" width="282" height="530"/>
+ <color key="backgroundColor" systemColor="systemYellowColor" red="1" green="0.80000000000000004" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <mutableString key="text">In the United States of America, there is a popular saying that "there are few things as American as apple pie".[9] In the United States, pie and especially apple pie, became "bound up in American mythology" to the point that in 1902, The New York Times asserted that "Pie is the food of the heroic" and stated that "No pie-eating people can ever be permanently vanquished".[2]
+
+The slang expression "to eat humble pie" comes from the umble pie, which was made with "chopped or minced innards of an animal", a "cheap offal filling...eaten by the poor".[27] The slang expression "it's a piece of pie", meaning that something is easy, dates from 1889.[28] The slang expression "pie-eyed", meaning drunk, dates from 1904.[29] The expression "pie in the sky", to refer to an unlikely proposal or idea, dates from a 1911 Wobbly song by Joe Hill.[30]The Pilgrim fathers and early settlers brought their pie recipes with them to America, adapting to the ingredients and techniques available to them in the New World. Settlers' recipes were for English-style meat pies.[9] The newcomers used the fruits and berries that they were familiar with from Europe, but also began incorporating North American vegetables and game that they were not familiar with, with guidance from Indigenous people.[21] Settlers favoured pies over bread because pies required less flour and did not require a brick bread oven, and because any mixture of ingredients could be added to pies to "stretch" their "meager provisions".[22] The apple pie made with American apples became popular, because apples were easy to dry and store in barrels over the winter.[22] Early American pies had thick, heavy crusts made with rough flour and suet.[22] As pioneers spread westward, pies continued to be an important supply of food; while apple pies made from dried apples were popular, cooks often had to use fillers or substitutes to stretch out their barrels of apples, such as crushed crackers, vinegar-soaked potatoes, sour green tomatoes and soft-shelled river turtle meat.[22]
+
+The first Thanksgiving feast included fowl and venison, which may have been included in pies.[9] Colonists appreciated the food preservation aspect of crusty-topped pies, which were often seasoned with "dried fruit, cinnamon, pepper and nutmeg".[9] Their first pies included pies that were based on berries and fruits pointed out to them by the Native North Americans.[1] Pies allowed colonial cooks to use round shallow pans to literally "cut corners" and to create a regional variation of shallow pie.[23] By the late 1700s, cookbooks show a wide range of newly developed sweet pies.[9]
+
+Pies became more refined with subsequent waves of immigrants; the Pennsylvania Dutch contributed a more aromatic, spiced, and less-sweet style of pie-making; the French brought the approach of making pie with butter and a range of tart, galette and pâté (forcemeat of meat and fish in dough) recipes.[22] Swedish immigrants in the plains states brought recipes for fish pie and berry pie; Finnish immigrants brought their recipes for pasties and meat pies.[22] In the northern states, pumpkin pie was popular, as pumpkins were plentiful.[22] Once the British had established Caribbean colonies, sugar became less expensive and more widely available, which meant that sweet pies could be readily made.[2] Molasses was popular in American pies due to the rum and slave trade with the Caribbean Islands, although maple syrup was an important sweetener in Northern states, after Indigenous people taught settlers how to tap maple trees and boil down the sap.[22] In the Midwest, cheese and cream pies were popular, due to the availability of big dairy farms.[22] In the US south, African-Americans enjoyed sweet potato pies, due to the widespread availability of this type of potato.[22]
+
+By the 1870s, the new science of nutrition led to criticism of pies, notably by Sarah Tyson Rorer, a cooking teacher and food editor who warned the public about how much energy pies take to digest.[22] Rorer stated that all pie crusts "...are to be condemned" and her cookbook only included an apple tart, jelly and meringue-covered crackers, pâté, and a "hygienic pie" which had "apple slices or a pumpkin custard baked in biscuit dough".[3] In 1866, Harper's Magazine included an article by C.W. Gesner that stated that although we "...cry for pie when we are infants", "Pie kills us finally", as the "heavy crust" cannot be digested.[3]
+
+Another factor that decreased the popularity of pies was industrialization and increasing movement of women into the labour market, which changed pie making from a weekly ritual to an "occasional undertaking" on special occasions.[22] In the 1950s, after WWII, the popularity of pies rebounded in the US, especially with commercial food inventions such as instant pudding mixes, Cool Whip topping, and Jello gelatin (which could be used as fillings) ready-made crusts, which were sold frozen, and alternative crusts made with crushed potato chips.[22] There was a pie renaissance in the 1980s, when old-fashioned pie recipes were rediscovered and a wide range of cross-cultural pies were explored.[22]</mutableString>
+ <fontDescription key="fontDescription" type="system" pointSize="10"/>
+ <nil key="textColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="PKZ-ch-9wl">
+ <rect key="frame" x="5" y="5" width="50" height="50"/>
+ <color key="backgroundColor" systemColor="systemRedColor" red="1" green="0.23137254900000001" blue="0.18823529410000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="50" id="A3G-al-rLJ"/>
+ <constraint firstAttribute="width" constant="50" id="Gaf-Hr-4es"/>
+ </constraints>
+ <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
+ <state key="normal" title="Click">
+ <color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </state>
+ <state key="disabled">
+ <color key="titleColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </state>
+ <state key="selected">
+ <color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </state>
+ <state key="highlighted">
+ <color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </state>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qxE-TV-gZz">
+ <rect key="frame" x="245" y="493" width="50" height="50"/>
+ <color key="backgroundColor" systemColor="systemBrownColor" red="0.63529411759999999" green="0.51764705879999995" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="50" id="Fa8-g9-ocy"/>
+ <constraint firstAttribute="height" constant="50" id="zup-kM-vrH"/>
+ </constraints>
+ <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
+ <state key="normal" title="Click">
+ <color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </state>
+ <state key="disabled">
+ <color key="titleColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </state>
+ <state key="selected">
+ <color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </state>
+ <state key="highlighted">
+ <color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </state>
+ </button>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4JX-Pj-iKW">
+ <rect key="frame" x="245" y="5" width="50" height="50"/>
+ <color key="backgroundColor" systemColor="systemGreenColor" red="0.20392156859999999" green="0.78039215689999997" blue="0.34901960780000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="50" id="A61-gw-DKz"/>
+ <constraint firstAttribute="height" constant="50" id="ZAI-HC-LrS"/>
+ </constraints>
+ <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
+ <state key="normal" title="Click">
+ <color key="titleColor" red="0.15317772569999999" green="0.12028289759999999" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ </state>
+ <state key="disabled">
+ <color key="titleColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </state>
+ <state key="selected">
+ <color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </state>
+ <state key="highlighted">
+ <color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </state>
+ </button>
+ <activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" animating="YES" style="large" translatesAutoresizingMaskIntoConstraints="NO" id="heO-VY-VjL">
+ <rect key="frame" x="131.5" y="255.5" width="37" height="37"/>
+ <color key="color" cocoaTouchSystemColor="darkTextColor"/>
+ </activityIndicatorView>
+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="TNH-7i-LBE">
+ <rect key="frame" x="5" y="493" width="50" height="50"/>
+ <color key="backgroundColor" systemColor="systemTealColor" red="0.35294117650000001" green="0.7843137255" blue="0.98039215690000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="50" id="A64-hz-7vL"/>
+ <constraint firstAttribute="height" constant="50" id="o9a-QN-Y6u"/>
+ </constraints>
+ <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
+ <state key="normal" title="Click">
+ <color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </state>
+ <state key="disabled">
+ <color key="titleColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </state>
+ <state key="selected">
+ <color key="titleColor" systemColor="systemPinkColor" red="1" green="0.1764705882" blue="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ </state>
+ <state key="highlighted">
+ <color key="titleShadowColor" systemColor="systemPinkColor" red="1" green="0.1764705882" blue="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ </state>
+ </button>
+ <view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="QmW-VP-tKv" userLabel="single tap view">
+ <rect key="frame" x="47" y="118" width="49" height="44"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </view>
+ <view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FSF-qa-Ph5" userLabel="double tap view">
+ <rect key="frame" x="126" y="118" width="49" height="44"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </view>
+ </subviews>
+ <color key="backgroundColor" systemColor="systemOrangeColor" red="1" green="0.58431372550000005" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <constraints>
+ <constraint firstItem="heO-VY-VjL" firstAttribute="centerX" secondItem="Ey4-1z-FIR" secondAttribute="centerX" id="2Br-ok-EIh"/>
+ <constraint firstAttribute="trailing" secondItem="4JX-Pj-iKW" secondAttribute="trailing" constant="5" id="56i-jf-OM6"/>
+ <constraint firstItem="PKZ-ch-9wl" firstAttribute="top" secondItem="Ey4-1z-FIR" secondAttribute="top" constant="5" id="6cV-pP-qgz"/>
+ <constraint firstAttribute="bottom" secondItem="qxE-TV-gZz" secondAttribute="bottom" constant="5" id="H21-wa-cgx"/>
+ <constraint firstItem="TJT-oW-v24" firstAttribute="leading" secondItem="Ey4-1z-FIR" secondAttribute="leadingMargin" constant="1" id="JvI-Nz-DjE"/>
+ <constraint firstAttribute="trailingMargin" secondItem="TJT-oW-v24" secondAttribute="trailing" constant="1" id="THe-Rk-tFd"/>
+ <constraint firstItem="PKZ-ch-9wl" firstAttribute="leading" secondItem="Ey4-1z-FIR" secondAttribute="leading" constant="5" id="WdA-k6-sZb"/>
+ <constraint firstItem="heO-VY-VjL" firstAttribute="centerY" secondItem="Ey4-1z-FIR" secondAttribute="centerY" id="irZ-ua-C1a"/>
+ <constraint firstAttribute="bottom" secondItem="TNH-7i-LBE" secondAttribute="bottom" constant="5" id="lJb-K8-rOt"/>
+ <constraint firstItem="4JX-Pj-iKW" firstAttribute="top" secondItem="Ey4-1z-FIR" secondAttribute="top" constant="5" id="p0s-Ds-2UH"/>
+ <constraint firstAttribute="trailing" secondItem="qxE-TV-gZz" secondAttribute="trailing" constant="5" id="pLg-aA-fdC"/>
+ <constraint firstItem="TNH-7i-LBE" firstAttribute="leading" secondItem="Ey4-1z-FIR" secondAttribute="leading" constant="5" id="uko-zi-wcc"/>
+ <constraint firstItem="TJT-oW-v24" firstAttribute="top" secondItem="Ey4-1z-FIR" secondAttribute="topMargin" constant="1" id="v68-KQ-Aol"/>
+ <constraint firstAttribute="bottomMargin" secondItem="TJT-oW-v24" secondAttribute="bottom" constant="1" id="wW2-st-tCN"/>
+ </constraints>
+ </view>
+ </subviews>
+ <color key="backgroundColor" systemColor="systemPurpleColor" red="0.68627450980000004" green="0.32156862749999998" blue="0.87058823529999996" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <constraints>
+ <constraint firstItem="MAo-Oq-qpx" firstAttribute="trailing" secondItem="Ey4-1z-FIR" secondAttribute="trailing" constant="10" id="MIm-Ww-bv7"/>
+ <constraint firstItem="Ey4-1z-FIR" firstAttribute="top" secondItem="MAo-Oq-qpx" secondAttribute="top" constant="10" id="bix-sz-KxU"/>
+ <constraint firstItem="MAo-Oq-qpx" firstAttribute="bottom" secondItem="Ey4-1z-FIR" secondAttribute="bottom" constant="10" id="e7M-Hm-lte"/>
+ <constraint firstItem="Ey4-1z-FIR" firstAttribute="leading" secondItem="MAo-Oq-qpx" secondAttribute="leading" constant="10" id="wv3-8Z-boi"/>
+ </constraints>
+ <viewLayoutGuide key="safeArea" id="MAo-Oq-qpx"/>
+ <connections>
+ <outlet property="doubleTapView" destination="FSF-qa-Ph5" id="0zI-JM-gnq"/>
+ <outlet property="singleTapView" destination="QmW-VP-tKv" id="RO8-qR-XqL"/>
+ </connections>
+ </view>
+ <connections>
+ <outletCollection property="buttons" destination="PKZ-ch-9wl" id="leI-2f-Dv0"/>
+ <outletCollection property="buttons" destination="4JX-Pj-iKW" id="6Es-8h-vxZ"/>
+ <outletCollection property="buttons" destination="TNH-7i-LBE" id="3UO-P1-hbN"/>
+ <outletCollection property="buttons" destination="qxE-TV-gZz" id="6LU-S7-MUP"/>
+ </connections>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="PEX-vZ-Rwq" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="1507.5" y="-173.2394366197183"/>
+ </scene>
+ <!--PreviewVC-->
+ <scene sceneID="Jo6-kD-QNk">
+ <objects>
+ <viewController storyboardIdentifier="preview_vc" id="q8J-E5-NMK" customClass="PreviewVC" sceneMemberID="viewController">
+ <view key="view" contentMode="scaleToFill" id="ylD-pA-bAw">
+ <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" minimumZoomScale="0.25" maximumZoomScale="10" translatesAutoresizingMaskIntoConstraints="NO" id="B1M-Y6-o2v">
+ <rect key="frame" x="10" y="10" width="300" height="438"/>
+ <subviews>
+ <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Iw2-de-ZyO">
+ <rect key="frame" x="113" y="184" width="74" height="70"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </imageView>
+ </subviews>
+ <color key="backgroundColor" systemColor="linkColor" red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <viewLayoutGuide key="contentLayoutGuide" id="ffF-Kb-LDy"/>
+ <viewLayoutGuide key="frameLayoutGuide" id="gxm-9d-9nN"/>
+ <connections>
+ <outlet property="delegate" destination="q8J-E5-NMK" id="7XZ-3f-dyK"/>
+ </connections>
+ </scrollView>
+ <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" text="xxx text" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="nj4-Uy-tiY">
+ <rect key="frame" x="10" y="498" width="300" height="60"/>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="60" id="rWB-1O-5n0"/>
+ </constraints>
+ <color key="textColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
+ <fontDescription key="fontDescription" name="CourierNewPSMT" family="Courier New" pointSize="16"/>
+ <textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/>
+ </textView>
+ <slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minValue="0.5" maxValue="10" translatesAutoresizingMaskIntoConstraints="NO" id="ULX-bg-omq">
+ <rect key="frame" x="8" y="478" width="304" height="30"/>
+ <constraints>
+ <constraint firstAttribute="height" constant="29" id="qxR-af-KkQ"/>
+ </constraints>
+ <connections>
+ <action selector="actDisplaySliderDidRelease:" destination="q8J-E5-NMK" eventType="editingDidEnd" id="O1Y-JY-U3Q"/>
+ <action selector="actDisplaySliderDidRelease:" destination="q8J-E5-NMK" eventType="touchCancel" id="bda-gF-3x9"/>
+ <action selector="actDisplaySliderDidRelease:" destination="q8J-E5-NMK" eventType="touchUpOutside" id="g1S-83-xF7"/>
+ <action selector="actDisplaySliderDidRelease:" destination="q8J-E5-NMK" eventType="touchUpInside" id="kSu-qe-Uhe"/>
+ <action selector="actScaleDidUpdate:" destination="q8J-E5-NMK" eventType="valueChanged" id="Xjj-o9-g8Z"/>
+ </connections>
+ </slider>
+ </subviews>
+ <color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ <constraints>
+ <constraint firstItem="hO5-c4-PJq" firstAttribute="trailing" secondItem="ULX-bg-omq" secondAttribute="trailing" constant="10" id="7Mm-uJ-I0R"/>
+ <constraint firstItem="ULX-bg-omq" firstAttribute="leading" secondItem="hO5-c4-PJq" secondAttribute="leading" constant="10" id="7by-ww-Emc"/>
+ <constraint firstItem="B1M-Y6-o2v" firstAttribute="top" secondItem="hO5-c4-PJq" secondAttribute="top" constant="10" id="CUf-Ei-MrX"/>
+ <constraint firstItem="hO5-c4-PJq" firstAttribute="trailing" secondItem="nj4-Uy-tiY" secondAttribute="trailing" constant="10" id="DiG-j7-73Q"/>
+ <constraint firstItem="hO5-c4-PJq" firstAttribute="trailing" secondItem="B1M-Y6-o2v" secondAttribute="trailing" constant="10" id="NNC-6c-dZm"/>
+ <constraint firstItem="nj4-Uy-tiY" firstAttribute="top" secondItem="B1M-Y6-o2v" secondAttribute="bottom" constant="50" id="S3R-6s-avz"/>
+ <constraint firstItem="B1M-Y6-o2v" firstAttribute="leading" secondItem="hO5-c4-PJq" secondAttribute="leading" constant="10" id="YxE-Gz-xvL"/>
+ <constraint firstItem="hO5-c4-PJq" firstAttribute="bottom" secondItem="nj4-Uy-tiY" secondAttribute="bottom" constant="10" id="b11-J4-TLE"/>
+ <constraint firstItem="nj4-Uy-tiY" firstAttribute="leading" secondItem="hO5-c4-PJq" secondAttribute="leading" constant="10" id="cIT-nz-Ro4"/>
+ <constraint firstItem="hO5-c4-PJq" firstAttribute="bottom" secondItem="ULX-bg-omq" secondAttribute="bottom" constant="61" id="r7D-e8-W2B"/>
+ </constraints>
+ <viewLayoutGuide key="safeArea" id="hO5-c4-PJq"/>
+ </view>
+ <connections>
+ <outlet property="imageView" destination="Iw2-de-ZyO" id="z2P-zg-fzg"/>
+ <outlet property="scaleSlider" destination="ULX-bg-omq" id="Ebf-mK-bKA"/>
+ <outlet property="scrollView" destination="B1M-Y6-o2v" id="XbX-3J-mnr"/>
+ <outlet property="textInfo" destination="nj4-Uy-tiY" id="oEI-LO-c1T"/>
+ </connections>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="fCs-pb-wfQ" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="581.25" y="507.04225352112678"/>
+ </scene>
+ <!--3D App-->
+ <scene sceneID="9au-4b-JQm">
+ <objects>
+ <viewController storyboardIdentifier="idGameViewController" title="3D App" id="0BT-CH-WFx" customClass="GameViewController" sceneMemberID="viewController">
+ <view key="view" contentMode="scaleToFill" id="xfv-mV-w6v" customClass="FunnyRenderView">
+ <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <sceneKitView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="036-0y-eGt">
+ <rect key="frame" x="15" y="15" width="290" height="538"/>
+ </sceneKitView>
+ </subviews>
+ <color key="backgroundColor" systemColor="systemPurpleColor" red="0.68627450980000004" green="0.32156862749999998" blue="0.87058823529999996" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <constraints>
+ <constraint firstItem="SRc-lN-OtU" firstAttribute="bottom" secondItem="036-0y-eGt" secondAttribute="bottom" constant="15" id="MzH-ag-Yrs"/>
+ <constraint firstItem="SRc-lN-OtU" firstAttribute="trailing" secondItem="036-0y-eGt" secondAttribute="trailing" constant="15" id="cdX-0c-TFP"/>
+ <constraint firstItem="036-0y-eGt" firstAttribute="leading" secondItem="SRc-lN-OtU" secondAttribute="leading" constant="15" id="klt-AK-6hL"/>
+ <constraint firstItem="036-0y-eGt" firstAttribute="top" secondItem="SRc-lN-OtU" secondAttribute="top" constant="15" id="qIo-sw-4ff"/>
+ </constraints>
+ <viewLayoutGuide key="safeArea" id="SRc-lN-OtU"/>
+ <connections>
+ <outlet property="scnView" destination="036-0y-eGt" id="ibx-a9-WiA"/>
+ </connections>
+ </view>
+ <connections>
+ <outlet property="scnView" destination="036-0y-eGt" id="Sdg-9U-zuX"/>
+ </connections>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="Gat-XI-GYP" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="2190" y="-330"/>
+ </scene>
+ </scenes>
+</document>
diff --git a/Example Apps/Example ObjC/ExampleApps/Resources/art.scnassets/ship.scn b/Example Apps/Example ObjC/ExampleApps/Resources/art.scnassets/ship.scn
new file mode 100644
index 000000000..ea345ea05
--- /dev/null
+++ b/Example Apps/Example ObjC/ExampleApps/Resources/art.scnassets/ship.scn
Binary files differ
diff --git a/Example Apps/Example ObjC/ExampleApps/Resources/art.scnassets/texture.png b/Example Apps/Example ObjC/ExampleApps/Resources/art.scnassets/texture.png
new file mode 100644
index 000000000..ba392589b
--- /dev/null
+++ b/Example Apps/Example ObjC/ExampleApps/Resources/art.scnassets/texture.png
Binary files differ
diff --git a/Example Apps/Example ObjC/ExampleApps/SC3DApp/GameViewController.h b/Example Apps/Example ObjC/ExampleApps/SC3DApp/GameViewController.h
new file mode 100644
index 000000000..6088ab8c8
--- /dev/null
+++ b/Example Apps/Example ObjC/ExampleApps/SC3DApp/GameViewController.h
@@ -0,0 +1,15 @@
+//
+// GameViewController.h
+// TestMetal
+//
+// Created by Leonid Lokhmatov on 5/24/20.
+// Copyright © 2018 Luxoft. All rights reserved
+//
+
+#import <UIKit/UIKit.h>
+#import <SceneKit/SceneKit.h>
+#import "SDLStreamingMediaDelegate.h"
+
+@interface GameViewController<SDLStreamingMediaDelegate> : UIViewController
++ (instancetype)createViewController;
+@end
diff --git a/Example Apps/Example ObjC/ExampleApps/SC3DApp/GameViewController.m b/Example Apps/Example ObjC/ExampleApps/SC3DApp/GameViewController.m
new file mode 100644
index 000000000..843619408
--- /dev/null
+++ b/Example Apps/Example ObjC/ExampleApps/SC3DApp/GameViewController.m
@@ -0,0 +1,192 @@
+//
+// GameViewController.m
+// TestMetal
+//
+// Created by Leonid Lokhmatov on 5/24/20.
+// Copyright © 2018 Luxoft. All rights reserved
+//
+
+#import "GameViewController.h"
+
+@interface GameViewController ()
+@property (strong, nonatomic) IBOutlet SCNView *scnView;
+@end
+
+
+@interface FunnyRenderView : UIView
+@property (strong, nonatomic) IBOutlet SCNView *scnView;
+@end
+
+@interface FunnyRenderLayer : CALayer
+@property (strong, nonatomic) IBOutlet SCNView *scnView;
+@end
+
+@implementation FunnyRenderLayer
+
+- (void)renderInContext:(CGContextRef)ctx {
+ [self.delegate drawLayer:self inContext:ctx];
+}
+
+@end
+
+
+@implementation FunnyRenderView
+
++ (Class)layerClass {
+ return [FunnyRenderLayer class];
+}
+
+- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
+ if (layer == self.layer) {
+ if (self.scnView) {
+ CGContextSetFillColorWithColor(ctx, self.backgroundColor.CGColor);
+ CGContextFillRect(ctx, self.bounds);
+ UIImage *image = self.scnView.snapshot;
+ const CGRect rect = self.scnView.frame;
+ CGContextDrawImage(ctx, rect, image.CGImage);
+ }
+ }
+}
+
+//- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates {
+// BOOL ok = [super drawViewHierarchyInRect:rect afterScreenUpdates:afterUpdates];
+// [self.layer drawInContext:UIGraphicsGetCurrentContext()];
+// return ok;
+//}
+
+
+@end
+
+
+@implementation GameViewController
+
++ (GameViewController*)createViewController {
+ UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"ExampleApps" bundle:nil];
+ GameViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"idGameViewController"];
+ return vc;
+}
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ [self startSceneView:self.scnView];
+ self.view.layer.geometryFlipped = YES;
+
+ // add a tap gesture recognizer
+ [self setupRecognizer];
+}
+
+- (void)startSceneView:(SCNView *)scnView {
+ // create a new scene
+ SCNScene *scene = [SCNScene sceneNamed:@"art.scnassets/ship.scn"];
+
+ // create and add a camera to the scene
+ SCNNode *cameraNode = [SCNNode node];
+ cameraNode.camera = [SCNCamera camera];
+ [scene.rootNode addChildNode:cameraNode];
+
+ // place the camera
+ cameraNode.position = SCNVector3Make(0, 0, 15);
+
+ // create and add a light to the scene
+ SCNNode *lightNode = [SCNNode node];
+ lightNode.light = [SCNLight light];
+ lightNode.light.type = SCNLightTypeOmni;
+ lightNode.position = SCNVector3Make(0, 10, 10);
+ [scene.rootNode addChildNode:lightNode];
+
+ // create and add an ambient light to the scene
+ SCNNode *ambientLightNode = [SCNNode node];
+ ambientLightNode.light = [SCNLight light];
+ ambientLightNode.light.type = SCNLightTypeAmbient;
+ ambientLightNode.light.color = [UIColor darkGrayColor];
+ [scene.rootNode addChildNode:ambientLightNode];
+
+ // retrieve the ship node
+ SCNNode *ship = [scene.rootNode childNodeWithName:@"ship" recursively:YES];
+
+ // animate the 3d object
+ [ship runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:0 y:2 z:0 duration:1]]];
+
+ // set the scene to the view
+ scnView.scene = scene;
+
+ // allows the user to manipulate the camera
+ scnView.allowsCameraControl = YES;
+
+ // show statistics such as fps and timing information
+ scnView.showsStatistics = YES;
+
+ // configure the view
+ scnView.backgroundColor = [UIColor blackColor];
+}
+
+- (void)setupRecognizer {
+ UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
+ NSMutableArray *gestureRecognizers = [NSMutableArray array];
+ [gestureRecognizers addObject:tapGesture];
+ [gestureRecognizers addObjectsFromArray:self.scnView.gestureRecognizers];
+ self.scnView.gestureRecognizers = gestureRecognizers;
+}
+
+- (void)handleTap:(UIGestureRecognizer*)gestureRecognize {
+ // retrieve the SCNView
+ SCNView *scnView = self.scnView;
+
+ // check what nodes are tapped
+ CGPoint p = [gestureRecognize locationInView:scnView];
+ NSArray *hitResults = [scnView hitTest:p options:nil];
+
+ // check that we clicked on at least one object
+ if([hitResults count] > 0){
+ // retrieved the first clicked object
+ SCNHitTestResult *result = [hitResults objectAtIndex:0];
+
+ // get its material
+ SCNMaterial *material = result.node.geometry.firstMaterial;
+
+ // highlight it
+ [SCNTransaction begin];
+ [SCNTransaction setAnimationDuration:0.5];
+
+ // on completion - unhighlight
+ [SCNTransaction setCompletionBlock:^{
+ [SCNTransaction begin];
+ [SCNTransaction setAnimationDuration:0.5];
+ material.emission.contents = [UIColor blackColor];
+ [SCNTransaction commit];
+ }];
+
+ material.emission.contents = [UIColor redColor];
+
+ [SCNTransaction commit];
+ }
+}
+
+- (BOOL)shouldAutorotate {
+ return YES;
+}
+
+- (BOOL)prefersStatusBarHidden {
+ return YES;
+}
+
+//- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
+// if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
+// return UIInterfaceOrientationMaskAllButUpsideDown;
+// } else {
+// return UIInterfaceOrientationMaskAll;
+// }
+//}
+
+#pragma mark - SDLStreamingMediaDelegate
+
+- (void)videoStreamingSizeDidUpdate:(CGSize)displaySize {
+ NSLog(@"%s: %@", __PRETTY_FUNCTION__, NSStringFromCGSize(displaySize));
+}
+
+- (void)videoStreamingSizeDoesNotMatch {
+ NSLog(@"%s", __PRETTY_FUNCTION__);
+}
+
+@end
diff --git a/Example Apps/Example ObjC/ExampleApps/UIApp/TestUIAppViewController.h b/Example Apps/Example ObjC/ExampleApps/UIApp/TestUIAppViewController.h
new file mode 100644
index 000000000..a2123da97
--- /dev/null
+++ b/Example Apps/Example ObjC/ExampleApps/UIApp/TestUIAppViewController.h
@@ -0,0 +1,18 @@
+//
+// TestUIAppViewController.h
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Leonid Lokhmatov on 5/25/20.
+// Copyright © 2018 Luxoft. All rights reserved
+//
+
+#import <UIKit/UIKit.h>
+#import "SDLStreamingMediaDelegate.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface TestUIAppViewController<SDLStreamingMediaDelegate> : UIViewController
++ (instancetype)createViewController;
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Example Apps/Example ObjC/ExampleApps/UIApp/TestUIAppViewController.m b/Example Apps/Example ObjC/ExampleApps/UIApp/TestUIAppViewController.m
new file mode 100644
index 000000000..df7992611
--- /dev/null
+++ b/Example Apps/Example ObjC/ExampleApps/UIApp/TestUIAppViewController.m
@@ -0,0 +1,153 @@
+//
+// TestUIAppViewController.m
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Leonid Lokhmatov on 5/25/20.
+// Copyright © 2018 Luxoft. All rights reserved
+//
+
+#import "TestUIAppViewController.h"
+#import "SDLStreamingMediaManagerConstants.h"
+
+@interface TestUIAppViewController ()
+@property (strong, nonatomic) IBOutlet UIView *displayView;
+@property (strong, nonatomic) IBOutlet NSLayoutConstraint *displayConstraintX;
+@property (strong, nonatomic) IBOutlet NSLayoutConstraint *displayConstraintY;
+@property (strong, nonatomic) IBOutlet NSLayoutConstraint *displayConstraintW;
+@property (strong, nonatomic) IBOutlet NSLayoutConstraint *displayConstraintH;
+
+@property (strong, nonatomic) IBOutlet UIView *subview1;
+@property (strong, nonatomic) IBOutlet UIView *subview2;
+@property (strong, nonatomic) IBOutlet UIView *subview3;
+@property (strong, nonatomic) IBOutlet UIView *subview4;
+@property (strong, nonatomic) IBOutlet UIActivityIndicatorView *spinner;
+@property (assign, nonatomic) BOOL subscribedForVideoNotifications;
+@property (strong, nonatomic) NSTimer * animeTimer;
+@property (strong, nonatomic) NSArray * animeColorViews;
+@property (assign, nonatomic) int animeIndex;
+@property (assign, nonatomic) BOOL enableDebugFrame;
+@end
+
+@implementation TestUIAppViewController
+
++ (TestUIAppViewController*)createViewController {
+ UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"ExampleApps" bundle:nil];
+ TestUIAppViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"idTestUIAppViewController"];
+ return vc;
+}
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.animeColorViews = @[self.subview1, self.subview2, self.subview3, self.subview4];
+ self.animeIndex = 0;
+ [self subscribeForNotifications];
+ self.enableDebugFrame = YES;
+}
+
+#pragma mark - Notifications
+
+- (void)subscribeForNotifications {
+ if (!self.subscribedForVideoNotifications) {
+ self.subscribedForVideoNotifications = YES;
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_videoStreamDidStartNotification:) name:SDLVideoStreamDidStartNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_videoStreamDidStopNotification:) name:SDLVideoStreamDidStopNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_videoStreamSuspendedNotification:) name:SDLVideoStreamSuspendedNotification object:nil];
+ }
+}
+
+- (void)unsubscribeFromNotifications {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ self.subscribedForVideoNotifications = NO;
+}
+
+- (void)_videoStreamDidStartNotification:(NSNotification*)notification {
+ NSLog(@"**V-START");
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self startAnime];
+ });
+}
+
+- (void)_videoStreamDidStopNotification:(NSNotification*)notification {
+ NSLog(@"**V-STOP");
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self stopAnime];
+ });
+}
+
+- (void)_videoStreamSuspendedNotification:(NSNotification*)notification {
+ NSLog(@"**V-SUSPEND");
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self stopAnime];
+ });
+}
+
+#pragma mark - Animationd
+
+- (void)startAnime {
+ NSLog(@"%s: thread: %@", __PRETTY_FUNCTION__, [NSThread isMainThread]?@"main":@"bg thread");
+ [self animateView:self.subview1 duration:1];
+ [self animateView:self.subview2 duration:1.5];
+ [self animateView:self.subview3 duration:2];
+ [self animateView:self.subview4 duration:2.5];
+ [self.spinner startAnimating];
+
+ // note: CA animation does not work offscreen that is why the timer
+ [self.animeTimer invalidate];
+ self.animeTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(animeTickTimer:) userInfo:nil repeats:YES];
+}
+
+- (void)stopAnime {
+ NSLog(@"%s: thread: %@", __PRETTY_FUNCTION__, [NSThread isMainThread]?@"main":@"bg thread");
+ [self stopAnimateView:self.subview1];
+ [self stopAnimateView:self.subview2];
+ [self stopAnimateView:self.subview3];
+ [self stopAnimateView:self.subview4];
+ [self.spinner stopAnimating];
+
+ [self.animeTimer invalidate];
+ self.animeTimer = nil;
+}
+
+- (void)animateView:(UIView*)view duration:(float)duration {
+ CATransform3D myRotationTransform = CATransform3DMakeRotation(M_PI * 2.0, 0, 0, 1);
+ view.layer.transform = myRotationTransform;
+ CABasicAnimation *myAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
+ myAnimation.duration = duration;
+ myAnimation.fromValue = @0.0;
+ myAnimation.toValue = @(M_PI * 2.0);
+ myAnimation.repeatCount = 999;
+ [view.layer addAnimation:myAnimation forKey:@"transform.rotation"];
+}
+
+- (void)stopAnimateView:(UIView*)view {
+ [view.layer removeAllAnimations];
+}
+
+- (void)animeTickTimer:(NSTimer*)timer {
+ const NSUInteger viewCount = self.animeColorViews.count;
+ if (1 < viewCount) {
+ UIView *view0 = self.animeColorViews[0];
+ UIView *prevView = view0;
+ UIColor * color0 = prevView.backgroundColor;
+ for (int i=1; i < viewCount; ++i) {
+ UIView * nextView = self.animeColorViews[i];
+ prevView.backgroundColor = nextView.backgroundColor;
+ prevView = nextView;
+ }
+ prevView.backgroundColor = color0;
+ }
+}
+
+#pragma mark - SDLStreamingMediaDelegate
+
+- (void)videoStreamingSizeDidUpdate:(CGSize)displaySize {
+ NSLog(@"%s: %@", __PRETTY_FUNCTION__, NSStringFromCGSize(displaySize));
+}
+
+- (void)videoStreamingSizeDoesNotMatch {
+ NSLog(@"%s", __PRETTY_FUNCTION__);
+}
+
+@end
+
diff --git a/Example Apps/Example ObjC/MenuManager.m b/Example Apps/Example ObjC/MenuManager.m
index ff6385196..00a05b377 100644
--- a/Example Apps/Example ObjC/MenuManager.m
+++ b/Example Apps/Example ObjC/MenuManager.m
@@ -62,7 +62,7 @@ NS_ASSUME_NONNULL_BEGIN
}
+ (NSArray<NSString *> *)sdlex_allVehicleDataTypes {
- return @[ACAccelerationPedalPositionMenuName, ACAirbagStatusMenuName, ACBeltStatusMenuName, ACBodyInformationMenuName, ACClusterModeStatusMenuName, ACDeviceStatusMenuName, ACDriverBrakingMenuName, ACECallInfoMenuName, ACElectronicParkBrakeStatus, ACEmergencyEventMenuName, ACEngineOilLifeMenuName, ACEngineTorqueMenuName, ACExternalTemperatureMenuName, ACFuelLevelMenuName, ACFuelLevelStateMenuName, ACFuelRangeMenuName, ACGearStatusMenuName, ACGPSMenuName, ACHeadLampStatusMenuName, ACInstantFuelConsumptionMenuName, ACMyKeyMenuName, ACOdometerMenuName, ACPRNDLMenuName, ACRPMMenuName, ACSpeedMenuName, ACSteeringWheelAngleMenuName, ACTirePressureMenuName, ACTurnSignalMenuName, ACVINMenuName, ACWiperStatusMenuName];
+ return @[ACAccelerationPedalPositionMenuName, ACAirbagStatusMenuName, ACBeltStatusMenuName, ACBodyInformationMenuName, ACClusterModeStatusMenuName, ACDeviceStatusMenuName, ACDriverBrakingMenuName, ACECallInfoMenuName, ACElectronicParkBrakeStatus, ACEmergencyEventMenuName, ACEngineOilLifeMenuName, ACEngineTorqueMenuName, ACExternalTemperatureMenuName, ACFuelLevelMenuName, ACFuelLevelStateMenuName, ACFuelRangeMenuName, ACGPSMenuName, ACHeadLampStatusMenuName, ACInstantFuelConsumptionMenuName, ACMyKeyMenuName, ACOdometerMenuName, ACPRNDLMenuName, ACRPMMenuName, ACSpeedMenuName, ACSteeringWheelAngleMenuName, ACTirePressureMenuName, ACTurnSignalMenuName, ACVINMenuName, ACWiperStatusMenuName];
}
+ (SDLMenuCell *)sdlex_menuCellShowPerformInteractionWithManager:(SDLManager *)manager performManager:(PerformInteractionManager *)performManager {
@@ -81,7 +81,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (SDLMenuCell *)sdlex_menuCellDialNumberWithManager:(SDLManager *)manager {
return [[SDLMenuCell alloc] initWithTitle:ACDialPhoneNumberMenuName icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:PhoneBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:@[ACDialPhoneNumberMenuName] handler:^(SDLTriggerSource _Nonnull triggerSource) {
if (![RPCPermissionsManager isDialNumberRPCAllowedWithManager:manager]) {
- [AlertManager sendAlertWithManager:manager image:nil textField1:AlertDialNumberPermissionsWarningText textField2:nil];
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"This app does not have the required permissions to dial a number" textField2:nil iconName:nil]];
return;
}
@@ -97,9 +97,10 @@ NS_ASSUME_NONNULL_BEGIN
// Non - Media
SDLMenuCell *cell = [[SDLMenuCell alloc] initWithTitle:@"Non - Media (Default)" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {
- [manager.screenManager changeLayout:[[SDLTemplateConfiguration alloc] initWithPredefinedLayout:SDLPredefinedLayoutNonMedia] withCompletionHandler:^(NSError * _Nullable error) {
- if (error != nil) {
- [AlertManager sendAlertWithManager:manager image:nil textField1:errorMessage textField2:nil];
+ SDLSetDisplayLayout* display = [[SDLSetDisplayLayout alloc] initWithPredefinedLayout:SDLPredefinedLayoutNonMedia];
+ [manager sendRequest:display withResponseHandler:^(SDLRPCRequest *request, SDLRPCResponse *response, NSError *error) {
+ if (!response.success) {
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:errorMessage textField2:nil iconName:nil]];
}
}];
}];
@@ -107,9 +108,10 @@ NS_ASSUME_NONNULL_BEGIN
// Graphic With Text
SDLMenuCell *cell2 = [[SDLMenuCell alloc] initWithTitle:@"Graphic With Text" icon:nil voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {
- [manager.screenManager changeLayout:[[SDLTemplateConfiguration alloc] initWithPredefinedLayout:SDLPredefinedLayoutGraphicWithText] withCompletionHandler:^(NSError * _Nullable error) {
- if (error != nil) {
- [AlertManager sendAlertWithManager:manager image:nil textField1:errorMessage textField2:nil];
+ SDLSetDisplayLayout* display = [[SDLSetDisplayLayout alloc] initWithPredefinedLayout:SDLPredefinedLayoutGraphicWithText];
+ [manager sendRequest:display withResponseHandler:^(SDLRPCRequest *request, SDLRPCResponse *response, NSError *error) {
+ if (!response.success) {
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:errorMessage textField2:nil iconName:nil]];
}
}];
}];
@@ -122,7 +124,7 @@ NS_ASSUME_NONNULL_BEGIN
NSMutableArray *submenuItems = [NSMutableArray array];
for (int i = 0; i < 75; i++) {
SDLMenuCell *cell = [[SDLMenuCell alloc] initWithTitle:[NSString stringWithFormat:@"%@ %i", ACSubmenuItemMenuName, i] icon:[SDLArtwork artworkWithImage:[[UIImage imageNamed:MenuBWIconImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] asImageFormat:SDLArtworkImageFormatPNG] voiceCommands:nil handler:^(SDLTriggerSource _Nonnull triggerSource) {
- [AlertManager sendAlertWithManager:manager image:nil textField1:[NSString stringWithFormat:@"You selected %@ %i", ACSubmenuItemMenuName, i] textField2:nil];
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:[NSString stringWithFormat:@"You selected %@ %i", ACSubmenuItemMenuName, i] textField2:nil iconName:nil]];
}];
[submenuItems addObject:cell];
}
@@ -136,11 +138,11 @@ NS_ASSUME_NONNULL_BEGIN
[manager sendRequest:sliderRPC withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) {
if(![response.resultCode isEqualToEnum:SDLResultSuccess]) {
if ([response.resultCode isEqualToEnum:SDLResultTimedOut]) {
- [AlertManager sendAlertWithManager:manager image:nil textField1:AlertSliderTimedOutWarningText textField2:nil];
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"Slider timed out" textField2:nil iconName:nil]];
} else if ([response.resultCode isEqualToEnum:SDLResultAborted]) {
- [AlertManager sendAlertWithManager:manager image:nil textField1:AlertSliderCancelledWarningText textField2:nil];
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"Slider cancelled" textField2:nil iconName:nil]];
} else {
- [AlertManager sendAlertWithManager:manager image:nil textField1:AlertSliderGeneralWarningText textField2:nil];
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"Slider could not be displayed" textField2:nil iconName:nil]];
}
}
}];
@@ -153,11 +155,11 @@ NS_ASSUME_NONNULL_BEGIN
[manager sendRequest:messageRPC withResponseHandler:^(__kindof SDLRPCRequest * _Nullable request, __kindof SDLRPCResponse * _Nullable response, NSError * _Nullable error) {
if(![response.resultCode isEqualToEnum:SDLResultSuccess]) {
if ([response.resultCode isEqualToEnum:SDLResultTimedOut]) {
- [AlertManager sendAlertWithManager:manager image:nil textField1:AlertScrollableMessageTimedOutWarningText textField2:nil];
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"Scrollable Message timed out" textField2:nil iconName:nil]];
} else if ([response.resultCode isEqualToEnum:SDLResultAborted]) {
- [AlertManager sendAlertWithManager:manager image:nil textField1:AlertScrollableMessageCancelledWarningText textField2:nil];
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"Scrollable Message cancelled" textField2:nil iconName:nil]];
} else {
- [AlertManager sendAlertWithManager:manager image:nil textField1:AlertScrollableMessageGeneralWarningText textField2:nil];
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"Scrollable Message could not be displayed" textField2:nil iconName:nil]];
}
}
}];
@@ -168,13 +170,13 @@ NS_ASSUME_NONNULL_BEGIN
+ (SDLVoiceCommand *)sdlex_voiceCommandStartWithManager:(SDLManager *)manager {
return [[SDLVoiceCommand alloc] initWithVoiceCommands:@[VCStop] handler:^{
- [AlertManager sendAlertWithManager:manager image:nil textField1:[NSString stringWithFormat:@"%@ voice command selected!", VCStop] textField2:nil];
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:[NSString stringWithFormat:@"%@ voice command selected!", VCStop] textField2:nil iconName:nil]];
}];
}
+ (SDLVoiceCommand *)sdlex_voiceCommandStopWithManager:(SDLManager *)manager {
return [[SDLVoiceCommand alloc] initWithVoiceCommands:@[VCStart] handler:^{
- [AlertManager sendAlertWithManager:manager image:nil textField1:[NSString stringWithFormat:@"%@ voice command selected!", VCStart] textField2:nil];
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:[NSString stringWithFormat:@"%@ voice command selected!", VCStart] textField2:nil iconName:nil]];
}];
}
diff --git a/Example Apps/Example ObjC/Models/SDLTCPConfig.h b/Example Apps/Example ObjC/Models/SDLTCPConfig.h
new file mode 100644
index 000000000..8b5491282
--- /dev/null
+++ b/Example Apps/Example ObjC/Models/SDLTCPConfig.h
@@ -0,0 +1,22 @@
+//
+// SDLTCPConfig.h
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Leonid Lokhmatov on 5/19/20.
+// Copyright © 2018 Luxoft. All rights reserved
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface SDLTCPConfig : NSObject
+
++ (instancetype)configWithHost:(NSString*)host port:(UInt16)port;
+
+@property (strong, nonatomic) NSString *ipAddress;
+@property (assign, nonatomic) UInt16 port;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Example Apps/Example ObjC/Models/SDLTCPConfig.m b/Example Apps/Example ObjC/Models/SDLTCPConfig.m
new file mode 100644
index 000000000..9000c1987
--- /dev/null
+++ b/Example Apps/Example ObjC/Models/SDLTCPConfig.m
@@ -0,0 +1,25 @@
+//
+// SDLTCPConfig.m
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Leonid Lokhmatov on 5/19/20.
+// Copyright © 2018 Luxoft. All rights reserved
+//
+
+#import "SDLTCPConfig.h"
+
+@implementation SDLTCPConfig
+
++ (instancetype)configWithHost:(NSString*)host port:(UInt16)port {
+ return [[self alloc] initWithHost:host port:port];
+}
+
+- (instancetype)initWithHost:(NSString*)host port:(UInt16)port {
+ if ((self = [super init])) {
+ _ipAddress = host;
+ _port = port;
+ }
+ return self;
+}
+
+@end
diff --git a/Example Apps/Example ObjC/Models/VideoStreamSettings.h b/Example Apps/Example ObjC/Models/VideoStreamSettings.h
new file mode 100644
index 000000000..e1ab7a69f
--- /dev/null
+++ b/Example Apps/Example ObjC/Models/VideoStreamSettings.h
@@ -0,0 +1,22 @@
+//
+// VideoStreamSettings.h
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Leonid Lokhmatov on 7/28/20.
+// Copyright © 2018 Luxoft. All rights reserved
+//
+
+#import <Foundation/Foundation.h>
+
+@class SDLSupportedStreamingRange;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface VideoStreamSettings : NSObject
+@property (nonatomic, copy) NSString * SDLVersion;
+@property (strong, nonatomic, nullable) SDLSupportedStreamingRange *supportedLandscapeStreamingRange;
+@property (strong, nonatomic, nullable) SDLSupportedStreamingRange *supportedPortraitStreamingRange;
+- (NSString *)detailedDescription;
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Example Apps/Example ObjC/Models/VideoStreamSettings.m b/Example Apps/Example ObjC/Models/VideoStreamSettings.m
new file mode 100644
index 000000000..b0f8a9a63
--- /dev/null
+++ b/Example Apps/Example ObjC/Models/VideoStreamSettings.m
@@ -0,0 +1,18 @@
+//
+// VideoStreamSettings.m
+// SmartDeviceLink-Example-ObjC
+//
+// Created by Leonid Lokhmatov on 7/28/20.
+// Copyright © 2018 Luxoft. All rights reserved
+//
+
+#import "VideoStreamSettings.h"
+#import "SDLSupportedStreamingRange.h"
+
+@implementation VideoStreamSettings
+
+- (NSString *)detailedDescription {
+ return [NSString stringWithFormat:@"SDLVersion: %@\nsupportedLandscapeStreamingRange: %@\nsupportedPortraitStreamingRange: %@", self.SDLVersion, self.supportedLandscapeStreamingRange, self.supportedPortraitStreamingRange];
+}
+
+@end
diff --git a/Example Apps/Example ObjC/ProxyManager.h b/Example Apps/Example ObjC/ProxyManager.h
index 7226c1ac4..5a3219b9d 100644
--- a/Example Apps/Example ObjC/ProxyManager.h
+++ b/Example Apps/Example ObjC/ProxyManager.h
@@ -2,7 +2,8 @@
// ProxyManager.h
// SmartDeviceLink-iOS
-#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+#import "SDLTCPConfig.h"
@class SDLManager;
@@ -17,15 +18,22 @@ typedef NS_ENUM(NSUInteger, ProxyState) {
ProxyStateConnected
};
+@protocol SDLStreamingMediaDelegate;
+@class VideoStreamSettings;
+
NS_ASSUME_NONNULL_BEGIN
@interface ProxyManager : NSObject
@property (assign, nonatomic, readonly) ProxyState state;
-@property (strong, nonatomic) SDLManager *sdlManager;
+@property (strong, nonatomic, nullable) SDLManager *sdlManager;
+
+@property (strong, nonatomic, nullable) UIViewController<SDLStreamingMediaDelegate> *videoVC;
+@property (strong, nonatomic, nullable) VideoStreamSettings *videoStreamSettings;
+ (instancetype)sharedManager;
- (void)startWithProxyTransportType:(ProxyTransportType)proxyTransportType;
+- (void)startProxyTCP:(SDLTCPConfig*)tcpConfig;
- (void)stopConnection;
@end
diff --git a/Example Apps/Example ObjC/ProxyManager.m b/Example Apps/Example ObjC/ProxyManager.m
index 0d13454d7..8d4155ed0 100644
--- a/Example Apps/Example ObjC/ProxyManager.m
+++ b/Example Apps/Example ObjC/ProxyManager.m
@@ -13,6 +13,9 @@
#import "SmartDeviceLink.h"
#import "SubscribeButtonManager.h"
#import "VehicleDataManager.h"
+#import "SDLCarWindow.h"
+#import "SDLStreamingMediaDelegate.h"
+#import "VideoStreamSettings.h"
NS_ASSUME_NONNULL_BEGIN
@@ -29,6 +32,11 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, copy, nullable) RefreshUIHandler refreshUIHandler;
@end
+//#Touch_Input:
+@interface ProxyManager (SDLTouchManagerDelegate) <SDLTouchManagerDelegate>
+- (void)touchEventAvailable:(SDLRPCNotificationNotification *)notification;
+@end
+
@implementation ProxyManager
@@ -53,6 +61,10 @@ NS_ASSUME_NONNULL_BEGIN
_state = ProxyStateStopped;
_firstHMILevel = SDLHMILevelNone;
+ //#Touch_Input: Pre sdl_ios v6.3
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(touchEventAvailable:) name:SDLDidReceiveTouchEventNotification object:nil];
+
+
return self;
}
@@ -74,7 +86,7 @@ NS_ASSUME_NONNULL_BEGIN
[RPCPermissionsManager setupPermissionsCallbacksWithManager:weakSelf.sdlManager];
[weakSelf sdlex_showInitialData];
- SDLLogD(@"SDL file manager storage: %lu mb", self.sdlManager.fileManager.bytesAvailable / 1024 / 1024);
+ SDLLogD(@"SDL file manager storage: %lu mb", (long)self.sdlManager.fileManager.bytesAvailable / 1024 / 1024);
}];
}
@@ -96,6 +108,87 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - SDL Configuration
+- (void)startProxyTCP:(SDLTCPConfig*)tcpConfig {
+ assert(nil != tcpConfig);
+ if (self.sdlManager) {
+ [self.sdlManager stop];
+ self.sdlManager = nil;
+ }
+
+ SDLLifecycleConfiguration *lifecycleConfiguration = [SDLLifecycleConfiguration debugConfigurationWithAppName:ExampleAppName fullAppId:ExampleFullAppId ipAddress:tcpConfig.ipAddress port:tcpConfig.port];
+
+ UIImage *appLogo = [[UIImage imageNamed:ExampleAppLogoName] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
+ SDLArtwork *appIconArt = [SDLArtwork persistentArtworkWithImage:appLogo asImageFormat:SDLArtworkImageFormatPNG];
+
+ lifecycleConfiguration.shortAppName = ExampleAppNameShort;
+ lifecycleConfiguration.appIcon = appIconArt;
+ lifecycleConfiguration.voiceRecognitionCommandNames = @[ExampleAppNameTTS];
+ lifecycleConfiguration.ttsName = [SDLTTSChunk textChunksFromString:ExampleAppName];
+ lifecycleConfiguration.language = SDLLanguageEnUs;
+ lifecycleConfiguration.languagesSupported = @[SDLLanguageEnUs, SDLLanguageFrCa, SDLLanguageEsMx];
+ lifecycleConfiguration.appType = SDLAppHMITypeNavigation;
+
+ SDLRGBColor *green = [[SDLRGBColor alloc] initWithRed:126 green:188 blue:121];
+ SDLRGBColor *white = [[SDLRGBColor alloc] initWithRed:249 green:251 blue:254];
+ SDLRGBColor *darkGrey = [[SDLRGBColor alloc] initWithRed:57 green:78 blue:96];
+ SDLRGBColor *grey = [[SDLRGBColor alloc] initWithRed:186 green:198 blue:210];
+ lifecycleConfiguration.dayColorScheme = [[SDLTemplateColorScheme alloc] initWithPrimaryRGBColor:green secondaryRGBColor:grey backgroundRGBColor:white];
+ lifecycleConfiguration.nightColorScheme = [[SDLTemplateColorScheme alloc] initWithPrimaryRGBColor:green secondaryRGBColor:grey backgroundRGBColor:darkGrey];
+
+ SDLLockScreenConfiguration *lockScreenConfiguration = [SDLLockScreenConfiguration enabledConfigurationWithAppIcon:[UIImage imageNamed:ExampleAppLogoName] backgroundColor:nil];
+ SDLConfiguration *config = [[SDLConfiguration alloc] initWithLifecycle:lifecycleConfiguration lockScreen:lockScreenConfiguration logging:[self.class sdlex_logConfiguration] fileManager:[SDLFileManagerConfiguration defaultConfiguration] encryption:[SDLEncryptionConfiguration defaultConfiguration]];
+
+
+
+
+ SDLEncryptionConfiguration *encryptionConfig = [SDLEncryptionConfiguration defaultConfiguration];//[[SDLEncryptionConfiguration alloc] initWithSecurityManagers:@[OEMSecurityManager.self] delegate:self];
+ SDLStreamingMediaConfiguration *streamingConfig = nil;
+// SDLStreamingMediaConfiguration *streamingConfig = [SDLStreamingMediaConfiguration insecureConfiguration];
+
+ if (self.videoVC) {
+ streamingConfig = [SDLStreamingMediaConfiguration autostreamingInsecureConfigurationWithInitialViewController:self.videoVC];
+ streamingConfig.delegate = self.videoVC;
+ streamingConfig.supportedPortraitStreamingRange = self.videoStreamSettings.supportedPortraitStreamingRange;
+ streamingConfig.supportedLandscapeStreamingRange = self.videoStreamSettings.supportedLandscapeStreamingRange;
+ } else {
+ streamingConfig = [SDLStreamingMediaConfiguration insecureConfiguration];
+ }
+
+ SDLConfiguration *config2 = [[SDLConfiguration alloc] initWithLifecycle:lifecycleConfiguration lockScreen:lockScreenConfiguration logging:[self.class sdlex_logConfiguration] streamingMedia:streamingConfig fileManager:[SDLFileManagerConfiguration defaultConfiguration] encryption:encryptionConfig];
+
+
+ self.sdlManager = [[SDLManager alloc] initWithConfiguration:config2 delegate:self];
+ self.sdlManager.sdlMsgVersionString = self.videoStreamSettings.SDLVersion;
+
+ __weak typeof (self) weakSelf = self;
+ [self.sdlManager startWithReadyHandler:^(BOOL success, NSError * _Nullable error) {
+ if (!success) {
+ NSLog(@"SDL start error: %@", error);
+ [weakSelf sdlex_updateProxyState:ProxyStateStopped];
+ return;
+ }
+
+ weakSelf.vehicleDataManager = [[VehicleDataManager alloc] initWithManager:weakSelf.sdlManager refreshUIHandler:weakSelf.refreshUIHandler];
+ weakSelf.performManager = [[PerformInteractionManager alloc] initWithManager:weakSelf.sdlManager];
+ weakSelf.buttonManager = [[ButtonManager alloc] initWithManager:weakSelf.sdlManager refreshUIHandler:weakSelf.refreshUIHandler];
+
+ [weakSelf sdlex_updateProxyState:ProxyStateConnected];
+ [RPCPermissionsManager setupPermissionsCallbacksWithManager:weakSelf.sdlManager];
+ [weakSelf sdlex_showInitialData];
+
+ //#Touch_Input, decide who is the delegate
+ if ([weakSelf.videoVC conformsToProtocol:@protocol(SDLTouchManagerDelegate)]) {
+ weakSelf.sdlManager.streamManager.touchManager.touchEventDelegate = (id<SDLTouchManagerDelegate>) weakSelf.videoVC;
+ } else {
+ weakSelf.sdlManager.streamManager.touchManager.touchEventDelegate = self;
+ }
+
+
+
+ NSLog(@"SDL started, file manager storage: %lu mb", (long)weakSelf.sdlManager.fileManager.bytesAvailable / 1024 / 1024);
+ }];
+}
+
- (void)startWithProxyTransportType:(ProxyTransportType)proxyTransportType {
[self sdlex_updateProxyState:ProxyStateSearchingForConnection];
@@ -114,6 +207,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)sdlex_setupConfigurationWithLifecycleConfiguration:(SDLLifecycleConfiguration *)lifecycleConfiguration {
if (self.sdlManager != nil) {
// Manager already created, just start it again.
+ //TODO: the ip might change but we still start it with the old config
[self sdlex_startManager];
return;
}
@@ -153,6 +247,9 @@ NS_ASSUME_NONNULL_BEGIN
logConfig.targets = [logConfig.targets setByAddingObject:[SDLLogTargetFile logger]];
logConfig.globalLogLevel = SDLLogLevelDebug;
+ //TODO: fix it when done
+// logConfig.globalLogLevel = SDLLogLevelVerbose;
+
return logConfig;
}
@@ -164,15 +261,13 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)sdlex_showInitialData {
- // Send static menu items and soft buttons
- [self sdlex_createMenus];
- self.sdlManager.screenManager.softButtonObjects = [self.buttonManager allScreenSoftButtons];
-
if (![self.sdlManager.hmiLevel isEqualToEnum:SDLHMILevelFull]) { return; }
- [self.sdlManager.screenManager changeLayout:[[SDLTemplateConfiguration alloc] initWithPredefinedLayout:SDLPredefinedLayoutNonMedia] withCompletionHandler:nil];
+ SDLSetDisplayLayout *setDisplayLayout = [[SDLSetDisplayLayout alloc] initWithPredefinedLayout:SDLPredefinedLayoutNonMedia];
+ [self.sdlManager sendRequest:setDisplayLayout];
[self sdlex_updateScreen];
+ self.sdlManager.screenManager.softButtonObjects = [self.buttonManager allScreenSoftButtons];
}
- (nullable RefreshUIHandler)refreshUIHandler {
@@ -243,19 +338,22 @@ NS_ASSUME_NONNULL_BEGIN
/// @param oldLevel The old HMI Level
/// @param newLevel The new HMI Level
- (void)hmiLevel:(SDLHMILevel)oldLevel didChangeToLevel:(SDLHMILevel)newLevel {
+ NSLog(@"hmiLevel:changed:HMI[%@-->%@]", oldLevel, newLevel);
+
if (![newLevel isEqualToEnum:SDLHMILevelNone] && ([self.firstHMILevel isEqualToEnum:SDLHMILevelNone])) {
// This is our first time in a non-NONE state
self.firstHMILevel = newLevel;
+ // Send static menu items.
+ [self sdlex_createMenus];
+
// Subscribe to vehicle data.
[self.vehicleDataManager subscribeToVehicleOdometer];
-
- //Handle initial launch
- [self sdlex_showInitialData];
}
if ([newLevel isEqualToEnum:SDLHMILevelFull]) {
// 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
@@ -264,12 +362,19 @@ NS_ASSUME_NONNULL_BEGIN
} else if ([newLevel isEqualToEnum:SDLHMILevelNone]) {
// The SDL app is not yet running
}
+
+ // Preventing Device Sleep
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [UIApplication sharedApplication].idleTimerDisabled = ![newLevel isEqualToEnum:SDLHMILevelNone];
+ });
}
/// 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 {
+ NSLog(@"systemContext:changed:[%@-->%@]", oldContext, newContext);
+
if ([newContext isEqualToEnum:SDLSystemContextAlert]) {
// The SDL app's screen is obscured by an alert
} else if ([newContext isEqualToEnum:SDLSystemContextHMIObscured]) {
@@ -287,6 +392,8 @@ NS_ASSUME_NONNULL_BEGIN
/// @param oldState The old audio streaming state
/// @param newState The new audio streaming state
- (void)audioStreamingState:(nullable SDLAudioStreamingState)oldState didChangeToState:(SDLAudioStreamingState)newState {
+ NSLog(@"audioStreamingState:changed:[%@-->%@]", oldState, newState);
+
if ([newState isEqualToEnum:SDLAudioStreamingStateAudible]) {
// The SDL app's audio can be heard
} else if ([newState isEqualToEnum:SDLAudioStreamingStateNotAudible]) {
@@ -301,6 +408,7 @@ NS_ASSUME_NONNULL_BEGIN
/// @param hmiLanguage The head unit's current HMI language
/// @return A SDLLifecycleConfigurationUpdate object
- (nullable SDLLifecycleConfigurationUpdate *)managerShouldUpdateLifecycleToLanguage:(SDLLanguage)language hmiLanguage:(SDLLanguage)hmiLanguage {
+>>>>>>> develop
SDLLifecycleConfigurationUpdate *update = [[SDLLifecycleConfigurationUpdate alloc] init];
if ([hmiLanguage isEqualToEnum:SDLLanguageEnUs]) {
@@ -320,4 +428,68 @@ NS_ASSUME_NONNULL_BEGIN
@end
+//#Touch_Input:
+@implementation ProxyManager (SDLTouchManagerDelegate)
+
+- (void)touchManager:(SDLTouchManager *)manager didReceiveSingleTapForView:(UIView *_Nullable)view atPoint:(CGPoint)point {
+ NSLog(@"%s: %@:%@ > %@", __PRETTY_FUNCTION__, NSStringFromClass(view.class), NSStringFromCGRect(view.frame), NSStringFromCGPoint(point));
+}
+
+- (void)touchManager:(SDLTouchManager *)manager didReceiveDoubleTapForView:(UIView *_Nullable)view atPoint:(CGPoint)point {
+ NSLog(@"%s: %@ > %@", __PRETTY_FUNCTION__, view, NSStringFromCGPoint(point));
+}
+
+// panning
+- (void)touchManager:(SDLTouchManager *)manager panningDidStartInView:(UIView *_Nullable)view atPoint:(CGPoint)point {
+ NSLog(@"%s: %@ > %@", __PRETTY_FUNCTION__, view, NSStringFromCGPoint(point));
+}
+
+- (void)touchManager:(SDLTouchManager *)manager didReceivePanningFromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint {
+ NSLog(@"%s: %@-->%@", __PRETTY_FUNCTION__, NSStringFromCGPoint(fromPoint), NSStringFromCGPoint(toPoint));
+}
+
+- (void)touchManager:(SDLTouchManager *)manager panningDidEndInView:(UIView *_Nullable)view atPoint:(CGPoint)point {
+ NSLog(@"%s: %@ > %@", __PRETTY_FUNCTION__, view, NSStringFromCGPoint(point));
+}
+
+- (void)touchManager:(SDLTouchManager *)manager panningCanceledAtPoint:(CGPoint)point {
+ NSLog(@"%s: %@", __PRETTY_FUNCTION__, NSStringFromCGPoint(point));
+}
+
+// pinch
+- (void)touchManager:(SDLTouchManager *)manager pinchDidStartInView:(UIView *_Nullable)view atCenterPoint:(CGPoint)point {
+ NSLog(@"%s: %@ > %@", __PRETTY_FUNCTION__, view, NSStringFromCGPoint(point));
+}
+
+- (void)touchManager:(SDLTouchManager *)manager didReceivePinchAtCenterPoint:(CGPoint)point withScale:(CGFloat)scale {
+ NSLog(@"%s: %@ : %2.2f", __PRETTY_FUNCTION__, NSStringFromCGPoint(point), scale);
+}
+
+- (void)touchManager:(SDLTouchManager *)manager didReceivePinchInView:(UIView *_Nullable)view atCenterPoint:(CGPoint)point withScale:(CGFloat)scale {
+ NSLog(@"%s: %@ > %@", __PRETTY_FUNCTION__, view, NSStringFromCGPoint(point));
+}
+
+- (void)touchManager:(SDLTouchManager *)manager pinchDidEndInView:(UIView *_Nullable)view atCenterPoint:(CGPoint)point {
+ NSLog(@"%s: %@ > %@", __PRETTY_FUNCTION__, view, NSStringFromCGPoint(point));
+}
+
+- (void)touchManager:(SDLTouchManager *)manager pinchCanceledAtCenterPoint:(CGPoint)point {
+ NSLog(@"%s: %@", __PRETTY_FUNCTION__, NSStringFromCGPoint(point));
+}
+
+/// touch notification
+- (void)touchEventAvailable:(SDLRPCNotificationNotification *)notification {
+ if (![notification.notification isKindOfClass:SDLOnTouchEvent.class]) {
+ return;
+ }
+// SDLOnTouchEvent *touchEvent = (SDLOnTouchEvent *)notification.notification;
+//
+// // Grab something like type
+// SDLTouchType type = touchEvent.type;
+// NSLog(@"%s > %@ : %@", __PRETTY_FUNCTION__, type, touchEvent);
+}
+
+@end
+
+
NS_ASSUME_NONNULL_END
diff --git a/Example Apps/Example ObjC/RPCPermissionsManager.m b/Example Apps/Example ObjC/RPCPermissionsManager.m
index 3370f18c2..93d2755e6 100644
--- a/Example Apps/Example ObjC/RPCPermissionsManager.m
+++ b/Example Apps/Example ObjC/RPCPermissionsManager.m
@@ -96,7 +96,7 @@ NS_ASSUME_NONNULL_BEGIN
* @return A unique identifier for the subscription. This can be used to later to unsubscribe from the notifications.
*/
+ (SDLPermissionObserverIdentifier)sdlex_subscribeGroupPermissionsWithManager:(SDLManager *)manager permissionElements:(NSArray<SDLPermissionElement *> *)permissionElements groupType:(SDLPermissionGroupType)groupType {
- SDLPermissionObserverIdentifier observerId = [manager.permissionManager subscribeToRPCPermissions:permissionElements groupType:groupType withHandler:^(NSDictionary<SDLRPCFunctionName, SDLRPCPermissionStatus *> * _Nonnull change, SDLPermissionGroupStatus status) {
+ 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;
diff --git a/Example Apps/Example ObjC/SmartDeviceLink-Example-ObjC-Info.plist b/Example Apps/Example ObjC/SmartDeviceLink-Example-ObjC-Info.plist
index 8e00f2ea6..5adff536f 100644
--- a/Example Apps/Example ObjC/SmartDeviceLink-Example-ObjC-Info.plist
+++ b/Example Apps/Example ObjC/SmartDeviceLink-Example-ObjC-Info.plist
@@ -19,7 +19,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1</string>
+ <string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSApplicationCategoryType</key>
<string></string>
<key>LSRequiresIPhoneOS</key>
diff --git a/Example Apps/Example ObjC/VehicleDataManager.m b/Example Apps/Example ObjC/VehicleDataManager.m
index f6192777a..bcbf1f362 100644
--- a/Example Apps/Example ObjC/VehicleDataManager.m
+++ b/Example Apps/Example ObjC/VehicleDataManager.m
@@ -138,17 +138,22 @@ NS_ASSUME_NONNULL_BEGIN
+ (void)getAllVehicleDataWithManager:(SDLManager *)manager triggerSource:(SDLTriggerSource)triggerSource vehicleDataType:(NSString *)vehicleDataType {
SDLLogD(@"Checking if app has permission to access vehicle data...");
if (![manager.permissionManager isRPCNameAllowed:SDLRPCFunctionNameGetVehicleData]) {
- [AlertManager sendAlertWithManager:manager image:nil textField1:AlertVehicleDataPermissionsWarningText textField2:nil];
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"This app does not have the required permissions to access vehicle data" textField2:nil iconName:nil]];
return;
}
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 gearStatus:@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 windowStatus:@YES];
+ 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 eCallInfo:@YES airbagStatus:@YES emergencyEvent:@YES clusterModeStatus:@YES myKey:@YES handsOffSteering:@YES];
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ 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) {
if (error || ![response isKindOfClass:SDLGetVehicleDataResponse.class]) {
- [AlertManager sendAlertWithManager:manager image:nil textField1:AlertVehicleDataGeneralWarningText textField2:nil];
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"Something went wrong while getting vehicle data" textField2:nil iconName:nil]];
return;
}
@@ -178,7 +183,7 @@ NS_ASSUME_NONNULL_BEGIN
alertMessage = [TextValidator validateText:alertMessage length:200];
if ([triggerSource isEqualToEnum:SDLTriggerSourceMenu]) {
- [AlertManager sendAlertWithManager:manager image:nil textField1:alertTitle textField2:alertMessage];
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:alertTitle textField2:alertMessage iconName:nil]];
} else {
NSString *spokenAlert = alertMessage ?: alertTitle;
[manager sendRequest:[[SDLSpeak alloc] initWithTTS:spokenAlert]];
@@ -216,13 +221,17 @@ NS_ASSUME_NONNULL_BEGIN
} else if ([vehicleDataType isEqualToString:ACExternalTemperatureMenuName]) {
vehicleDataDescription = vehicleData.externalTemperature.description;
} else if ([vehicleDataType isEqualToString:ACFuelLevelMenuName]) {
- vehicleDataDescription = vehicleData.fuelRange.firstObject.level.description;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ vehicleDataDescription = vehicleData.fuelLevel.description;
+#pragma clang diagnostic pop
} else if ([vehicleDataType isEqualToString:ACFuelLevelStateMenuName]) {
- vehicleDataDescription = vehicleData.fuelRange.firstObject.levelState.description;
+#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:ACGearStatusMenuName]) {
- vehicleDataDescription = vehicleData.gearStatus.description;
} else if ([vehicleDataType isEqualToString:ACGPSMenuName]) {
vehicleDataDescription = vehicleData.gps.description;
} else if ([vehicleDataType isEqualToString:ACHeadLampStatusMenuName]) {
@@ -234,7 +243,7 @@ NS_ASSUME_NONNULL_BEGIN
} else if ([vehicleDataType isEqualToString:ACOdometerMenuName]) {
vehicleDataDescription = vehicleData.odometer.description;
} else if ([vehicleDataType isEqualToString:ACPRNDLMenuName]) {
- vehicleDataDescription = vehicleData.gearStatus.actualGear.description;
+ vehicleDataDescription = vehicleData.prndl.description;
} else if ([vehicleDataType isEqualToString:ACSpeedMenuName]) {
vehicleDataDescription = vehicleData.speed.description;
} else if ([vehicleDataType isEqualToString:ACSteeringWheelAngleMenuName]) {
@@ -262,7 +271,7 @@ NS_ASSUME_NONNULL_BEGIN
SDLLogD(@"Checking phone call capability");
[manager.systemCapabilityManager updateCapabilityType:SDLSystemCapabilityTypePhoneCall completionHandler:^(NSError * _Nullable error, SDLSystemCapabilityManager * _Nonnull systemCapabilityManager) {
if (!systemCapabilityManager.phoneCapability) {
- [AlertManager sendAlertWithManager:manager image:nil textField1:AlertDialNumberPermissionsWarningText textField2:nil];
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"The head unit does not support the phone call capability" textField2:nil iconName:nil]];
return;
}
@@ -270,7 +279,7 @@ NS_ASSUME_NONNULL_BEGIN
SDLLogD(@"Dialing phone number %@", phoneNumber);
[self sdlex_dialPhoneNumber:phoneNumber manager:manager];
} else {
- [AlertManager sendAlertWithManager:manager image:nil textField1:AlertDialNumberUnavailableWarningText textField2:nil];
+ [manager sendRequest:[AlertManager alertWithMessageAndCloseButton:@"The dial number feature is unavailable for this head unit" textField2:nil iconName:nil]];
}
}];
}
diff --git a/Example Apps/Example Swift/AlertManager.swift b/Example Apps/Example Swift/AlertManager.swift
index bf0f1af96..718210777 100644
--- a/Example Apps/Example Swift/AlertManager.swift
+++ b/Example Apps/Example Swift/AlertManager.swift
@@ -10,58 +10,18 @@ import Foundation
import SmartDeviceLink
class AlertManager {
- /// Sends an alert with up to two lines of text, an image, and a close button that will dismiss the alert when tapped.
- /// - Parameters:
- /// - imageName: The name of the image to upload
- /// - textField1: The first line of text in the alert
- /// - textField2: The second line of text in the alert
- /// - sdlManager: The SDLManager
- class func sendAlert(imageName: String? = nil, textField1: String, textField2: String? = nil, sdlManager: SDLManager) {
- let okSoftButton = SDLSoftButton(type: .text, text: AlertOKButtonText, image: nil, highlighted: true, buttonId: 10000, systemAction: nil, handler: nil)
- let alert = SDLAlert(alertText1: textField1, alertText2: textField2, alertText3: nil, softButtons: [okSoftButton], playTone: true, ttsChunks: nil, duration: 5000, progressIndicator: false, alertIcon: nil, cancelID: 0)
-
- if let imageName = imageName {
- sendImage(imageName, sdlManager: sdlManager) { (success, artworkName) in
- if success {
- alert.alertIcon = SDLImage(name: artworkName, isTemplate: true)
- }
- sdlManager.send(alert)
- }
- } else {
- sdlManager.send(alert)
- }
- }
-
- /// Sends a subtle alert with up to two lines of text, and an image.
- /// - Parameters:
- /// - imageName: The name of the image to upload
- /// - textField1: The first line of text in the alert
- /// - textField2: The second line of text in the alert
- /// - sdlManager: The SDLManager
- class func sendSubtleAlert(imageName: String? = nil, textField1: String, textField2: String? = nil, sdlManager: SDLManager) {
- let subtleAlert = SDLSubtleAlert(alertText1: textField1, alertText2: textField2, alertIcon: nil, ttsChunks: nil, duration: nil, softButtons: nil, cancelID: NSNumber(0))
-
- if let imageName = imageName {
- sendImage(imageName, sdlManager: sdlManager) { (success, artworkName) in
- if success {
- subtleAlert.alertIcon = SDLImage(name: artworkName, isTemplate: true)
- }
- sdlManager.send(subtleAlert)
- }
- } else {
- sdlManager.send(subtleAlert)
- }
+ private class var okSoftButton: SDLSoftButton {
+ return SDLSoftButton(type: .text, text: AlertOKButtonText, image: nil, highlighted: true, buttonId: 1, systemAction: nil, handler: nil)
}
- /// Helper method for uploading an image before it is shown in an alert
+ /// Creates an alert with up to two lines of text, an image, and a close button that will dismiss the alert when tapped.
+ ///
/// - Parameters:
- /// - imageName: The name of the image to upload
- /// - sdlManager: The SDLManager
- /// - completionHandler: Handler called when the artwork has finished uploading with the success of the upload and the name of the uploaded image.
- private class func sendImage(_ imageName: String, sdlManager: SDLManager, completionHandler: @escaping ((_ success: Bool, _ artwork: String) -> ())) {
- let artwork = SDLArtwork(image: UIImage(named: imageName)!.withRenderingMode(.alwaysTemplate), persistent: false, as: .PNG)
- sdlManager.fileManager.upload(artwork: artwork) { (success, artworkName, bytesAvailable, error) in
- return completionHandler(success, artworkName)
- }
+ /// - textField1: The first line of a message to display in the alert
+ /// - textField2: The second line of a message to display in the alert
+ /// - iconName: The name of the uploaded icon artwork
+ /// - Returns: An SDLAlert object
+ class func alertWithMessageAndCloseButton(_ textField1: String, textField2: String? = nil, iconName: String? = nil) -> SDLAlert {
+ return SDLAlert(alertText1: textField1, alertText2: textField2, alertText3: nil, softButtons: [okSoftButton], playTone: true, ttsChunks: nil, duration: 5000, progressIndicator: false, alertIcon: (iconName != nil) ? SDLImage(name: iconName!, isTemplate: true) : nil, cancelID: 0)
}
}
diff --git a/Example Apps/Example Swift/AudioManager.swift b/Example Apps/Example Swift/AudioManager.swift
index 8300bcb18..6ea7e8813 100644
--- a/Example Apps/Example Swift/AudioManager.swift
+++ b/Example Apps/Example Swift/AudioManager.swift
@@ -19,6 +19,7 @@ fileprivate enum SpeechRecognitionAuthState {
case authorized, notAuthorized, badRegion
}
+@available(iOS 10.0, *)
class AudioManager: NSObject {
fileprivate let sdlManager: SDLManager
fileprivate var audioData: Data?
@@ -59,7 +60,7 @@ class AudioManager: NSObject {
func startRecording() {
guard speechRecognitionAuthState == .authorized else {
SDLLog.w("This app does not have permission to access the Speech Recognition API")
- AlertManager.sendAlert(textField1: AlertSpeechPermissionsWarningText, sdlManager: sdlManager)
+ sdlManager.send(AlertManager.alertWithMessageAndCloseButton("You must give this app permission to access Speech Recognition"))
return
}
@@ -87,6 +88,7 @@ class AudioManager: NSObject {
// MARK: - Audio Pass Thru Notifications
+@available(iOS 10.0, *)
private extension AudioManager {
/// SDL streams the audio data as it is collected.
var audioDataReceivedHandler: SDLAudioPassThruHandler? {
@@ -104,19 +106,20 @@ private extension AudioManager {
/// Called when `PerformAudioPassThru` request times out or when a `EndAudioPassThru` request is sent
var audioPassThruEndedHandler: SDLResponseHandler? {
return { [weak self] (request, response, error) in
- guard let self = self, let response = response else { return }
+ guard let response = response else { return }
switch response.resultCode {
case .success: // The `PerformAudioPassThru` timed out or the "Done" button was pressed in the pop-up.
SDLLog.d("Audio Pass Thru ended successfully")
- AlertManager.sendAlert(textField1: "You said: \(self.speechTranscription.isEmpty ? "No speech detected" : self.speechTranscription)", sdlManager: self.sdlManager)
+ guard let speechTranscription = self?.speechTranscription else { return }
+ self?.sdlManager.send(AlertManager.alertWithMessageAndCloseButton("You said: \(speechTranscription.isEmpty ? "No speech detected" : speechTranscription)"))
case .aborted: // The "Cancel" button was pressed in the pop-up. Ignore this audio pass thru.
SDLLog.d("Audio recording canceled")
default:
SDLLog.d("Audio recording not successful: \(response.resultCode)")
}
- self.stopSpeechRecognitionTask()
+ self?.stopSpeechRecognitionTask()
}
}
@@ -142,6 +145,7 @@ private extension AudioManager {
// MARK: - Speech Recognition
+@available(iOS 10.0, *)
private extension AudioManager {
/// Configures speech recognition
func startSpeechRecognitionTask() {
@@ -183,6 +187,7 @@ private extension AudioManager {
// MARK: - Speech Recognition Authorization
+@available(iOS 10.0, *)
extension AudioManager: SFSpeechRecognizerDelegate {
func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) {
speechRecognitionAuthState = AudioManager.checkAuthorization(speechRecognizer: speechRecognizer)
diff --git a/Example Apps/Example Swift/ButtonManager.swift b/Example Apps/Example Swift/ButtonManager.swift
index 02d3f7962..e0953accc 100644
--- a/Example Apps/Example Swift/ButtonManager.swift
+++ b/Example Apps/Example Swift/ButtonManager.swift
@@ -16,7 +16,7 @@ class ButtonManager: NSObject {
fileprivate let sdlManager: SDLManager!
fileprivate var refreshUIHandler: RefreshUIHandler?
- /// Textfields are visible if true; hidden if false
+ /// SDL UI textfields are visible if true; hidden if false
public fileprivate(set) var textEnabled: Bool {
didSet {
guard let refreshUIHandler = refreshUIHandler else { return }
@@ -24,20 +24,20 @@ class ButtonManager: NSObject {
}
}
- /// UI images are visible if true; hidden if false
+ /// SDL UI images are visible if true; hidden if false
public fileprivate(set) var imagesEnabled: Bool {
didSet {
- guard let refreshUIHandler = refreshUIHandler else { return }
+ guard let refreshUIHandler = refreshUIHandler, let alertSoftButton = sdlManager.screenManager.softButtonObjectNamed(AlertSoftButton) else { return }
+ alertSoftButton.transitionToNextState()
refreshUIHandler()
}
}
- private var isSubtleAlertAllowed: Bool {
- return sdlManager.permissionManager.isRPCNameAllowed(.subtleAlert)
- }
-
- private var isAlertAllowed: Bool {
- return sdlManager.permissionManager.isRPCNameAllowed(.alert)
+ /// Keeps track of the toggle soft button current state. The image or text changes when the button is selected
+ fileprivate var toggleEnabled: Bool {
+ didSet {
+ guard let hexagonSoftButton = sdlManager.screenManager.softButtonObjectNamed(ToggleSoftButton), hexagonSoftButton.transition(toState: toggleEnabled ? ToggleSoftButtonImageOnState : ToggleSoftButtonImageOffState) else { return }
+ }
}
init(sdlManager: SDLManager, updateScreenHandler: RefreshUIHandler? = nil) {
@@ -45,56 +45,54 @@ class ButtonManager: NSObject {
self.refreshUIHandler = updateScreenHandler
textEnabled = true
imagesEnabled = true
+ toggleEnabled = true
+ super.init()
}
- /// An array of all the soft buttons
+ /// Creates and returns an array of all soft buttons for the UI
///
/// - Parameter manager: The SDL Manager
/// - Returns: An array of all soft buttons for the UI
- func allScreenSoftButtons() -> [SDLSoftButtonObject] {
- return [softButtonAlert, softButtonSubtleAlert, softButtonTextVisible, softButtonImagesVisible]
+ func allScreenSoftButtons(with manager: SDLManager) -> [SDLSoftButtonObject] {
+ return [softButtonAlert(with: manager), softButtonToggle(), softButtonTextVisible(), softButtonImagesVisible()]
}
}
// MARK: - Custom Soft Buttons
-extension ButtonManager {
+private extension ButtonManager {
/// Returns a soft button that shows an alert when tapped.
- private var softButtonAlert: SDLSoftButtonObject {
- let imageAndTextState = SDLSoftButtonState(stateName: AlertSoftButtonImageAndTextState, text: AlertSoftButtonText, image: UIImage(named: AlertBWIconName)?.withRenderingMode(.alwaysTemplate))
- let textState = SDLSoftButtonState(stateName: AlertSoftButtonTextState, text: AlertSoftButtonText, image: nil)
- return SDLSoftButtonObject(name: AlertSoftButton, states: [imageAndTextState, textState], initialStateName: imageAndTextState.name) { [weak self] (buttonPress, buttonEvent) in
- guard let self = self, buttonPress != nil else { return }
-
- if (self.isAlertAllowed) {
- AlertManager.sendAlert(imageName: CarBWIconImageName, textField1: AlertMessageText, sdlManager: self.sdlManager)
- } else if (self.isSubtleAlertAllowed) {
- AlertManager.sendSubtleAlert(imageName: CarBWIconImageName, textField1: AlertMessageText, sdlManager: self.sdlManager)
- } else {
- SDLLog.w("The module does not support the Alert request or the Subtle Alert request")
- }
+ ///
+ /// - Parameter manager: The SDL Manager for showing the alert
+ /// - Returns: A soft button
+ func softButtonAlert(with manager: SDLManager) -> SDLSoftButtonObject {
+ let imageSoftButtonState = SDLSoftButtonState(stateName: AlertSoftButtonImageState, text: nil, image: UIImage(named: AlertBWIconName)?.withRenderingMode(.alwaysTemplate))
+ let textSoftButtonState = SDLSoftButtonState(stateName: AlertSoftButtonTextState, text: AlertSoftButtonText, image: nil)
+ return SDLSoftButtonObject(name: AlertSoftButton, states: [imageSoftButtonState, textSoftButtonState], initialStateName: imageSoftButtonState.name) { (buttonPress, buttonEvent) in
+ guard buttonPress != nil else { return }
+ manager.fileManager.upload(artwork: SDLArtwork(image: UIImage(named: CarBWIconImageName)!, persistent: false, as: .PNG), completionHandler: { (success, artworkName, bytesAvailable, err) in
+ let alert = AlertManager.alertWithMessageAndCloseButton("You pressed the button!", iconName: artworkName)
+ manager.send(alert)
+ })
}
}
- /// Returns a soft button that shows a subtle alert when tapped. If the subtle alert is not supported, then a regular alert is shown.
- private var softButtonSubtleAlert: SDLSoftButtonObject {
- let imageAndTextState = SDLSoftButtonState(stateName: SubtleAlertSoftButtonImageAndTextState, text: SubtleAlertSoftButtonText, image: UIImage(named: BatteryFullBWIconName)?.withRenderingMode(.alwaysTemplate))
- let textState = SDLSoftButtonState(stateName: SubtleAlertSoftButtonTextState, text: SubtleAlertSoftButtonText, image: nil)
- return SDLSoftButtonObject(name: SubtleAlertSoftButton, states: [imageAndTextState, textState], initialStateName: imageAndTextState.name) { [weak self] (buttonPress, buttonEvent) in
- guard let self = self, buttonPress != nil else { return }
-
- if (self.isSubtleAlertAllowed) {
- AlertManager.sendSubtleAlert(imageName: BatteryEmptyBWIconName, textField1: SubtleAlertHeaderText, textField2: SubtleAlertSubheaderText, sdlManager: self.sdlManager)
- } else if (self.isAlertAllowed) {
- AlertManager.sendAlert(imageName: BatteryEmptyBWIconName, textField1: SubtleAlertHeaderText, textField2: SubtleAlertSubheaderText, sdlManager: self.sdlManager)
- } else {
- SDLLog.w("The module does not support the Alert request or the Subtle Alert request")
- }
+ /// Returns a soft button that toggles between two states: on and off. If images are currently visible, the button image toggles; if images aren't visible, the button text toggles.
+ ///
+ /// - Returns: A soft button
+ func softButtonToggle() -> SDLSoftButtonObject {
+ let imageOnState = SDLSoftButtonState(stateName: ToggleSoftButtonImageOnState, text: nil, image: UIImage(named: ToggleOnBWIconName)?.withRenderingMode(.alwaysTemplate))
+ let imageOffState = SDLSoftButtonState(stateName: ToggleSoftButtonImageOffState, text: nil, image: UIImage(named: ToggleOffBWIconName)?.withRenderingMode(.alwaysTemplate))
+ return SDLSoftButtonObject(name: ToggleSoftButton, states: [imageOnState, imageOffState], initialStateName: imageOnState.name) { [unowned self] (buttonPress, buttonEvent) in
+ guard buttonPress != nil else { return }
+ self.toggleEnabled = !self.toggleEnabled
}
}
- /// Returns a soft button that toggles the textfield visibility state.
- private var softButtonTextVisible: SDLSoftButtonObject {
+ /// Returns a soft button that toggles the textfield visibility state for the SDL UI. The button's text toggles based on the current text visibility.
+ ///
+ /// - Returns: A soft button
+ func softButtonTextVisible() -> SDLSoftButtonObject {
let textVisibleState = SDLSoftButtonState(stateName: TextVisibleSoftButtonTextOnState, text: TextVisibleSoftButtonTextOnText, artwork: nil)
let textNotVisibleState = SDLSoftButtonState(stateName: TextVisibleSoftButtonTextOffState, text: TextVisibleSoftButtonTextOffText, image: nil)
return SDLSoftButtonObject(name: TextVisibleSoftButton, states: [textVisibleState, textNotVisibleState], initialStateName: textVisibleState.name) { [unowned self] (buttonPress, buttonEvent) in
@@ -107,26 +105,19 @@ extension ButtonManager {
}
}
- /// Returns a soft button that toggles the image visibility state.
- private var softButtonImagesVisible: SDLSoftButtonObject {
+ /// Returns a soft button that toggles the image visibility state for the SDL UI. The button's text toggles based on the current image visibility.
+ ///
+ /// - Returns: A soft button
+ func softButtonImagesVisible() -> SDLSoftButtonObject {
let imagesVisibleState = SDLSoftButtonState(stateName: ImagesVisibleSoftButtonImageOnState, text: ImagesVisibleSoftButtonImageOnText, image: nil)
let imagesNotVisibleState = SDLSoftButtonState(stateName: ImagesVisibleSoftButtonImageOffState, text: ImagesVisibleSoftButtonImageOffText, image: nil)
- return SDLSoftButtonObject(name: ImagesVisibleSoftButton, states: [imagesVisibleState, imagesNotVisibleState], initialStateName: imagesVisibleState.name) { [weak self] (buttonPress, buttonEvent) in
- guard let self = self, let sdlManager = self.sdlManager, buttonPress != nil else { return }
-
+ return SDLSoftButtonObject(name: ImagesVisibleSoftButton, states: [imagesVisibleState, imagesNotVisibleState], initialStateName: imagesVisibleState.name) { [unowned self] (buttonPress, buttonEvent) in
+ guard buttonPress != nil else { return }
self.imagesEnabled = !self.imagesEnabled
- if let imagesVisibleSoftButton = sdlManager.screenManager.softButtonObjectNamed(ImagesVisibleSoftButton) {
- imagesVisibleSoftButton.transitionToNextState()
- }
-
- if let alertSoftButton = sdlManager.screenManager.softButtonObjectNamed(AlertSoftButton) {
- alertSoftButton.transitionToNextState()
- }
-
- if let subtleAlertSoftButton = sdlManager.screenManager.softButtonObjectNamed(SubtleAlertSoftButton) {
- subtleAlertSoftButton.transitionToNextState()
- }
+ // Update the button state
+ let softButton = self.sdlManager.screenManager.softButtonObjectNamed(ImagesVisibleSoftButton)
+ softButton?.transitionToNextState()
}
}
}
diff --git a/Example Apps/Example Swift/MenuManager.swift b/Example Apps/Example Swift/MenuManager.swift
index e21a05e10..cdf478149 100644
--- a/Example Apps/Example Swift/MenuManager.swift
+++ b/Example Apps/Example Swift/MenuManager.swift
@@ -72,7 +72,7 @@ private extension MenuManager {
/// A list of all possible vehicle data types
static var allVehicleDataTypes: [String] {
- return [ACAccelerationPedalPositionMenuName, ACAirbagStatusMenuName, ACBeltStatusMenuName, ACBodyInformationMenuName, ACClusterModeStatusMenuName, ACDeviceStatusMenuName, ACDriverBrakingMenuName, ACECallInfoMenuName, ACElectronicParkBrakeStatus, ACEmergencyEventMenuName, ACEngineOilLifeMenuName, ACEngineTorqueMenuName, ACExternalTemperatureMenuName, ACFuelLevelMenuName, ACFuelLevelStateMenuName, ACFuelRangeMenuName, ACGearStatusMenuName, ACGPSMenuName, ACHeadLampStatusMenuName, ACInstantFuelConsumptionMenuName, ACMyKeyMenuName, ACOdometerMenuName, ACPRNDLMenuName, ACRPMMenuName, ACSpeedMenuName, ACSteeringWheelAngleMenuName, ACTirePressureMenuName, ACTurnSignalMenuName, ACVINMenuName, ACWiperStatusMenuName]
+ return [ACAccelerationPedalPositionMenuName, ACAirbagStatusMenuName, ACBeltStatusMenuName, ACBodyInformationMenuName, ACClusterModeStatusMenuName, ACDeviceStatusMenuName, ACDriverBrakingMenuName, ACECallInfoMenuName, ACElectronicParkBrakeStatus, ACEmergencyEventMenuName, ACEngineOilLifeMenuName, ACEngineTorqueMenuName, ACExternalTemperatureMenuName, ACFuelLevelMenuName, ACFuelLevelStateMenuName, ACFuelRangeMenuName, ACGPSMenuName, ACHeadLampStatusMenuName, ACInstantFuelConsumptionMenuName, ACMyKeyMenuName, ACOdometerMenuName, ACPRNDLMenuName, ACRPMMenuName, ACSpeedMenuName, ACSteeringWheelAngleMenuName, ACTirePressureMenuName, ACTurnSignalMenuName, ACVINMenuName, ACWiperStatusMenuName]
}
/// Menu item that shows a custom menu (i.e. a Perform Interaction Choice Set) when selected
@@ -90,9 +90,15 @@ private extension MenuManager {
/// - Parameter manager: The SDL Manager
/// - Returns: A SDLMenuCell object
class func menuCellRecordInCarMicrophoneAudio(with manager: SDLManager) -> SDLMenuCell {
- let audioManager = AudioManager(sdlManager: manager)
- return SDLMenuCell(title: ACRecordInCarMicrophoneAudioMenuName, icon: SDLArtwork(image: UIImage(named: MicrophoneBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), voiceCommands: [ACRecordInCarMicrophoneAudioMenuName], handler: { _ in
- audioManager.startRecording()
+ if #available(iOS 10.0, *) {
+ let audioManager = AudioManager(sdlManager: manager)
+ return SDLMenuCell(title: ACRecordInCarMicrophoneAudioMenuName, icon: SDLArtwork(image: UIImage(named: MicrophoneBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), voiceCommands: [ACRecordInCarMicrophoneAudioMenuName], handler: { _ in
+ audioManager.startRecording()
+ })
+ }
+
+ return SDLMenuCell(title: ACRecordInCarMicrophoneAudioMenuName, icon: SDLArtwork(image: UIImage(named: SpeakBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), voiceCommands: [ACRecordInCarMicrophoneAudioMenuName], handler: { _ in
+ manager.send(AlertManager.alertWithMessageAndCloseButton("Speech recognition feature only available on iOS 10+"))
})
}
@@ -103,7 +109,7 @@ private extension MenuManager {
class func menuCellDialNumber(with manager: SDLManager) -> SDLMenuCell {
return SDLMenuCell(title: ACDialPhoneNumberMenuName, icon: SDLArtwork(image: UIImage(named: PhoneBWIconImageName)!.withRenderingMode(.alwaysTemplate), persistent: true, as: .PNG), voiceCommands: [ACDialPhoneNumberMenuName], handler: { _ in
guard RPCPermissionsManager.isDialNumberRPCAllowed(with: manager) else {
- AlertManager.sendAlert(textField1: AlertDialNumberPermissionsWarningText, sdlManager: manager)
+ manager.send(AlertManager.alertWithMessageAndCloseButton("This app does not have the required permissions to dial a number"))
return
}
@@ -124,9 +130,10 @@ private extension MenuManager {
/// Non-Media
let submenuTitleNonMedia = "Non - Media (Default)"
submenuItems.append(SDLMenuCell(title: submenuTitleNonMedia, icon: nil, voiceCommands: nil, handler: { (triggerSource) in
- manager.screenManager.changeLayout(SDLTemplateConfiguration(predefinedLayout: .nonMedia)) { err in
- if err != nil {
- AlertManager.sendAlert(textField1: errorMessage, sdlManager: manager)
+ let display = SDLSetDisplayLayout(predefinedLayout: .nonMedia)
+ manager.send(request: display) { (request, response, error) in
+ guard response?.success.boolValue == .some(true) else {
+ manager.send(AlertManager.alertWithMessageAndCloseButton(errorMessage))
return
}
}
@@ -135,9 +142,10 @@ private extension MenuManager {
/// Graphic with Text
let submenuTitleGraphicText = "Graphic With Text"
submenuItems.append(SDLMenuCell(title: submenuTitleGraphicText, icon: nil, voiceCommands: nil, handler: { (triggerSource) in
- manager.screenManager.changeLayout(SDLTemplateConfiguration(predefinedLayout: .graphicWithText)) { err in
- if err != nil {
- AlertManager.sendAlert(textField1: errorMessage, sdlManager: manager)
+ let display = SDLSetDisplayLayout(predefinedLayout: .graphicWithText)
+ manager.send(request: display) { (request, response, error) in
+ guard response?.success.boolValue == .some(true) else {
+ manager.send(AlertManager.alertWithMessageAndCloseButton(errorMessage))
return
}
}
@@ -158,7 +166,7 @@ private extension MenuManager {
let message = "\(submenuTitle) selected!"
switch triggerSource {
case .menu:
- AlertManager.sendAlert(textField1: message, sdlManager: manager)
+ manager.send(AlertManager.alertWithMessageAndCloseButton(message))
case .voiceRecognition:
manager.send(SDLSpeak(tts: message))
default: break
@@ -176,11 +184,11 @@ private extension MenuManager {
guard let response = response else { return }
guard response.resultCode == .success else {
if response.resultCode == .timedOut {
- AlertManager.sendAlert(textField1: AlertSliderTimedOutWarningText, sdlManager: manager)
+ manager.send(AlertManager.alertWithMessageAndCloseButton("Slider timed out"))
} else if response.resultCode == .aborted {
- AlertManager.sendAlert(textField1: AlertSliderCancelledWarningText, sdlManager: manager)
+ manager.send(AlertManager.alertWithMessageAndCloseButton("Slider cancelled"))
} else {
- AlertManager.sendAlert(textField1: AlertSliderGeneralWarningText, sdlManager: manager)
+ manager.send(AlertManager.alertWithMessageAndCloseButton("Slider could not be displayed"))
}
return
}
@@ -195,11 +203,11 @@ private extension MenuManager {
guard let response = response else { return }
guard response.resultCode == .success else {
if response.resultCode == .timedOut {
- AlertManager.sendAlert(textField1: AlertScrollableMessageTimedOutWarningText, sdlManager: manager)
+ manager.send(AlertManager.alertWithMessageAndCloseButton("Scrollable Message timed out"))
} else if response.resultCode == .aborted {
- AlertManager.sendAlert(textField1: AlertScrollableMessageCancelledWarningText, sdlManager: manager)
+ manager.send(AlertManager.alertWithMessageAndCloseButton("Scrollable Message cancelled"))
} else {
- AlertManager.sendAlert(textField1: AlertScrollableMessageGeneralWarningText, sdlManager: manager)
+ manager.send(AlertManager.alertWithMessageAndCloseButton("Scrollable Message could not be displayed"))
}
return
}
@@ -217,7 +225,7 @@ private extension MenuManager {
/// - Returns: A SDLVoiceCommand object
class func voiceCommandStart(with manager: SDLManager) -> SDLVoiceCommand {
return SDLVoiceCommand(voiceCommands: [VCStart], handler: {
- AlertManager.sendAlert(textField1: "\(VCStart) voice command selected!", sdlManager: manager)
+ manager.send(AlertManager.alertWithMessageAndCloseButton("\(VCStart) voice command selected!"))
})
}
@@ -227,7 +235,7 @@ private extension MenuManager {
/// - Returns: A SDLVoiceCommand object
class func voiceCommandStop(with manager: SDLManager) -> SDLVoiceCommand {
return SDLVoiceCommand(voiceCommands: [VCStop], handler: {
- AlertManager.sendAlert(textField1: "\(VCStop) voice command selected!", sdlManager: manager)
+ manager.send(AlertManager.alertWithMessageAndCloseButton("\(VCStop) voice command selected!"))
})
}
}
diff --git a/Example Apps/Example Swift/ProxyManager.swift b/Example Apps/Example Swift/ProxyManager.swift
index 8a53e7c76..fdad60360 100644
--- a/Example Apps/Example Swift/ProxyManager.swift
+++ b/Example Apps/Example Swift/ProxyManager.swift
@@ -165,16 +165,17 @@ extension ProxyManager: SDLManagerDelegate {
// This is our first time in a non-NONE state
firstHMILevelState = newLevel
+ // Send static menu items.
+ createMenuAndGlobalVoiceCommands()
+
// Subscribe to vehicle data.
vehicleDataManager.subscribeToVehicleOdometer()
-
- //Handle initial launch
- showInitialData()
}
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.
+ showInitialData()
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
@@ -248,15 +249,13 @@ private extension ProxyManager {
/// Set the template and create the UI
func showInitialData() {
- // Send static menu items and soft buttons
- createMenuAndGlobalVoiceCommands()
- sdlManager.screenManager.softButtonObjects = buttonManager.allScreenSoftButtons()
-
guard sdlManager.hmiLevel == .full else { return }
-
- sdlManager.screenManager.changeLayout(SDLTemplateConfiguration(predefinedLayout: .nonMedia), withCompletionHandler: nil)
+
+ let setDisplayLayout = SDLSetDisplayLayout(predefinedLayout: .nonMedia)
+ sdlManager.send(setDisplayLayout)
updateScreen()
+ sdlManager.screenManager.softButtonObjects = buttonManager.allScreenSoftButtons(with: sdlManager)
}
/// Update the UI's textfields, images and soft buttons
diff --git a/Example Apps/Example Swift/VehicleDataManager.swift b/Example Apps/Example Swift/VehicleDataManager.swift
index 87176a883..c0f6e59dc 100644
--- a/Example Apps/Example Swift/VehicleDataManager.swift
+++ b/Example Apps/Example Swift/VehicleDataManager.swift
@@ -111,7 +111,7 @@ extension VehicleDataManager {
guard hasPermissionToAccessVehicleData(with: manager) else { return }
SDLLog.d("App has permission to access vehicle data. Requesting all vehicle data...")
- let getAllVehicleData = SDLGetVehicleData(gps: NSNumber(true), speed: NSNumber(true), rpm: NSNumber(true), instantFuelConsumption: NSNumber(true), fuelRange: NSNumber(true), externalTemperature: NSNumber(true), turnSignal: NSNumber(true), vin: NSNumber(true), gearStatus: NSNumber(true), tirePressure: NSNumber(true), odometer: NSNumber(true), beltStatus: NSNumber(true), bodyInformation: NSNumber(true), deviceStatus: NSNumber(true), driverBraking: NSNumber(true), wiperStatus: NSNumber(true), headLampStatus: NSNumber(true), engineTorque: NSNumber(true), accPedalPosition: NSNumber(true), steeringWheelAngle: NSNumber(true), engineOilLife: NSNumber(true), electronicParkBrakeStatus: NSNumber(true), cloudAppVehicleID: NSNumber(true), stabilityControlsStatus: NSNumber(true), eCallInfo: NSNumber(true), airbagStatus: NSNumber(true), emergencyEvent: NSNumber(true), clusterModeStatus: NSNumber(true), myKey: NSNumber(true), handsOffSteering: NSNumber(true), windowStatus: NSNumber(true))
+ let getAllVehicleData = SDLGetVehicleData(accelerationPedalPosition: true, airbagStatus: true, beltStatus: true, bodyInformation: true, cloudAppVehicleID: true, clusterModeStatus: true, deviceStatus: true, driverBraking: true, eCallInfo: true, electronicParkBrakeStatus: true, emergencyEvent: true, engineOilLife: true, engineTorque: true, externalTemperature: true, fuelLevel: true, fuelLevelState: true, fuelRange: true, gps: true, headLampStatus: true, instantFuelConsumption: true, myKey: true, odometer: true, prndl: true, rpm: true, speed: true, steeringWheelAngle: true, tirePressure: true, turnSignal: true, vin: true, wiperStatus: true)
manager.send(request: getAllVehicleData) { (request, response, error) in
guard didAccessVehicleDataSuccessfully(with: manager, response: response, error: error) else { return }
@@ -144,7 +144,9 @@ extension VehicleDataManager {
if triggerSource == .menu {
let title = !alertTitle.isEmpty ? alertTitle : "No Vehicle Data Available"
let detailMessage = !alertMessage.isEmpty ? alertMessage : nil
- AlertManager.sendAlert(textField1: title, textField2: detailMessage, sdlManager: manager)
+ let alert = AlertManager.alertWithMessageAndCloseButton(title,
+ textField2: detailMessage)
+ manager.send(alert)
} else {
let spokenAlert = !alertMessage.isEmpty ? alertMessage : alertTitle
manager.send(SDLSpeak(tts: spokenAlert))
@@ -190,9 +192,9 @@ extension VehicleDataManager {
case ACExternalTemperatureMenuName:
vehicleDataDescription = vehicleData.externalTemperature?.description ?? notAvailable
case ACFuelLevelMenuName:
- vehicleDataDescription = vehicleData.fuelRange?.first?.level?.description ?? notAvailable
+ vehicleDataDescription = vehicleData.fuelLevel?.description ?? notAvailable
case ACFuelLevelStateMenuName:
- vehicleDataDescription = vehicleData.fuelRange?.first?.levelState?.rawValue.rawValue ?? notAvailable
+ vehicleDataDescription = vehicleData.fuelLevel_State?.rawValue.rawValue ?? notAvailable
case ACFuelRangeMenuName:
vehicleDataDescription = vehicleData.fuelRange?.description ?? notAvailable
case ACGPSMenuName:
@@ -206,7 +208,7 @@ extension VehicleDataManager {
case ACOdometerMenuName:
vehicleDataDescription = vehicleData.odometer?.description ?? notAvailable
case ACPRNDLMenuName:
- vehicleDataDescription = vehicleData.gearStatus?.actualGear?.rawValue.rawValue ?? notAvailable
+ vehicleDataDescription = vehicleData.prndl?.rawValue.rawValue ?? notAvailable
case ACSpeedMenuName:
vehicleDataDescription = vehicleData.speed?.description ?? notAvailable
case ACSteeringWheelAngleMenuName:
@@ -231,7 +233,8 @@ extension VehicleDataManager {
SDLLog.d("Checking if app has permission to access vehicle data...")
guard manager.permissionManager.isRPCNameAllowed(SDLRPCFunctionName.getVehicleData) else {
- AlertManager.sendAlert(textField1: AlertVehicleDataPermissionsWarningText, sdlManager: manager)
+ let alert = AlertManager.alertWithMessageAndCloseButton("This app does not have the required permissions to access vehicle data")
+ manager.send(request: alert)
return false
}
@@ -249,7 +252,8 @@ extension VehicleDataManager {
SDLLog.d("Checking if Core returned vehicle data")
guard response != nil, error == nil else {
- AlertManager.sendAlert(textField1: AlertVehicleDataGeneralWarningText, sdlManager: manager)
+ let alert = AlertManager.alertWithMessageAndCloseButton("Something went wrong while getting vehicle data")
+ manager.send(request: alert)
return false
}
@@ -268,14 +272,14 @@ extension VehicleDataManager {
SDLLog.d("Checking phone call capability")
manager.systemCapabilityManager.updateCapabilityType(.phoneCall, completionHandler: { (error, systemCapabilityManager) in
guard let phoneCapability = systemCapabilityManager.phoneCapability else {
- AlertManager.sendAlert(textField1: AlertDialNumberPermissionsWarningText, sdlManager: manager)
+ manager.send(AlertManager.alertWithMessageAndCloseButton("The head unit does not support the phone call capability"))
return
}
if phoneCapability.dialNumberEnabled?.boolValue ?? false {
SDLLog.d("Dialing phone number \(phoneNumber)...")
dialPhoneNumber(phoneNumber, manager: manager)
} else {
- AlertManager.sendAlert(textField1: AlertDialNumberUnavailableWarningText, sdlManager: manager)
+ manager.send(AlertManager.alertWithMessageAndCloseButton("A phone call can not be made"))
}
})
}
diff --git a/Example Apps/Shared/AppConstants.h b/Example Apps/Shared/AppConstants.h
index b06009fa7..5fb4b25b0 100644
--- a/Example Apps/Shared/AppConstants.h
+++ b/Example Apps/Shared/AppConstants.h
@@ -22,13 +22,16 @@ extern NSString * const SmartDeviceLinkText;
extern NSString * const ExampleAppText;
#pragma mark - SDL Soft Buttons
-extern NSString * const SubtleAlertSoftButton;
-extern NSString * const SubtleAlertSoftButtonImageAndTextState;
-extern NSString * const SubtleAlertSoftButtonTextState;
-extern NSString * const SubtleAlertSoftButtonText;
+extern NSString * const ToggleSoftButton;
+extern NSString * const ToggleSoftButtonImageOnState;
+extern NSString * const ToggleSoftButtonImageOffState;
+extern NSString * const ToggleSoftButtonTextOnState;
+extern NSString * const ToggleSoftButtonTextOffState;
+extern NSString * const ToggleSoftButtonTextTextOnText;
+extern NSString * const ToggleSoftButtonTextTextOffText;
extern NSString * const AlertSoftButton;
-extern NSString * const AlertSoftButtonImageAndTextState;
+extern NSString * const AlertSoftButtonImageState;
extern NSString * const AlertSoftButtonTextState;
extern NSString * const AlertSoftButtonText;
@@ -45,21 +48,7 @@ extern NSString * const ImagesVisibleSoftButtonImageOnText;
extern NSString * const ImagesVisibleSoftButtonImageOffText;
#pragma mark - Alert
-extern NSString * const AlertMessageText;
extern NSString * const AlertOKButtonText;
-extern NSString * const SubtleAlertHeaderText;
-extern NSString * const SubtleAlertSubheaderText;
-extern NSString * const AlertDialNumberPermissionsWarningText;
-extern NSString * const AlertDialNumberUnavailableWarningText;
-extern NSString * const AlertSliderTimedOutWarningText;
-extern NSString * const AlertSliderCancelledWarningText;
-extern NSString * const AlertSliderGeneralWarningText;
-extern NSString * const AlertScrollableMessageTimedOutWarningText;
-extern NSString * const AlertScrollableMessageCancelledWarningText;
-extern NSString * const AlertScrollableMessageGeneralWarningText;
-extern NSString * const AlertVehicleDataPermissionsWarningText;
-extern NSString * const AlertVehicleDataGeneralWarningText;
-extern NSString * const AlertSpeechPermissionsWarningText;
#pragma mark - SDL Text-To-Speech
extern NSString * const TTSGoodJob;
@@ -112,7 +101,6 @@ extern NSString * const ACExternalTemperatureMenuName;
extern NSString * const ACFuelLevelMenuName;
extern NSString * const ACFuelLevelStateMenuName;
extern NSString * const ACFuelRangeMenuName;
-extern NSString * const ACGearStatusMenuName;
extern NSString * const ACGPSMenuName;
extern NSString * const ACHeadLampStatusMenuName;
extern NSString * const ACInstantFuelConsumptionMenuName;
@@ -135,8 +123,8 @@ extern NSString * const MenuBWIconImageName;
extern NSString * const MicrophoneBWIconImageName;
extern NSString * const PhoneBWIconImageName;
extern NSString * const SpeakBWIconImageName;
-extern NSString * const BatteryEmptyBWIconName;
-extern NSString * const BatteryFullBWIconName;
+extern NSString * const ToggleOffBWIconName;
+extern NSString * const ToggleOnBWIconName;
#pragma mark - SDL App Name in Different Languages
extern NSString * const ExampleAppNameSpanish;
diff --git a/Example Apps/Shared/AppConstants.m b/Example Apps/Shared/AppConstants.m
index 69447b16d..ffe4762d1 100644
--- a/Example Apps/Shared/AppConstants.m
+++ b/Example Apps/Shared/AppConstants.m
@@ -19,15 +19,18 @@ NSString * const SmartDeviceLinkText = @"SmartDeviceLink (SDL)";
NSString * const ExampleAppText = @"Example App";
#pragma mark - SDL Soft Buttons
-NSString * const SubtleAlertSoftButton = @"SubtleAlertSoftButton";
-NSString * const SubtleAlertSoftButtonImageAndTextState = @"SubtleAlertSoftButtonImageAndTextState";
-NSString * const SubtleAlertSoftButtonTextState = @"SubtleAlertSoftButtonTextState";
-NSString * const SubtleAlertSoftButtonText = @"Check Battery";
+NSString * const ToggleSoftButton = @"ToggleSoftButton";
+NSString * const ToggleSoftButtonImageOnState = @"ToggleSoftButtonImageOnState";
+NSString * const ToggleSoftButtonImageOffState = @"ToggleSoftButtonImageOffState";
+NSString * const ToggleSoftButtonTextOnState = @"ToggleSoftButtonTextOnState";
+NSString * const ToggleSoftButtonTextOffState = @"ToggleSoftButtonTextOffState";
+NSString * const ToggleSoftButtonTextTextOnText = @"➖";
+NSString * const ToggleSoftButtonTextTextOffText = @"➕";
NSString * const AlertSoftButton = @"AlertSoftButton";
-NSString * const AlertSoftButtonImageAndTextState = @"AlertSoftButtonImageAndTextState";
+NSString * const AlertSoftButtonImageState = @"AlertSoftButtonImageState";
NSString * const AlertSoftButtonTextState = @"AlertSoftButtonTextState";
-NSString * const AlertSoftButtonText = @"Show Alert";
+NSString * const AlertSoftButtonText = @"Tap Me";
NSString * const TextVisibleSoftButton = @"TextVisibleSoftButton";
NSString * const TextVisibleSoftButtonTextOnState = @"TextVisibleSoftButtonTextOnState";
@@ -42,21 +45,7 @@ NSString * const ImagesVisibleSoftButtonImageOnText = @"➖Icons";
NSString * const ImagesVisibleSoftButtonImageOffText = @"➕Icons";
#pragma mark - Alert
-NSString * const AlertMessageText = @"You pressed the button!";
NSString * const AlertOKButtonText = @"OK";
-NSString * const SubtleAlertHeaderText = @"Battery Level";
-NSString * const SubtleAlertSubheaderText = @"Almost empty";
-NSString * const AlertDialNumberPermissionsWarningText = @"This app does not have the required permissions to dial a number";
-NSString * const AlertDialNumberUnavailableWarningText = @"The dial number feature is unavailable for this head unit";
-NSString * const AlertSliderTimedOutWarningText = @"Slider timed out";
-NSString * const AlertSliderCancelledWarningText = @"Slider cancelled";
-NSString * const AlertSliderGeneralWarningText = @"Slider could not be displayed";
-NSString * const AlertScrollableMessageTimedOutWarningText = @"Scrollable Message timed out";
-NSString * const AlertScrollableMessageCancelledWarningText = @"Scrollable Message cancelled";
-NSString * const AlertScrollableMessageGeneralWarningText = @"Scrollable Message could not be displayed";
-NSString * const AlertVehicleDataPermissionsWarningText = @"This app does not have the required permissions to access vehicle data";
-NSString * const AlertVehicleDataGeneralWarningText = @"Something went wrong while getting vehicle data";
-NSString * const AlertSpeechPermissionsWarningText = @"You must give this app permission to access Speech Recognition";
#pragma mark - SDL Text-To-Speech
NSString * const TTSGoodJob = @"Good Job";
@@ -109,7 +98,6 @@ NSString * const ACExternalTemperatureMenuName = @"External Temperature";
NSString * const ACFuelLevelMenuName = @"Fuel Level";
NSString * const ACFuelLevelStateMenuName = @"Fuel Level State";
NSString * const ACFuelRangeMenuName = @"Fuel Range";
-NSString * const ACGearStatusMenuName = @"Gear Status";
NSString * const ACGPSMenuName = @"GPS";
NSString * const ACHeadLampStatusMenuName = @"Head Lamp Status";
NSString * const ACInstantFuelConsumptionMenuName = @"Instant Fuel Consumption";
@@ -132,8 +120,8 @@ NSString * const MenuBWIconImageName = @"choice_set";
NSString * const MicrophoneBWIconImageName = @"microphone";
NSString * const PhoneBWIconImageName = @"phone";
NSString * const SpeakBWIconImageName = @"speak";
-NSString * const BatteryEmptyBWIconName = @"toggle_off";
-NSString * const BatteryFullBWIconName = @"toggle_on";
+NSString * const ToggleOffBWIconName = @"toggle_off";
+NSString * const ToggleOnBWIconName = @"toggle_on";
#pragma mark - SDL App Name in Different Languages
NSString * const ExampleAppNameSpanish = @"SDL Aplicación de ejemplo";
diff --git a/Example Apps/Shared/Images.xcassets/AppIcon.appiconset/Contents.json b/Example Apps/Shared/Images.xcassets/AppIcon.appiconset/Contents.json
index 5e692a4d1..997a0f138 100644
--- a/Example Apps/Shared/Images.xcassets/AppIcon.appiconset/Contents.json
+++ b/Example Apps/Shared/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -2,59 +2,58 @@
"images" : [
{
"idiom" : "iphone",
- "scale" : "2x",
- "size" : "20x20"
+ "size" : "20x20",
+ "scale" : "2x"
},
{
"idiom" : "iphone",
- "scale" : "3x",
- "size" : "20x20"
+ "size" : "20x20",
+ "scale" : "3x"
},
{
- "filename" : "Icon-Small@2x.png",
+ "size" : "29x29",
"idiom" : "iphone",
- "scale" : "2x",
- "size" : "29x29"
+ "filename" : "Icon-Small@2x.png",
+ "scale" : "2x"
},
{
- "filename" : "Icon-Small@3x.png",
+ "size" : "29x29",
"idiom" : "iphone",
- "scale" : "3x",
- "size" : "29x29"
+ "filename" : "Icon-Small@3x.png",
+ "scale" : "3x"
},
{
- "filename" : "Icon-Small-40@2x.png",
+ "size" : "40x40",
"idiom" : "iphone",
- "scale" : "2x",
- "size" : "40x40"
+ "filename" : "Icon-Small-40@2x.png",
+ "scale" : "2x"
},
{
- "filename" : "Icon-60@2x-1.png",
+ "size" : "40x40",
"idiom" : "iphone",
- "scale" : "3x",
- "size" : "40x40"
+ "filename" : "Icon-60@2x-1.png",
+ "scale" : "3x"
},
{
- "filename" : "Icon-60@2x.png",
+ "size" : "60x60",
"idiom" : "iphone",
- "scale" : "2x",
- "size" : "60x60"
+ "filename" : "Icon-60@2x.png",
+ "scale" : "2x"
},
{
- "filename" : "Icon-60@3x.png",
+ "size" : "60x60",
"idiom" : "iphone",
- "scale" : "3x",
- "size" : "60x60"
+ "filename" : "Icon-60@3x.png",
+ "scale" : "3x"
},
{
- "filename" : "iTunesArtwork.png",
"idiom" : "ios-marketing",
- "scale" : "1x",
- "size" : "1024x1024"
+ "size" : "1024x1024",
+ "scale" : "1x"
}
],
"info" : {
- "author" : "xcode",
- "version" : 1
+ "version" : 1,
+ "author" : "xcode"
}
-}
+} \ No newline at end of file
diff --git a/Example Apps/Shared/resources/sdl_video.mp4 b/Example Apps/Shared/resources/sdl_video.mp4
new file mode 100644
index 000000000..9fa253a75
--- /dev/null
+++ b/Example Apps/Shared/resources/sdl_video.mp4
Binary files differ