├── .github ├── CODEOWNERS └── stale.yml ├── .gitignore ├── IoT-Sample └── Swift │ ├── IoTSampleSwift.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata │ ├── IoTSampleSwift.xcworkspace │ └── contents.xcworkspacedata │ ├── IoTSampleSwift │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── first.imageset │ │ │ ├── Contents.json │ │ │ └── first.pdf │ │ └── second.imageset │ │ │ ├── Contents.json │ │ │ └── second.pdf │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── ConfigurationViewController.swift │ ├── ConnectionViewController+Websocket.swift │ ├── ConnectionViewController.swift │ ├── Constants.swift │ ├── Info.plist │ ├── IoTSampleSwift.entitlements │ ├── IoTSampleTabBarController.swift │ ├── PublishViewController.swift │ └── SubscribeViewController.swift │ ├── Podfile │ ├── README.md │ └── awsconfiguration.json ├── LICENSE ├── Lex-Sample ├── ObjC │ ├── Lex-Sample.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ ├── Lex-Sample │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── ChatViewController.h │ │ ├── ChatViewController.m │ │ ├── Constants.h │ │ ├── Constants.m │ │ ├── Info.plist │ │ ├── TableViewController.h │ │ ├── TableViewController.m │ │ ├── ViewController.h │ │ ├── ViewController.m │ │ └── main.m │ └── Podfile └── Swift │ ├── .gitignore │ ├── LexSwift.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata │ ├── LexSwift │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── ChatViewController.swift │ ├── Constants.swift │ ├── Info.plist │ ├── Main.storyboard │ ├── StringExtension.swift │ ├── TableViewController.swift │ └── VoiceChatViewController.swift │ ├── Podfile │ ├── README.md │ └── awsconfiguration.json ├── NOTICE ├── Polly-Sample └── Swift │ ├── Podfile │ ├── PollySample.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata │ ├── PollySample.xcworkspace │ └── contents.xcworkspacedata │ ├── PollySample │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ └── ViewController.swift │ ├── README.md │ └── awsconfiguration.json ├── README.md └── S3TransferUtility-Sample ├── Objective-C ├── Podfile ├── README.md ├── S3BackgroundTransferSampleObjC │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ └── Main.storyboard │ ├── Constants.h │ ├── Constants.m │ ├── FirstViewController.h │ ├── FirstViewController.m │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── first.imageset │ │ │ ├── Contents.json │ │ │ └── first.pdf │ │ └── second.imageset │ │ │ ├── Contents.json │ │ │ └── second.pdf │ ├── Info.plist │ ├── Launch Screen.storyboard │ ├── SecondViewController.h │ ├── SecondViewController.m │ ├── TemplateIcon2x.png │ └── main.m ├── S3TransferUtilitySampleObjC.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata └── S3TransferUtilitySampleObjC.xcworkspace │ └── contents.xcworkspacedata └── Swift ├── .gitignore ├── Podfile ├── README.md ├── S3BackgroundTransferSampleSwift ├── AppDelegate.swift ├── Base.lproj │ └── Main.storyboard ├── Constants.swift ├── DownloadViewController.swift ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── first.imageset │ │ ├── Contents.json │ │ └── first.pdf │ └── second.imageset │ │ ├── Contents.json │ │ └── second.pdf ├── Info.plist ├── Launch Screen.storyboard └── UploadViewController.swift ├── S3TransferUtilitySampleSwift.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── S3TransferUtilitySampleSwift.xcworkspace └── contents.xcworkspacedata ├── S3TransferUtilitySampleSwiftUITests ├── Info.plist └── S3TransferUtilitySampleSwiftUITests.swift └── awsconfiguration.json /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @awslabs/amplify-ios 2 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | # Setting this to 100 years, because we do not want to automatically mark issues as stale 3 | daysUntilStale: 36500 4 | # Number of days of inactivity before a stale issue is closed 5 | daysUntilClose: 7 6 | # Label to use when marking an issue as stale 7 | staleLabel: closing-soon-if-no-response 8 | # Comment to post when marking an issue as stale. Set to `false` to disable 9 | markComment: > 10 | This issue has been automatically marked as stale because it has not had 11 | recent activity. It will be closed if no further activity occurs. Thank you 12 | for your contributions. 13 | # Comment to post when closing a stale issue. Set to `false` to disable 14 | closeComment: > 15 | This issue has been automatically closed because of inactivity. 16 | Please open a new issue if are still encountering problems. 17 | # Limit to only `issues` or `pulls` 18 | only: issues 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS generated files # 2 | ###################### 3 | .DS_Store 4 | .DS_Store? 5 | ._* 6 | .Spotlight-V100 7 | .Trashes 8 | Icon? 9 | ehthumbs.db 10 | Thumbs.db 11 | src/Documentation/* 12 | src/docs/docset/* 13 | src/docs/docset-installed.txt 14 | src/aws-ios-sdk-*.zip 15 | 16 | # Xcode generated files # 17 | ###################### 18 | xcuserdata 19 | *.xccheckout 20 | *.xcscmblueprint 21 | 22 | # Patched code # 23 | ###################### 24 | *.bak 25 | 26 | # Built assets # 27 | ###################### 28 | build 29 | buildFramework 30 | AWS*.framework 31 | 32 | # Stuff that can't be committed # 33 | ###################### 34 | credentials.json 35 | Podfile.lock 36 | **/Pods 37 | -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import UIKit 17 | import AWSCore 18 | 19 | @UIApplicationMain 20 | class AppDelegate: UIResponder, UIApplicationDelegate { 21 | 22 | var window: UIWindow? 23 | 24 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 25 | // Override point for customization after application launch. 26 | 27 | // Setting up logging to xcode console. 28 | AWSDDLog.sharedInstance.logLevel = .debug 29 | AWSDDLog.add(AWSDDTTYLogger.sharedInstance) 30 | 31 | return true 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift/Assets.xcassets/first.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "first.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift/Assets.xcassets/first.imageset/first.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-sdk-ios-samples/0343d828361b5b9f21e57d3d23cb6d18f45689a7/IoT-Sample/Swift/IoTSampleSwift/Assets.xcassets/first.imageset/first.pdf -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift/Assets.xcassets/second.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "second.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift/Assets.xcassets/second.imageset/second.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-sdk-ios-samples/0343d828361b5b9f21e57d3d23cb6d18f45689a7/IoT-Sample/Swift/IoTSampleSwift/Assets.xcassets/second.imageset/second.pdf -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift/ConfigurationViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import UIKit 17 | import AWSIoT 18 | 19 | class ConfigurationViewController: UIViewController, UITextFieldDelegate { 20 | 21 | @IBOutlet weak var deleteCertificateButton: UIButton! 22 | @IBOutlet weak var topicTextField: UITextField! 23 | 24 | @IBAction func deleteCertificateButtonPressed(_ sender: AnyObject) { 25 | let actionController: UIAlertController = UIAlertController( title: nil, message: nil, preferredStyle: .actionSheet) 26 | let cancelAction: UIAlertAction = UIAlertAction( title: "Cancel", style: .cancel) { action -> Void in 27 | } 28 | 29 | actionController.addAction( cancelAction ) 30 | 31 | let okAction: UIAlertAction = UIAlertAction( title: "Delete", style: .default) { action -> Void in 32 | print( "deleting identity...") 33 | 34 | // To delete an identity created via the API: 35 | // 36 | // 1) Set the certificate's status to 'inactive' 37 | // 2) Detach the policy from the certificate 38 | // 3) Delete the certificate 39 | // 4) Remove the keys and certificate from the keychain 40 | // 5) Delete user defaults 41 | // 42 | // To delete an identity created via a PKCS12 file in the bundle: 43 | // 44 | // 1) Remove the keys and certificate from the keychain 45 | // 2) Delete user defaults 46 | 47 | let defaults = UserDefaults.standard 48 | let certificateId = defaults.string( forKey: "certificateId") 49 | let certificateArn = defaults.string( forKey: "certificateArn") 50 | 51 | if certificateArn != "from-bundle" && certificateId != nil 52 | { 53 | let iot = AWSIoT.default() 54 | 55 | let updateCertificateRequest = AWSIoTUpdateCertificateRequest() 56 | updateCertificateRequest?.certificateId = certificateId 57 | updateCertificateRequest?.latestStatus = .inactive 58 | 59 | iot.updateCertificate( updateCertificateRequest! ).continueWith(block:{ (task) -> AnyObject? in 60 | 61 | if let error = task.error { 62 | print("failed: [\(error)]") 63 | } 64 | print("result: [\(String(describing: task.result))]") 65 | if (task.error == nil) 66 | { 67 | // The certificate is now inactive; detach the policy from the certificate. 68 | let certificateArn = defaults.string( forKey: "certificateArn") 69 | let detachPolicyRequest = AWSIoTDetachPrincipalPolicyRequest() 70 | detachPolicyRequest?.principal = certificateArn 71 | detachPolicyRequest?.policyName = POLICY_NAME 72 | 73 | iot.detachPrincipalPolicy(detachPolicyRequest!).continueWith(block: { (task) -> AnyObject? in 74 | if let error = task.error { 75 | print("failed: [\(error)]") 76 | } 77 | print("result: [\(String(describing: task.result))]") 78 | if (task.error == nil) 79 | { 80 | // The policy is now detached; delete the certificate 81 | let deleteCertificateRequest = AWSIoTDeleteCertificateRequest() 82 | deleteCertificateRequest?.certificateId = certificateId 83 | 84 | iot.deleteCertificate(deleteCertificateRequest!).continueWith(block: { (task) -> AnyObject? in 85 | 86 | if let error = task.error { 87 | print("failed: [\(error)]") 88 | } 89 | print("result: [\(String(describing: task.result))]") 90 | if (task.error == nil) 91 | { 92 | // The certificate has been deleted; now delete the keys and certificate from the keychain. 93 | if (AWSIoTManager.deleteCertificate() != true) 94 | { 95 | print("error deleting certificate") 96 | } 97 | else 98 | { 99 | defaults.removeObject(forKey: "certificateId") 100 | defaults.removeObject(forKey: "certificateArn") 101 | DispatchQueue.main.async { 102 | self.tabBarController?.selectedIndex = 0 103 | } 104 | } 105 | } 106 | return nil 107 | }) 108 | } 109 | return nil 110 | }) 111 | } 112 | return nil 113 | }) 114 | 115 | } 116 | else if certificateArn == "from-bundle" 117 | { 118 | // Delete the keys and certificate from the keychain. 119 | if (AWSIoTManager.deleteCertificate() != true) 120 | { 121 | print("error deleting certificate") 122 | } 123 | else 124 | { 125 | defaults.removeObject(forKey: "certificateId") 126 | defaults.removeObject(forKey: "certificateArn") 127 | DispatchQueue.main.async { 128 | self.tabBarController?.selectedIndex = 0 129 | } 130 | } 131 | } 132 | else 133 | { 134 | print("certificate id == nil!") // shouldn't be possible 135 | } 136 | 137 | } 138 | 139 | actionController.addAction( okAction ) 140 | self.present( actionController, animated: true, completion: nil ) 141 | } 142 | 143 | func textFieldShouldReturn(_ textField: UITextField) -> Bool { 144 | topicTextField.resignFirstResponder() 145 | return true 146 | } 147 | 148 | func textFieldDidEndEditing(_ textField: UITextField) { 149 | topicTextField.text = textField.text 150 | let defaults = UserDefaults.standard 151 | let tabBarViewController = tabBarController as! IoTSampleTabBarController 152 | tabBarViewController.topic = textField.text! 153 | defaults.set(textField.text, forKey:"sliderTopic") 154 | } 155 | 156 | override func viewDidLoad() { 157 | super.viewDidLoad() 158 | 159 | topicTextField.delegate = self 160 | let defaults = UserDefaults.standard 161 | let certificateId = defaults.string( forKey: "certificateId") 162 | let sliderTopic = defaults.string( forKey: "sliderTopic" ) 163 | let tabBarViewController = tabBarController as! IoTSampleTabBarController 164 | 165 | if (certificateId == nil) 166 | { 167 | deleteCertificateButton.isHidden=true 168 | } 169 | if (sliderTopic != nil) 170 | { 171 | tabBarViewController.topic=sliderTopic! 172 | } 173 | 174 | topicTextField.text = tabBarViewController.topic 175 | } 176 | 177 | override func viewWillAppear(_ animated: Bool) { 178 | super.viewWillAppear(animated) 179 | 180 | let defaults = UserDefaults.standard 181 | let certificateId = defaults.string( forKey: "certificateId") 182 | 183 | if (certificateId == nil) 184 | { 185 | deleteCertificateButton.isHidden=true 186 | } 187 | else 188 | { 189 | deleteCertificateButton.isHidden=false 190 | } 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift/ConnectionViewController+Websocket.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | import UIKit 16 | import AWSIoT 17 | import AWSMobileClient 18 | 19 | extension ConnectionViewController { 20 | 21 | func mqttEventCallbackWebsocket(_ status: AWSIoTMQTTStatus) { 22 | guard case .connected = status else { 23 | mqttEventCallback(status) 24 | return 25 | } 26 | 27 | DispatchQueue.main.async { 28 | let tabBarViewController = self.tabBarController as! IoTSampleTabBarController 29 | tabBarViewController.mqttStatus = "Connected" 30 | self.activityIndicatorView.stopAnimating() 31 | self.connected = true 32 | self.connectIoTDataWebSocket.setTitle("Disconnect \(self.IOT_WEBSOCKET)", for:UIControl.State()) 33 | self.logTextView.text = "Connected via websocket" 34 | self.connectIoTDataWebSocket.isEnabled = true 35 | tabBarViewController.viewControllers = [ self, self.publishViewController, self.subscribeViewController ] 36 | } 37 | } 38 | 39 | @objc func didTapConnectIoTDataWebSocket(_ sender: UIButton) { 40 | sender.isEnabled = false 41 | if (connected == false) { 42 | handleConnectViaWebsocket() 43 | } else { 44 | handleDisconnect() 45 | DispatchQueue.main.async { 46 | sender.setTitle("Connect \(self.IOT_WEBSOCKET)", for:UIControl.State()) 47 | sender.isEnabled = true 48 | } 49 | } 50 | } 51 | 52 | func handleConnectViaWebsocket() { 53 | self.connectButton.isHidden = true 54 | activityIndicatorView.startAnimating() 55 | DispatchQueue.main.async { 56 | self.logTextView.text = "Connecting (data plane)..." 57 | } 58 | let uuid = UUID().uuidString 59 | // Connect to the AWS IoT data plane service over websocket 60 | iotDataManager.connectUsingWebSocket(withClientId: uuid, cleanSession: true, statusCallback: mqttEventCallbackWebsocket(_:)) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift/Constants.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import Foundation 17 | import AWSCore 18 | 19 | //WARNING: To run this sample correctly, you must set the following constants. 20 | 21 | let CertificateSigningRequestCommonName = "IoTSampleSwift Application" 22 | let CertificateSigningRequestCountryName = "Your Country" 23 | let CertificateSigningRequestOrganizationName = "Your Organization" 24 | let CertificateSigningRequestOrganizationalUnitName = "Your Organizational Unit" 25 | 26 | let POLICY_NAME = "YourPolicyName" 27 | 28 | // This is the endpoint in your AWS IoT console. eg: https://xxxxxxxxxx.iot..amazonaws.com 29 | let AWS_REGION = AWSRegionType.Unknown 30 | 31 | //For both connecting over websockets and cert, IOT_ENDPOINT should look like 32 | //https://xxxxxxx-ats.iot.REGION.amazonaws.com 33 | let IOT_ENDPOINT = "https://xxxxxxxxxx.iot..amazonaws.com" 34 | let IDENTITY_POOL_ID = ":" 35 | 36 | //Used as keys to look up a reference of each manager 37 | let AWS_IOT_DATA_MANAGER_KEY = "MyIotDataManager" 38 | let AWS_IOT_MANAGER_KEY = "MyIotManager" 39 | -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIStatusBarTintParameters 34 | 35 | UINavigationBar 36 | 37 | Style 38 | UIBarStyleDefault 39 | Translucent 40 | 41 | 42 | 43 | UISupportedInterfaceOrientations 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | UISupportedInterfaceOrientations~ipad 50 | 51 | UIInterfaceOrientationPortrait 52 | UIInterfaceOrientationPortraitUpsideDown 53 | UIInterfaceOrientationLandscapeLeft 54 | UIInterfaceOrientationLandscapeRight 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift/IoTSampleSwift.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | keychain-access-groups 6 | 7 | $(AppIdentifierPrefix)Amazon-Web-Services.IoTSampleSwift 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift/IoTSampleTabBarController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import UIKit 17 | 18 | class IoTSampleTabBarController: UITabBarController { 19 | 20 | @objc var mqttStatus: String = "Disconnected" 21 | @objc var topic: String = "slider" 22 | } 23 | -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift/PublishViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import UIKit 17 | import AWSIoT 18 | 19 | class PublishViewController: UIViewController { 20 | 21 | @IBOutlet weak var publishSlider: UISlider! 22 | 23 | @IBAction func sliderValueChanged(_ sender: UISlider) { 24 | print("Publish slider value: " + "\(sender.value)") 25 | 26 | let iotDataManager = AWSIoTDataManager(forKey: AWS_IOT_DATA_MANAGER_KEY) 27 | let tabBarViewController = tabBarController as! IoTSampleTabBarController 28 | 29 | iotDataManager.publishString("\(sender.value)", onTopic:tabBarViewController.topic, qoS:.messageDeliveryAttemptedAtMostOnce) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /IoT-Sample/Swift/IoTSampleSwift/SubscribeViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import UIKit 17 | import AWSIoT 18 | 19 | class SubscribeViewController: UIViewController { 20 | 21 | @IBOutlet weak var subscribeSlider: UISlider! 22 | 23 | override func viewDidLoad() { 24 | super.viewDidLoad() 25 | 26 | // Do any additional setup after loading the view, typically from a nib. 27 | subscribeSlider.isEnabled = false 28 | } 29 | 30 | override func viewWillAppear(_ animated: Bool) { 31 | let iotDataManager = AWSIoTDataManager(forKey: AWS_IOT_DATA_MANAGER_KEY) 32 | let tabBarViewController = tabBarController as! IoTSampleTabBarController 33 | 34 | iotDataManager.subscribe(toTopic: tabBarViewController.topic, qoS: .messageDeliveryAttemptedAtMostOnce, messageCallback: { 35 | (payload) ->Void in 36 | let stringValue = NSString(data: payload, encoding: String.Encoding.utf8.rawValue)! 37 | 38 | print("received: \(stringValue)") 39 | DispatchQueue.main.async { 40 | self.subscribeSlider.value = stringValue.floatValue 41 | } 42 | } ) 43 | } 44 | 45 | override func viewWillDisappear(_ animated: Bool) { 46 | let iotDataManager = AWSIoTDataManager(forKey: AWS_IOT_DATA_MANAGER_KEY) 47 | let tabBarViewController = tabBarController as! IoTSampleTabBarController 48 | iotDataManager.unsubscribeTopic(tabBarViewController.topic) 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /IoT-Sample/Swift/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '12.0' 2 | use_frameworks! 3 | 4 | target 'IoTSampleSwift' do 5 | pod 'AWSMobileClient' 6 | pod 'AWSIoT' 7 | end 8 | -------------------------------------------------------------------------------- /IoT-Sample/Swift/README.md: -------------------------------------------------------------------------------- 1 | # The Amazon IoT Sample 2 | 3 | This sample demonstrates use of the AWS IoT APIs to securely publish to and subscribe from an MQTT topic. It uses Cognito authentication in conjunction with AWS IoT to create an identity (client certificate and private key) and store it in the iOS keychain. This identity is then used to authenticate to AWS IoT. Once a connection to the AWS IoT platform has been established, the application can operate in either the publish or subscribe role; the data format is a single floating point number in the range of 1-50. A configuration tab is provided allowing the user to select the name of the MQTT topic being published to or subscribed from, or to delete the identity. This application also supports the use of a pre-existing identity. 4 | 5 | ## Requirements 6 | 7 | * Xcode 9.2 and later 8 | * iOS 9 and later 9 | 10 | ## Using the Sample 11 | 12 | 1. The AWS Mobile SDK for iOS is available through [CocoaPods](http://cocoapods.org). If you have not installed CocoaPods, install CocoaPods: 13 | 14 | ```sh 15 | sudo gem install cocoapods 16 | pod setup 17 | ``` 18 | 19 | 1. To install the AWS Mobile SDK for iOS, change the current directory to the one with your **Podfile** in it and run the following command: 20 | 21 | ```sh 22 | pod install 23 | ``` 24 | 25 | 1. This sample requires Cognito to authorize to AWS IoT in order to create a device certificate. Use Amazon Cognito to create a new identity pool: 26 | 1. In the [Amazon Cognito Console](https://console.aws.amazon.com/cognito/), press the `Manage Federated Identities` button and on the resulting page press the `Create new identity pool` button. 27 | 1. Give your identity pool a name and ensure that `Enable access to unauthenticated identities` under the `Unauthenticated identities` section is checked. This allows the sample application to assume the unauthenticated role associated with this identity pool. Press the `Create Pool` button to create your identity pool. 28 | 29 | **Important**: see note below on unauthenticated user access. 30 | 31 | 1. As part of creating the identity pool, Cognito will setup two roles in [Identity and Access Management (IAM)](https://console.aws.amazon.com/iam/home#roles). These will be named something similar to: `Cognito_PoolNameAuth_Role` and `Cognito_PoolNameUnauth_Role`. You can view them by pressing the `View Details` button. Now press the `Allow` button to create the roles. 32 | 1. Save the `Identity pool ID` value that shows up in red in the "Getting started with Amazon Cognito" page, it should look similar to: `us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" and note the region that is being used. These will be used in the application code later. 33 | 1. Now we will attach a policy to the unauthenticated role which has permissions to access the required AWS IoT APIs. This is done by first creating an IAM Policy in the [IAM Console](https://console.aws.amazon.com/iam/home#roles) and then attaching it to the unauthenticated role. Click into Roles and search using the name used for the roles created above. Click on the link for the unauth role. Click on the "Add inline policy" button and add the following example policy which can be used with the sample application. This policy allows the application to create a new certificate (including private key) as well as attach an existing policy to a certificate. 34 | 35 | ```json 36 | { 37 | "Version": "2012-10-17", 38 | "Statement": [ 39 | { 40 | "Effect": "Allow", 41 | "Action": [ 42 | "iot:AttachPrincipalPolicy", 43 | "iot:CreateKeysAndCertificate", 44 | "iot:CreateCertificateFromCsr" 45 | ], 46 | "Resource": [ 47 | "*" 48 | ] 49 | } 50 | ] 51 | } 52 | ``` 53 | 54 | More information on AWS IAM roles and policies can be found [here](http://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage.html). More information on AWS IoT policies can be found [here](http://docs.aws.amazon.com/iot/latest/developerguide/authorization.html). 55 | 56 | **Note**: to keep this example simple it makes use of unauthenticated users in the identity pool. This can be used for getting started and prototypes but unauthenticated users should typically only be given read-only permissions if used in production applications. More information on Cognito identity pools including the Cognito developer guide can be found [here](http://aws.amazon.com/cognito/). 57 | 58 | 1. Note that the application does not actually create the AWS IoT policy itself, rather it relies on a policy to already be created in AWS IoT and then makes a call to attach that policy to the newly created certificate. To create a policy in AWS IoT, 59 | 1. Navigate to the [AWS IoT Console](https://console.aws.amazon.com/iot/home) and press the `Get Started` button. On the resulting page click on `Secure` on the side panel and the click on `Policies`. 60 | 1. Click on `Create a Policy` 61 | 1. Give the policy a name. Note this name as this is the string you will use in the application when making the attach policy API call. 62 | 1. The policy should be created to allow connecting to AWS IoT as well as allowing publishing, subscribing and receiving messages on whatever topics you will use in the sample application. Below is an example policy. This policy allows access to all topics under your AWS IoT account. To scope this policy down to specific topics specify them explicitly as ARNs in the resource section: `"Resource": "arn:aws:iot:::topic/mytopic/mysubtopic"`. Note that the first `topic` is an ARN specifer so this example actually specifies the topic `mytopic/mysubtopic`. 63 | 1. To add this policy, click on `Advanced Mode` and replace the default policy with the following text and then click the `Create` button. 64 | 65 | ```json 66 | { 67 | "Version": "2012-10-17", 68 | "Statement": [ 69 | { 70 | "Effect": "Allow", 71 | "Action": "iot:Connect", 72 | "Resource": "*" 73 | }, 74 | { 75 | "Effect": "Allow", 76 | "Action": [ 77 | "iot:Publish", 78 | "iot:Subscribe", 79 | "iot:Receive" 80 | ], 81 | "Resource": "*" 82 | } 83 | ] 84 | } 85 | ``` 86 | 87 | 1. Open `IoTSampleSwift.xcworkspace`. 88 | 89 | 1. Open `awsconfiguration.json` and update the Cognito Identity Pool ID (from the value you saved above) and Cognito region for Cognito Identity Pool ID (for example us-east-1). 90 | 91 | ```json 92 | "CredentialsProvider": { 93 | "CognitoIdentity": { 94 | "Default": { 95 | "PoolId": "CHANGE_ME", 96 | "Region": "CHANGE_ME" 97 | } 98 | } 99 | } 100 | ``` 101 | 102 | 1. Open `Constants.swift` and update the following lines with the appropriate constants: 103 | 104 | ```swift 105 | let CertificateSigningRequestCommonName = "IoTSampleSwift Application" 106 | let CertificateSigningRequestCountryName = "Your Country" 107 | let CertificateSigningRequestOrganizationName = "Your Organization" 108 | let CertificateSigningRequestOrganizationalUnitName = "Your Organizational Unit" 109 | let PolicyName = "YourPolicyName" 110 | 111 | let AwsRegion = AWSRegionType.Unknown 112 | let IOT_ENDPOINT = "https://xxxxxxxxxx.iot..amazonaws.com" // make sure to include "https://" prefix 113 | ``` 114 | 115 | Note: The endpoint can be found under [IoT Home](https://console.aws.amazon.com/iot/home). Once there, scroll down and click Settings on the side navigation on the left side. For Certificate details, navigate to ***Secure > Certificates*** and select the specific certificate to view certificate details such as CommonName (CN), OrganizationName (O), OrganizationUnit(OU), and Country (C). 116 | 117 | 1. Add the IoT certificate (IoT identity) to the Xcode project 118 | 1. Follow the instructions below to create the certificate 119 | 1. Place the PKCS #12 archive (.p12) in the same directory as Info.plist 120 | 1. Add it to the same group in Xcode as Info.plist 121 | 1. Select the build targets which will use this IoT identity 122 | 123 | 1. Build and run the sample app on two different simulators or devices. After you connect then changes in one devices publish panel will show up in the other devices subscribe panel. 124 | 125 | The sample application will allow you to connect to the AWS IoT platform, and then publish or subscribe to a topic using MQTT. You can configure the topic name under the 'Configuration' tab; it's set to 'slider' by default (only when you are disconnected). You can use another instance of this application so that one instance publishes while the other subscribes, or you can use the MQTT client in the [Amazon AWS IoT console](https://console.aws.amazon.com/iot/) to interact with your application. 126 | 127 | ## Prepare IoT Certificate for Identity 128 | 129 | You can also configure the sample application to use an existing AWS IoT identity. To do this, create a certificate and private key in the [Amazon AWS IoT console](https://console.aws.amazon.com/iot/) and associate it with a policy which allows access to 'iot:\*'. Go to the section named Secure and click on Certificates on the side navigation on the left sideN. Download the generated files and use the following command to create a PKCS #12 archive from the certificate and private key (NOTE: the filename must use the .p12 suffix): 130 | 131 | ```sh 132 | openssl pkcs12 -export -in certificate.pem.crt -inkey private.pem.key -out awsiot-identity.p12 133 | ``` 134 | 135 | When prompted for `Enter Export Password:`, enter the default empty string as the export password. 136 | 137 | The app will use this IoT identity instead of creating one dynamically. Note that when using your own certificate and private key, the "Delete" option under the "Configuration" tab only deletes them from the keychain; they remain in the application itself and will be re-added into the keychain the next time you connect. 138 | -------------------------------------------------------------------------------- /IoT-Sample/Swift/awsconfiguration.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "1.0", 3 | "IdentityManager": { 4 | "Default": {} 5 | }, 6 | "CredentialsProvider": { 7 | "CognitoIdentity": { 8 | "Default": { 9 | "PoolId": "CHANGE_ME", 10 | "Region": "CHANGE_ME" 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | 4 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 5 | 6 | 1. Definitions. 7 | 8 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 9 | 10 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 11 | 12 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 13 | 14 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 15 | 16 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 17 | 18 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 19 | 20 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 21 | 22 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 23 | 24 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 25 | 26 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 27 | 28 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 29 | 30 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 31 | 32 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 33 | 34 | 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and 35 | 2. You must cause any modified files to carry prominent notices stating that You changed the files; and 36 | 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 37 | 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 38 | 39 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 40 | 41 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 42 | 43 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 44 | 45 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 46 | 47 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 48 | 49 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 50 | 51 | END OF TERMS AND CONDITIONS 52 | 53 | ============================= 54 | 55 | ELCImagePickerController 56 | 57 | The MIT License 58 | 59 | Copyright (c) 2010 ELC Technologies 60 | 61 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 62 | 63 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 64 | 65 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 66 | 67 | ============================= 68 | 69 | JTSImageViewController 70 | 71 | The MIT License (MIT) 72 | 73 | Copyright (c) 2014 Jared Sinclair 74 | 75 | Permission is hereby granted, free of charge, to any person obtaining a copy 76 | of this software and associated documentation files (the "Software"), to deal 77 | in the Software without restriction, including without limitation the rights 78 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 79 | copies of the Software, and to permit persons to whom the Software is 80 | furnished to do so, subject to the following conditions: 81 | 82 | The above copyright notice and this permission notice shall be included in all 83 | copies or substantial portions of the Software. 84 | 85 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 86 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 87 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 88 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 89 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 90 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 91 | SOFTWARE. -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Lex-Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Lex-Sample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import 17 | 18 | @interface AppDelegate : UIResponder 19 | 20 | @property (strong, nonatomic) UIWindow *window; 21 | 22 | @end 23 | 24 | -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Lex-Sample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import "AppDelegate.h" 17 | #import "Constants.h" 18 | #import 19 | #import 20 | 21 | static NSString *AWSLexVoiceButtonIdentifierKey = @"AWSLexVoiceButton"; 22 | static NSString *AWSLexChatConfigIdentifierKey = @"chatConfig"; 23 | 24 | @interface AppDelegate () 25 | 26 | @end 27 | 28 | @implementation AppDelegate 29 | 30 | 31 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 32 | AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc] 33 | initWithRegionType:CognitoRegionType 34 | identityPoolId:CognitoIdentityPoolId]; 35 | 36 | AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:LexRegionType credentialsProvider:credentialsProvider]; 37 | 38 | [AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration; 39 | 40 | AWSLexInteractionKitConfig *config = [AWSLexInteractionKitConfig defaultInteractionKitConfigWithBotName:BotName botAlias:BotAlias]; 41 | 42 | [AWSLexInteractionKit registerInteractionKitWithServiceConfiguration:configuration interactionKitConfiguration:config forKey:AWSLexVoiceButtonIdentifierKey]; 43 | 44 | AWSLexInteractionKitConfig *chatConfig = [AWSLexInteractionKitConfig defaultInteractionKitConfigWithBotName:BotName botAlias:BotAlias]; 45 | chatConfig.autoPlayback = NO; 46 | [AWSLexInteractionKit registerInteractionKitWithServiceConfiguration:configuration interactionKitConfiguration:chatConfig forKey:AWSLexChatConfigIdentifierKey]; 47 | 48 | return YES; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Lex-Sample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Lex-Sample/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Lex-Sample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 101 | 102 | 103 | 104 | 105 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Lex-Sample/ChatViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import 17 | #import 18 | 19 | @interface ChatViewController : JSQMessagesViewController 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Lex-Sample/ChatViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import "ChatViewController.h" 17 | #import 18 | #import 19 | 20 | #define HEIGHT 100; 21 | #define CLIENT_SENDER_ID @"client" 22 | #define SERVER_SENDER_ID @"server" 23 | #define CONFIG_KEY @"chatConfig" 24 | 25 | @interface ChatViewController() 26 | 27 | @property (nonatomic, strong) NSMutableArray *messages; 28 | 29 | @property (nonatomic, strong) AWSLexInteractionKit *interactionKit; 30 | 31 | @property (nonatomic, strong) NSDictionary *sessionAttributes; 32 | 33 | @property (strong, nonatomic) JSQMessagesBubbleImage *outgoingBubbleImageData; 34 | 35 | @property (strong, nonatomic) JSQMessagesBubbleImage *incomingBubbleImageData; 36 | 37 | @end 38 | 39 | @implementation ChatViewController{ 40 | JSQMessage *speechMessage; 41 | NSUInteger speechIndex; 42 | AWSTaskCompletionSource *textModeSwitchingCompletion; 43 | NSUInteger count; 44 | } 45 | 46 | -(void)viewDidLoad{ 47 | [super viewDidLoad]; 48 | count = 0; 49 | self.interactionKit = [AWSLexInteractionKit interactionKitForKey:CONFIG_KEY]; 50 | self.interactionKit.interactionDelegate = self; 51 | self.interactionKit.microphoneDelegate = self; 52 | 53 | self.showLoadEarlierMessagesHeader = NO; 54 | self.collectionView.collectionViewLayout.incomingAvatarViewSize = CGSizeZero; 55 | self.collectionView.collectionViewLayout.outgoingAvatarViewSize = CGSizeZero; 56 | self.inputToolbar.contentView.textView.keyboardType = UIKeyboardTypeDefault; 57 | self.messages = [NSMutableArray new]; 58 | 59 | JSQMessagesBubbleImageFactory *bubbleFactory = [[JSQMessagesBubbleImageFactory alloc] init]; 60 | 61 | self.outgoingBubbleImageData = [bubbleFactory outgoingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleLightGrayColor]]; 62 | self.incomingBubbleImageData = [bubbleFactory incomingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleGreenColor]]; 63 | self.inputToolbar.contentView.leftBarButtonItem = nil; 64 | } 65 | 66 | - (void)didPressSendButton:(UIButton *)button 67 | withMessageText:(NSString *)text 68 | senderId:(NSString *)senderId 69 | senderDisplayName:(NSString *)senderDisplayName 70 | date:(NSDate *)date 71 | { 72 | JSQMessage *message = [[JSQMessage alloc] initWithSenderId:senderId 73 | senderDisplayName:senderDisplayName 74 | date:date 75 | text:text]; 76 | 77 | [self.messages addObject:message]; 78 | 79 | if(textModeSwitchingCompletion){ 80 | [textModeSwitchingCompletion setResult:text]; 81 | textModeSwitchingCompletion = nil; 82 | }else{ 83 | [self.interactionKit textInTextOut:text]; 84 | } 85 | [self finishSendingMessageAnimated:YES]; 86 | } 87 | 88 | - (NSString *)senderDisplayName 89 | { 90 | return @"Sender"; 91 | } 92 | 93 | - (NSString *)senderId 94 | { 95 | return CLIENT_SENDER_ID; 96 | } 97 | 98 | - (id)collectionView:(JSQMessagesCollectionView *)collectionView messageDataForItemAtIndexPath:(NSIndexPath *)indexPath 99 | { 100 | return [self.messages objectAtIndex:indexPath.item]; 101 | } 102 | 103 | - (void)collectionView:(JSQMessagesCollectionView *)collectionView didDeleteMessageAtIndexPath:(NSIndexPath *)indexPath 104 | { 105 | // Do nothing 106 | } 107 | 108 | - (id)collectionView:(JSQMessagesCollectionView *)collectionView messageBubbleImageDataForItemAtIndexPath:(NSIndexPath *)indexPath 109 | { 110 | 111 | JSQMessage *message = [self.messages objectAtIndex:indexPath.item]; 112 | 113 | if ([message.senderId isEqualToString:self.senderId]) { 114 | return self.outgoingBubbleImageData; 115 | } 116 | 117 | return self.incomingBubbleImageData; 118 | } 119 | 120 | - (id)collectionView:(JSQMessagesCollectionView *)collectionView avatarImageDataForItemAtIndexPath:(NSIndexPath *)indexPath 121 | { 122 | return nil; 123 | } 124 | 125 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 126 | { 127 | return [self.messages count]; 128 | } 129 | 130 | - (UICollectionViewCell *)collectionView:(JSQMessagesCollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 131 | { 132 | JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath]; 133 | 134 | JSQMessage *msg = [self.messages objectAtIndex:indexPath.item]; 135 | 136 | if (!msg.isMediaMessage) { 137 | 138 | if ([msg.senderId isEqualToString:self.senderId]) { 139 | cell.textView.textColor = [UIColor blackColor]; 140 | }else { 141 | cell.textView.textColor = [UIColor whiteColor]; 142 | } 143 | 144 | cell.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : cell.textView.textColor, 145 | NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) }; 146 | } 147 | 148 | return cell; 149 | } 150 | 151 | 152 | - (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath 153 | { 154 | JSQMessage *message = [self.messages objectAtIndex:indexPath.item]; 155 | return [[JSQMessagesTimestampFormatter sharedFormatter] attributedTimestampForDate:message.date]; 156 | } 157 | 158 | - (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForMessageBubbleTopLabelAtIndexPath:(NSIndexPath *)indexPath 159 | { 160 | JSQMessage *message = [self.messages objectAtIndex:indexPath.item]; 161 | 162 | // iOS7-style sender name labels 163 | 164 | if ([message.senderId isEqualToString:self.senderId]) { 165 | return nil; 166 | } 167 | 168 | if (indexPath.item - 1 > 0) { 169 | JSQMessage *previousMessage = [self.messages objectAtIndex:indexPath.item - 1]; 170 | if ([[previousMessage senderId] isEqualToString:message.senderId]) { 171 | return nil; 172 | } 173 | } 174 | 175 | // Don't specify attributes to use the defaults. 176 | return [[NSAttributedString alloc] initWithString:message.senderDisplayName]; 177 | } 178 | 179 | - (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellBottomLabelAtIndexPath:(NSIndexPath *)indexPath 180 | { 181 | return nil; 182 | } 183 | 184 | - (BOOL)composerTextView:(JSQMessagesComposerTextView *)textView shouldPasteWithSender:(id)sender 185 | { 186 | return YES; 187 | } 188 | 189 | - (void)messageView:(JSQMessagesCollectionView *)view didTapAccessoryButtonAtIndexPath:(NSIndexPath *)path 190 | { 191 | NSLog(@"Tapped accessory button!"); 192 | } 193 | 194 | #pragma mark InteractionKit 195 | 196 | - (void)interactionKit:(AWSLexInteractionKit *)interactionKit 197 | onError:(NSError *)error{ 198 | // Do nothing for now. 199 | NSLog(@"error occured %@", error); 200 | } 201 | 202 | - (void)interactionKit:(AWSLexInteractionKit *)interactionKit 203 | switchModeInput:(AWSLexSwitchModeInput *)switchModeInput 204 | completionSource:(AWSTaskCompletionSource *)completionSource{ 205 | 206 | self.sessionAttributes = switchModeInput.sessionAttributes; 207 | 208 | dispatch_async(dispatch_get_main_queue(), ^{ 209 | JSQMessage *message = nil; 210 | 211 | if (switchModeInput.outputText != nil) { 212 | message = [[JSQMessage alloc] initWithSenderId:SERVER_SENDER_ID 213 | senderDisplayName:@"" 214 | date:[[NSDate alloc]init] 215 | text:switchModeInput.outputText]; 216 | 217 | [self.messages addObject:message]; 218 | } 219 | 220 | [self finishSendingMessageAnimated:YES]; 221 | }); 222 | 223 | // This can expand to take input from user. 224 | AWSLexSwitchModeResponse *switchModeResponse = [AWSLexSwitchModeResponse new]; 225 | [switchModeResponse setInteractionMode:AWSLexInteractionModeText]; 226 | [switchModeResponse setSessionAttributes:switchModeInput.sessionAttributes]; 227 | [completionSource setResult:switchModeResponse]; 228 | 229 | } 230 | 231 | /* 232 | * Sent to delegate when the Switch mode requires a user to input a text. You should set the completion source result to the string that you get from the user. This ensures that the session attribute information is carried over from the previous request to the next one. 233 | */ 234 | - (void)interactionKitContinueWithText:(AWSLexInteractionKit *)interactionKit 235 | completionSource:(AWSTaskCompletionSource *)completionSource{ 236 | textModeSwitchingCompletion = completionSource; 237 | } 238 | #pragma mark - 239 | 240 | @end 241 | -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Lex-Sample/Constants.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import 17 | #import 18 | 19 | FOUNDATION_EXPORT AWSRegionType const CognitoRegionType; 20 | FOUNDATION_EXPORT AWSRegionType const LexRegionType; 21 | FOUNDATION_EXPORT NSString *const CognitoIdentityPoolId; 22 | FOUNDATION_EXPORT NSString *const BotName; 23 | FOUNDATION_EXPORT NSString *const BotAlias; 24 | 25 | @interface Constants : NSObject 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Lex-Sample/Constants.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import "Constants.h" 17 | 18 | #warning To run this sample correctly, you must set the following constants. 19 | 20 | AWSRegionType const CognitoRegionType = AWSRegionUnknown; // e.g. AWSRegionUSEast1 21 | AWSRegionType const LexRegionType = AWSRegionUnknown; 22 | NSString *const CognitoIdentityPoolId = @"YourCognitoIdentityPoolId"; 23 | NSString *const BotName = @"YourBotName"; 24 | NSString *const BotAlias = @"$LATEST"; 25 | 26 | @implementation Constants 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Lex-Sample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSMicrophoneUsageDescription 26 | For recording Audio and transmitting it to service 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Lex-Sample/TableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import 17 | 18 | @interface TableViewController : UITableViewController 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Lex-Sample/TableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import "TableViewController.h" 17 | 18 | @interface TableViewController () 19 | 20 | @property (nonatomic, strong) NSArray *conversationTypes; 21 | 22 | 23 | @end 24 | 25 | @implementation TableViewController 26 | 27 | - (void)viewDidLoad { 28 | [super viewDidLoad]; 29 | 30 | self.conversationTypes = [[NSArray alloc]initWithObjects:@"Voice", @"Chat", nil]; 31 | 32 | } 33 | 34 | - (void)didReceiveMemoryWarning { 35 | [super didReceiveMemoryWarning]; 36 | 37 | } 38 | 39 | #pragma mark - Table view data source 40 | 41 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 42 | return 1; 43 | } 44 | 45 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 46 | return [self.conversationTypes count]; 47 | } 48 | 49 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 50 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"reuseIdentifier" forIndexPath:indexPath]; 51 | if(!cell){ 52 | cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"reuseIdentifier"]; 53 | } 54 | 55 | cell.textLabel.text = [self.conversationTypes objectAtIndex:indexPath.row]; 56 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 57 | 58 | return cell; 59 | } 60 | 61 | - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 62 | if(indexPath.row == 0){ 63 | [self performSegueWithIdentifier:@"voicecontroller" sender:self]; 64 | }else{ 65 | [self performSegueWithIdentifier:@"chatcontroller" sender:self]; 66 | } 67 | } 68 | 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Lex-Sample/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import 17 | #import 18 | 19 | @interface ViewController : UIViewController 20 | 21 | @property (weak, nonatomic) IBOutlet AWSLexVoiceButton *voiceButton; 22 | @property (weak, nonatomic) IBOutlet UILabel *output; 23 | @property (weak, nonatomic) IBOutlet UILabel *input; 24 | 25 | 26 | @property (nonatomic, weak) id delegate; 27 | @end 28 | 29 | -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Lex-Sample/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import "ViewController.h" 17 | 18 | @interface ViewController () 19 | 20 | @end 21 | 22 | @implementation ViewController 23 | 24 | - (void)viewDidLoad { 25 | [super viewDidLoad]; 26 | self.voiceButton.delegate = self; 27 | // Do any additional setup after loading the view, typically from a nib. 28 | } 29 | 30 | #pragma mark - VoiceButtonDelegate Methods 31 | 32 | - (void)voiceButton:(AWSLexVoiceButton *)button onResponse:(nonnull AWSLexVoiceButtonResponse *)response{ 33 | // `inputTranscript` is the transcript of the voice input to the operation 34 | NSLog(@"Input Transcript: %@", response.inputTranscript); 35 | self.input.text = [NSString stringWithFormat:@"\"%@\"", response.inputTranscript]; 36 | 37 | NSLog(@"on text output %@", response.outputText); 38 | self.output.text = response.outputText; 39 | } 40 | 41 | - (void)voiceButton:(AWSLexVoiceButton *)button onError:(NSError *)error{ 42 | NSLog(@"error %@", error); 43 | } 44 | 45 | #pragma mark - 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Lex-Sample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | #import 17 | #import "AppDelegate.h" 18 | 19 | int main(int argc, char * argv[]) { 20 | @autoreleasepool { 21 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Lex-Sample/ObjC/Podfile: -------------------------------------------------------------------------------- 1 | ENV['SWIFT_VERSION'] = '5' 2 | platform :ios, '12.0' 3 | use_frameworks! 4 | target :'Lex-Sample' do 5 | pod 'JSQMessagesViewController', '~>7.3.4' 6 | pod 'AWSLex' 7 | end 8 | 9 | post_install do |installer| 10 | installer.pods_project.targets.each do |target| 11 | target.build_configurations.each do |config| 12 | config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET' 13 | end 14 | end 15 | end -------------------------------------------------------------------------------- /Lex-Sample/Swift/.gitignore: -------------------------------------------------------------------------------- 1 | *.xcworkspace/ 2 | -------------------------------------------------------------------------------- /Lex-Sample/Swift/LexSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Lex-Sample/Swift/LexSwift/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | import UIKit 17 | import AWSCore 18 | import AWSLex 19 | import AWSMobileClient 20 | 21 | @UIApplicationMain 22 | class AppDelegate: UIResponder, UIApplicationDelegate { 23 | 24 | var window: UIWindow? 25 | 26 | 27 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 28 | 29 | 30 | AWSMobileClient.sharedInstance().initialize { (userState, error) in 31 | guard error == nil else { 32 | print("Error initializing AWSMobileClient. Error: \(error!.localizedDescription)") 33 | return 34 | } 35 | print("AWSMobileClient initialized.") 36 | } 37 | 38 | let configuration = AWSServiceConfiguration(region: LexRegion, credentialsProvider: AWSMobileClient.sharedInstance()) 39 | AWSServiceManager.default().defaultServiceConfiguration = configuration 40 | 41 | let chatConfig = AWSLexInteractionKitConfig.defaultInteractionKitConfig(withBotName: BotName, botAlias: BotAlias) 42 | AWSLexInteractionKit.register(with: configuration!, interactionKitConfiguration: chatConfig, forKey: "AWSLexVoiceButton") 43 | chatConfig.autoPlayback = false 44 | AWSLexInteractionKit.register(with: configuration!, interactionKitConfiguration: chatConfig, forKey: "chatConfig") 45 | 46 | // Override point for customization after application launch. 47 | return true 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /Lex-Sample/Swift/LexSwift/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /Lex-Sample/Swift/LexSwift/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Lex-Sample/Swift/LexSwift/ChatViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | import Foundation 17 | import JSQMessagesViewController 18 | import AWSLex 19 | 20 | let ClientSenderId = "Client" 21 | let ServerSenderId = "Server" 22 | 23 | class ChatViewController: JSQMessagesViewController, JSQMessagesComposerTextViewPasteDelegate { 24 | 25 | @objc var messages: [JSQMessage]? 26 | @objc var interactionKit: AWSLexInteractionKit? 27 | @objc var sessionAttributes: [AnyHashable: Any]? 28 | @objc var outgoingBubbleImageData: JSQMessagesBubbleImage? 29 | @objc var incomingBubbleImageData: JSQMessagesBubbleImage? 30 | 31 | @objc var speechMessage: JSQMessage? 32 | @objc var speechIndex: Int = 0 33 | @objc var textModeSwitchingCompletion: AWSTaskCompletionSource? 34 | var count: Int? 35 | 36 | override func viewDidLoad() { 37 | super.viewDidLoad() 38 | count = 0 39 | self.interactionKit = AWSLexInteractionKit.init(forKey: "chatConfig") 40 | self.interactionKit?.interactionDelegate = self 41 | 42 | self.showLoadEarlierMessagesHeader = false 43 | self.collectionView?.collectionViewLayout.incomingAvatarViewSize = CGSize.zero 44 | self.collectionView?.collectionViewLayout.outgoingAvatarViewSize = CGSize.zero 45 | 46 | self.inputToolbar.contentView?.textView?.keyboardType = UIKeyboardType.default 47 | self.messages = [JSQMessage]() 48 | 49 | let bubbleFactory = JSQMessagesBubbleImageFactory() 50 | self.outgoingBubbleImageData = bubbleFactory?.outgoingMessagesBubbleImage(with: UIColor.jsq_messageBubbleLightGray()) 51 | self.incomingBubbleImageData = bubbleFactory?.incomingMessagesBubbleImage(with: UIColor.jsq_messageBubbleGreen()) 52 | 53 | self.inputToolbar.contentView?.leftBarButtonItem = nil; 54 | 55 | } 56 | 57 | override func didPressSend(_ button: UIButton, withMessageText text: String, senderId: String, senderDisplayName: String, date: Date) { 58 | let message = JSQMessage(senderId: senderId, senderDisplayName: senderDisplayName, date: date, text: text) 59 | self.messages?.append(message!) 60 | 61 | if let textModeSwitchingCompletion = textModeSwitchingCompletion { 62 | textModeSwitchingCompletion.set(result: text as NSString) 63 | self.textModeSwitchingCompletion = nil 64 | } 65 | else { 66 | self.interactionKit?.text(inTextOut: text) 67 | } 68 | self.finishSendingMessage(animated: true) 69 | } 70 | 71 | override var senderDisplayName:String! { 72 | get{ 73 | return "John Doe" 74 | } 75 | set{ 76 | //do nothing 77 | } 78 | } 79 | 80 | override var senderId:String! { 81 | get{ 82 | return ClientSenderId 83 | } 84 | set{ 85 | //do nothing 86 | } 87 | } 88 | 89 | override func collectionView(_ collectionView: JSQMessagesCollectionView, messageDataForItemAt indexPath: IndexPath) -> JSQMessageData { 90 | 91 | return self.messages![indexPath.item] 92 | } 93 | 94 | override func collectionView(_ collectionView: JSQMessagesCollectionView, didDeleteMessageAt indexPath: IndexPath) { 95 | //DO NOTHING 96 | } 97 | 98 | override func collectionView(_ collectionView: JSQMessagesCollectionView, messageBubbleImageDataForItemAt indexPath: IndexPath) -> JSQMessageBubbleImageDataSource { 99 | let message = self.messages![indexPath.item] 100 | if (message.senderId == self.senderId) { 101 | return self.outgoingBubbleImageData! 102 | } 103 | return self.incomingBubbleImageData! 104 | } 105 | 106 | override func collectionView(_ collectionView: JSQMessagesCollectionView, avatarImageDataForItemAt indexPath: IndexPath) -> JSQMessageAvatarImageDataSource? { 107 | return nil 108 | } 109 | 110 | override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 111 | if let messages = messages { 112 | return messages.count 113 | } 114 | return 0 115 | } 116 | 117 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 118 | 119 | let cell = (super.collectionView(collectionView, cellForItemAt: indexPath) as! JSQMessagesCollectionViewCell) 120 | let msg = self.messages?[indexPath.item] 121 | if !msg!.isMediaMessage { 122 | if (msg?.senderId == self.senderId) { 123 | cell.textView?.textColor = UIColor.black 124 | } 125 | else { 126 | cell.textView?.textColor = UIColor.white 127 | } 128 | } 129 | return cell 130 | } 131 | 132 | override func collectionView(_ collectionView: JSQMessagesCollectionView, attributedTextForCellTopLabelAt indexPath: IndexPath) -> NSAttributedString? { 133 | if indexPath.item % 3 == 0 { 134 | let message = self.messages?[indexPath.item] 135 | return JSQMessagesTimestampFormatter.shared().attributedTimestamp(for: message!.date) 136 | } 137 | return nil 138 | } 139 | 140 | override func collectionView(_ collectionView: JSQMessagesCollectionView, attributedTextForMessageBubbleTopLabelAt indexPath: IndexPath) -> NSAttributedString? { 141 | let message = self.messages?[indexPath.item] 142 | /** 143 | * iOS7-style sender name labels 144 | */ 145 | if (message?.senderId == self.senderId) { 146 | return nil 147 | } 148 | if indexPath.item - 1 > 0 { 149 | let previousMessage = self.messages?[indexPath.item - 1] 150 | if (previousMessage?.senderId == message?.senderId) { 151 | return nil 152 | } 153 | } 154 | /** 155 | * Don't specify attributes to use the defaults. 156 | */ 157 | return NSAttributedString(string: message!.senderDisplayName) 158 | } 159 | 160 | override func collectionView(_ collectionView: JSQMessagesCollectionView, attributedTextForCellBottomLabelAt indexPath: IndexPath) -> NSAttributedString? { 161 | return nil 162 | } 163 | 164 | public func composerTextView(_ textView: JSQMessagesComposerTextView, shouldPasteWithSender sender: Any) -> Bool { 165 | return true 166 | } 167 | 168 | } 169 | 170 | // MARK: Interaction Kit 171 | extension ChatViewController: AWSLexInteractionDelegate { 172 | 173 | @objc public func interactionKitOnRecordingEnd(_ interactionKit: AWSLexInteractionKit, audioStream: Data, contentType: String) { 174 | DispatchQueue.main.async(execute: { 175 | let audioItem = JSQAudioMediaItem(data: audioStream) 176 | self.speechMessage = JSQMessage(senderId: ClientSenderId, displayName: "", media: audioItem) 177 | 178 | self.messages?[self.speechIndex] = self.speechMessage! 179 | self.finishSendingMessage(animated: true) 180 | }) 181 | } 182 | 183 | public func interactionKit(_ interactionKit: AWSLexInteractionKit, onError error: Error) { 184 | //do nothing for now. 185 | } 186 | 187 | public func interactionKit(_ interactionKit: AWSLexInteractionKit, switchModeInput: AWSLexSwitchModeInput, completionSource: AWSTaskCompletionSource?) { 188 | self.sessionAttributes = switchModeInput.sessionAttributes 189 | DispatchQueue.main.async(execute: { 190 | let message: JSQMessage 191 | // Handle a successful fulfillment 192 | if (switchModeInput.dialogState == AWSLexDialogState.readyForFulfillment) { 193 | // Currently just displaying the slots returned on ready for fulfillment 194 | if let slots = switchModeInput.slots { 195 | message = JSQMessage(senderId: ServerSenderId, senderDisplayName: "", date: Date(), text: "Slots:\n\(slots)") 196 | self.messages?.append(message) 197 | self.finishSendingMessage(animated: true) 198 | } 199 | } else { 200 | //if you have special characters you need to be returned, make sure you base 64 encode your responses in your bot and then they will be decoded here as needed. 201 | guard let text = switchModeInput.outputText else { 202 | return //no response was returned 203 | } 204 | if let base64DecodedText = text.base64Decoded { 205 | message = JSQMessage(senderId: ServerSenderId, senderDisplayName: "", date: Date(), text: base64DecodedText) 206 | } else { 207 | message = JSQMessage(senderId: ServerSenderId, senderDisplayName: "", date: Date(), text: text) 208 | } 209 | 210 | self.messages?.append(message) 211 | self.finishSendingMessage(animated: true) 212 | } 213 | }) 214 | //this can expand to take input from user. 215 | let switchModeResponse = AWSLexSwitchModeResponse() 216 | switchModeResponse.interactionMode = AWSLexInteractionMode.text 217 | switchModeResponse.sessionAttributes = switchModeInput.sessionAttributes 218 | completionSource?.set(result: switchModeResponse) 219 | } 220 | 221 | /* 222 | * Sent to delegate when the Switch mode requires a user to input a text. You should set the completion source result to the string that you get from the user. This ensures that the session attribute information is carried over from the previous request to the next one. 223 | */ 224 | func interactionKitContinue(withText interactionKit: AWSLexInteractionKit, completionSource: AWSTaskCompletionSource) { 225 | textModeSwitchingCompletion = completionSource 226 | } 227 | 228 | } 229 | -------------------------------------------------------------------------------- /Lex-Sample/Swift/LexSwift/Constants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | import Foundation 17 | import AWSCore 18 | 19 | // WARNING: To run this sample correctly, you must set the following constants. 20 | 21 | let LexRegion = AWSRegionType.Unknown // Change this is this is not your Lex region (most are currently AWSRegionType.USEast1) 22 | let BotName = "BotName" // Put your bot name here 23 | let BotAlias = "$LATEST" // You can leave this if you always want to use 24 | // the latest version of your bot or put the version 25 | -------------------------------------------------------------------------------- /Lex-Sample/Swift/LexSwift/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSMicrophoneUsageDescription 6 | For recording Audio and transmitting it to service 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleDisplayName 10 | Lex Sample 11 | CFBundleExecutable 12 | $(EXECUTABLE_NAME) 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | $(PRODUCT_NAME) 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1 27 | LSRequiresIPhoneOS 28 | 29 | UILaunchStoryboardName 30 | LaunchScreen 31 | UIMainStoryboardFile 32 | Main 33 | UIRequiredDeviceCapabilities 34 | 35 | armv7 36 | 37 | UISupportedInterfaceOrientations 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | UISupportedInterfaceOrientations~ipad 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationPortraitUpsideDown 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /Lex-Sample/Swift/LexSwift/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 101 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /Lex-Sample/Swift/LexSwift/StringExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StringExtension.swift 3 | // LexSwift 4 | // 5 | // Created by Stone, Nicki on 4/10/20. 6 | // 7 | 8 | import Foundation 9 | 10 | public extension String { 11 | 12 | /// Assuming the current string is base64 encoded, this property returns a String 13 | /// initialized by converting the current string into Unicode characters, encoded to 14 | /// utf8. If the current string is not base64 encoded, nil is returned instead. 15 | var base64Decoded: String? { 16 | guard let base64 = Data(base64Encoded: self) else { return nil } 17 | let utf8 = String(data: base64, encoding: .utf8) 18 | return utf8 19 | } 20 | 21 | /// Returns a base64 representation of the current string, or nil if the 22 | /// operation fails. 23 | var base64Encoded: String? { 24 | let utf8 = self.data(using: .utf8) 25 | let base64 = utf8?.base64EncodedString() 26 | return base64 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Lex-Sample/Swift/LexSwift/TableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | import Foundation 17 | import UIKit 18 | 19 | class TableViewController: UITableViewController { 20 | 21 | @objc var conversationTypes: [String]? 22 | 23 | override func viewDidLoad() { 24 | super.viewDidLoad() 25 | self.conversationTypes = ["Voice", "Chat"] 26 | } 27 | 28 | override func numberOfSections(in tableView: UITableView) -> Int { 29 | return 1 30 | } 31 | 32 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 33 | return self.conversationTypes!.count 34 | } 35 | 36 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 37 | let cell = UITableViewCell(style: .default, reuseIdentifier: "reuseIdentifier") 38 | cell.textLabel?.text = self.conversationTypes![indexPath.row] 39 | cell.accessoryType = .disclosureIndicator 40 | return cell 41 | } 42 | 43 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 44 | if indexPath.row == 0 { 45 | self.performSegue(withIdentifier: "voicecontroller", sender: self) 46 | } 47 | else { 48 | self.performSegue(withIdentifier: "chatcontroller", sender: self) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Lex-Sample/Swift/LexSwift/VoiceChatViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). 5 | // You may not use this file except in compliance with the License. 6 | // A copy of the License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | // 15 | 16 | import Foundation 17 | import AWSLex 18 | import UIKit 19 | 20 | 21 | class VoiceChatViewController: UIViewController, AWSLexVoiceButtonDelegate { 22 | 23 | @IBOutlet weak var voiceButton: AWSLexVoiceButton! 24 | @IBOutlet weak var input: UILabel! 25 | @IBOutlet weak var output: UILabel! 26 | 27 | override func viewDidLoad() { 28 | super.viewDidLoad() 29 | (self.voiceButton as AWSLexVoiceButton).delegate = self 30 | } 31 | 32 | func voiceButton(_ button: AWSLexVoiceButton, on response: AWSLexVoiceButtonResponse) { 33 | DispatchQueue.main.async(execute: { 34 | // `inputTranscript` is the transcript of the voice input to the operation 35 | if let inputTranscript = response.inputTranscript { 36 | print("Input Transcript: " + inputTranscript) 37 | self.input.text = "\"\(inputTranscript)\"" 38 | } 39 | 40 | if let outputText = response.outputText { 41 | print("Output Transcript: " + outputText) 42 | self.output.text = outputText 43 | } else { 44 | self.output.text = "" 45 | } 46 | }) 47 | } 48 | 49 | public func voiceButton(_ button: AWSLexVoiceButton, onError error: Error) { 50 | print("error \(error)") 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /Lex-Sample/Swift/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '12.0' 2 | use_frameworks! 3 | target :'LexSwift' do 4 | pod 'JSQMessagesViewController', '~>7.3.4' 5 | 6 | pod 'AWSMobileClient' 7 | pod 'AWSLex' 8 | end 9 | 10 | post_install do |installer| 11 | installer.pods_project.targets.each do |target| 12 | target.build_configurations.each do |config| 13 | config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET' 14 | end 15 | end 16 | end 17 | 18 | -------------------------------------------------------------------------------- /Lex-Sample/Swift/README.md: -------------------------------------------------------------------------------- 1 | # The Amazon Lex Sample 2 | 3 | This sample demonstrates how to use Amazon Lex interaction client library on iOS. This application uses AWS Cognito for authentication with Amazon Lex. 4 | 5 | ## Requirements 6 | 7 | * Xcode 9.2 and later 8 | * iOS 9 and later 9 | 10 | ## Using the Sample 11 | 12 | 1. The AWS Mobile SDK for iOS is available through [CocoaPods](http://cocoapods.org). If you have not installed CocoaPods, install CocoaPods: 13 | 14 | sudo gem install cocoapods 15 | pod setup 16 | 17 | 1. To install the AWS Mobile SDK for iOS, change the current directory to the one with your **Podfile** in it and run the following command: 18 | 19 | pod install 20 | 21 | 1. This sample requires Cognito to authorize to Amazon Lex to post content. Use Amazon Cognito to create a new identity pool: 22 | 1. In the [Amazon Cognito Console](https://console.aws.amazon.com/cognito/), press the `Manage Federated Identities` button and on the resulting page press the `Create new identity pool` button. 23 | 1. Give your identity pool a name and ensure that `Enable access to unauthenticated identities` under the `Unauthenticated identities` section is checked. This allows the sample application to assume the unauthenticated role associated with this identity pool. Press the `Create Pool` button to create your identity pool. 24 | 25 | **Important**: see note below on unauthenticated user access. 26 | 27 | 1. As part of creating the identity pool, Cognito will setup two roles in [Identity and Access Management (IAM)](https://console.aws.amazon.com/iam/home#roles). These will be named something similar to: `Cognito_PoolNameAuth_Role` and `Cognito_PoolNameUnauth_Role`. You can view them by pressing the `View Details` button. Now press the `Allow` button to create the roles. 28 | 1. Save the `Identity pool ID` value that shows up in red in the "Getting started with Amazon Cognito" page, it should look similar to: `us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` and note the region that is being used. These will be used in the application code later. 29 | 1. Now we will attach a policy to the unauthenticated role which has permissions to access the required Amazon Lex API. This is done by attaching an IAM Policy to the unauthenticated role in the [IAM Console](https://console.aws.amazon.com/iam/home#roles). First, search for the unauth role that you created in step 3 above (named something similar to `Cognito_PoolNameUnauth_Role`) and select its hyperlink. In the resulting "Summary" page press the `Attach Policy` button in the "Permissions" tab. 30 | 1. Search for "lex" and check the box next to the policy named `AmazonLexRunBotsOnly` and then press the `Attach Policy` button. This policy allows the application access to Amazon Lex conversational APIs. 31 | 32 | More information on AWS IAM roles and policies can be found [here](http://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage.html). More information on Amazon Lex policies can be found [here](http://docs.aws.amazon.com/lex/latest/dg/access-control-managing-permissions.html). 33 | 34 | **Note**: to keep this example simple it makes use of unauthenticated users in the identity pool. This can be used for getting started and prototypes but unauthenticated users should typically only be given read-only permissions in production applications. More information on Cognito identity pools including the Cognito developer guide can be found [here](http://aws.amazon.com/cognito/). 35 | 1. Use the [Amazon Lex console](https://console.aws.amazon.com/lex/home) to configure a bot that interacts with your mobile app features. To learn more, see [Amazon Lex Developer Guide](https://docs.aws.amazon.com/lex/latest/dg/what-is.html). For a quickstart, see [Getting Started](https://alpha-docs-aws.amazon.com/lex/latest/dg/getting-started.html). 36 | 37 | 1. Open `LexSwift.xcworkspace/`. 38 | 39 | 1. Open `awsconfiguration.json` and update the values for Cognito Identity Pool ID (from the value you saved above) and Cognito region for Cognito Identity Pool ID (for example us-east-1). 40 | 41 | ```json 42 | "CredentialsProvider": { 43 | "CognitoIdentity": { 44 | "Default": { 45 | "PoolId": "CHANGE_ME", 46 | "Region": "CHANGE_ME" 47 | } 48 | } 49 | } 50 | ``` 51 | 52 | 1. Open `Constants.swift` and update the following lines with the appropriate constants: 53 | 54 | ```swift 55 | let LexRegion = AWSRegionType.Unknown // Change this to your Lex region (most are currently AWSRegionType.USEast1) 56 | let BotName = "BotName" // Put your bot name here 57 | let BotAlias = "$LATEST" // You can leave this if you always want to use the latest version of your bot or put the version 58 | ``` 59 | 60 | 1. Build and run the sample app. 61 | -------------------------------------------------------------------------------- /Lex-Sample/Swift/awsconfiguration.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "1.0", 3 | "IdentityManager": { 4 | "Default": {} 5 | }, 6 | "CredentialsProvider": { 7 | "CognitoIdentity": { 8 | "Default": { 9 | "PoolId": "CHANGE_ME", 10 | "Region": "CHANGE_ME" 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Version 2 of AWS SDK Sample for iOS 2 | 3 | Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.  4 | 5 | This product includes software developed by Amazon Technologies, Inc (http://www.amazon.com/).  6 | 7 | Licensed under the Apache License Version 2.0 8 | 9 | See the License for the specific language governing permissions and limitations under the License. 10 | 11 | ********************** 12 | THIRD PARTY COMPONENTS 13 | ********************** 14 | 15 | This software includes third party software subject to the following copyrights: 16 | - ELCImagePickerController - Copyright (c) 2010 ELC Technologies - The MIT License 17 | - JTSImageViewController - Copyright (c) 2014 Jared Sinclair - MIT license 18 | 19 | The licenses for these third party components are included in the License file. 20 | -------------------------------------------------------------------------------- /Polly-Sample/Swift/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '12.0' 2 | use_frameworks! 3 | 4 | target 'PollySample' do 5 | pod 'AWSMobileClient' 6 | pod 'AWSPolly' 7 | end 8 | -------------------------------------------------------------------------------- /Polly-Sample/Swift/PollySample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Polly-Sample/Swift/PollySample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Polly-Sample/Swift/PollySample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import UIKit 17 | import AWSCore 18 | import AWSMobileClient 19 | 20 | @UIApplicationMain 21 | class AppDelegate: UIResponder, UIApplicationDelegate { 22 | 23 | var window: UIWindow? 24 | 25 | 26 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 27 | AWSMobileClient.sharedInstance().initialize { (userState, error) in 28 | guard error == nil else { 29 | print("AWSMobileClient initialization failed. Error: \(error!.localizedDescription)") 30 | return 31 | } 32 | print("AWSMobileClient initialized.") 33 | } 34 | 35 | return true 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /Polly-Sample/Swift/PollySample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /Polly-Sample/Swift/PollySample/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Polly-Sample/Swift/PollySample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /Polly-Sample/Swift/PollySample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Polly-Sample/Swift/README.md: -------------------------------------------------------------------------------- 1 | # The Amazon Polly Sample 2 | 3 | This sample demonstrates use of the Amazon Polly APIs to retrieve list of voices and generate speech using the given voice. It uses Cognito authentication in conjunction with Amazon Polly in order to authenticate to the Amazon Polly service. The user is presented with a list of voices which is retrieved when the application loads. 4 | 5 | ## Requirements 6 | 7 | * Xcode 9.2 and later 8 | * iOS 8 and later 9 | 10 | ## Using the Sample 11 | 12 | 1. The AWS Mobile SDK for iOS is available through [CocoaPods](http://cocoapods.org). If you have not installed CocoaPods, install CocoaPods: 13 | 14 | sudo gem install cocoapods 15 | pod setup 16 | 17 | 1. To install the AWS Mobile SDK for iOS, change the current directory to the one with your **Podfile** in it and run the following command: 18 | 19 | pod install 20 | 21 | 1. This sample requires Cognito to authorize to Amazon Polly. Use Amazon Cognito to create a new identity pool: 22 | 1. In the [Amazon Cognito Console](https://console.aws.amazon.com/cognito/), press the `Manage Federated Identities` button and on the resulting page press the `Create new identity pool` button. 23 | 1. Give your identity pool a name and ensure that `Enable access to unauthenticated identities` under the `Unauthenticated identities` section is checked. This allows the sample application to assume the unauthenticated role associated with this identity pool. Press the `Create Pool` button to create your identity pool. 24 | 25 | **Important**: see note below on unauthenticated user access. 26 | 27 | 1. As part of creating the identity pool, Cognito will setup two roles in [Identity and Access Management (IAM)](https://console.aws.amazon.com/iam/home#roles). These will be named something similar to: `Cognito_PoolNameAuth_Role` and `Cognito_PoolNameUnauth_Role`. You can view them by pressing the `View Details` button. Now press the `Allow` button to create the roles. 28 | 1. Save the `Identity pool ID` value that shows up in red in the "Getting started with Amazon Cognito" page, it should look similar to: `us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" and note the region that is being used. These will be used in the application code later. 29 | 1. Now we will attach a policy to the unauthenticated role which has permissions to access the required Amazon Polly API. This is done by attaching an IAM Policy to the unauthenticated role in the [IAM Console](https://console.aws.amazon.com/iam/home#roles). First, search for the unauth role that you created in step 3 above (named something similar to `Cognito_PoolNameUnauth_Role`) and select its hyperlink. In the resulting "Summary" page press the `Attach Policy` button in the "Permissions" tab. 30 | 1. Search for "polly" and check the box next to the policy named `AmazonPollyFullAccess` and then press the `Attach Policy` button. This policy allows the application to perform all operations on the Amazon Polly service. 31 | 32 | More information on AWS IAM roles and policies can be found [here](http://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage.html). More information on Amazon Polly policies can be found [here](http://docs.aws.amazon.com/polly/latest/dg/using-identity-based-policies.html). 33 | 34 | **Note**: To keep this example simple it makes use of unauthenticated users in the identity pool. This can be used for getting started and prototypes but unauthenticated users should typically only be given read-only permissions in production applications. More information on Cognito identity pools including the Cognito developer guide can be found [here](http://aws.amazon.com/cognito/). 35 | 36 | 1. Open `PollySample.xcworkspace`. 37 | 38 | 1. Open `awsconfiguration.json` and update the values for Cognito Identity Pool ID (from the value you saved above) and the region value for CognitoIdentity, Polly and PollySynthesizeSpeechUrlBuilder (for example us-east-1). 39 | 40 | ```json 41 | "CredentialsProvider": { 42 | "CognitoIdentity": { 43 | "Default": { 44 | "PoolId": "CHANGE_ME", 45 | "Region": "CHANGE_ME" 46 | } 47 | } 48 | }, 49 | "Polly": { 50 | "Default": { 51 | "Region": "CHANGE_ME" 52 | } 53 | }, 54 | "PollySynthesizeSpeechUrlBuilder": { 55 | "Default": { 56 | "Region": "CHANGE_ME" 57 | } 58 | } 59 | ``` 60 | 61 | 1. Build and run the sample app. 62 | 63 | The app will automatically query Amazon Polly for the list of voices and synthesize text with the selected voice. 64 | -------------------------------------------------------------------------------- /Polly-Sample/Swift/awsconfiguration.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "1.0", 3 | "IdentityManager": { 4 | "Default": {} 5 | }, 6 | "CredentialsProvider": { 7 | "CognitoIdentity": { 8 | "Default": { 9 | "PoolId": "CHANGE_ME", 10 | "Region": "CHANGE_ME" 11 | } 12 | } 13 | }, 14 | "Polly": { 15 | "Default": { 16 | "Region": "CHANGE_ME" 17 | } 18 | }, 19 | "PollySynthesizeSpeechUrlBuilder": { 20 | "Default": { 21 | "Region": "CHANGE_ME" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The AWS SDK for iOS Samples 2 | 3 | This repository has samples that demonstrate various aspects of the [AWS SDK for iOS](https://github.com/aws-amplify/aws-sdk-ios). 4 | 5 | ### Resources 6 | 7 | * [Developer Guide for AWS SDK for iOS](https://aws-amplify.github.io/docs/ios/start) 8 | 9 | Please refer to **README.md** in each sample directory for more specific instructions. 10 | 11 | ### List of Samples 12 | 13 | * S3TransferUtility-Sample ([Swift](https://github.com/awslabs/aws-sdk-ios-samples/tree/main/S3TransferUtility-Sample/Swift/), [Objective-C](https://github.com/awslabs/aws-sdk-ios-samples/tree/main/S3TransferUtility-Sample/Objective-C/)). This is a sample mobile application that demonstrates how to use the Amazon S3 PreSigned URL Builder to download / upload files in background. Involved AWS Services are: 14 | + Amazon S3 15 | + Amazon Cognito Identity 16 | 17 | * IoT-Sample ([Swift](https://github.com/awslabs/aws-sdk-ios-samples/tree/main/IoT-Sample/Swift/)). This is a sample mobile application that demonstrates how to publish and subscribe to data using AWS IoT. Involved AWS Services are: 18 | + Amazon AWS IoT 19 | + Amazon Cognito Identity 20 | 21 | * Lex-Sample ([Objective-C](https://github.com/awslabs/aws-sdk-ios-samples/tree/main/Lex-Sample/ObjC/), [Swift](https://github.com/awslabs/aws-sdk-ios-samples/tree/main/Lex-Sample/swift-3/)). This is a sample mobile application that demonstrates how to use text to text chat and voice to voice chat using Amazon Lex. Involved AWS Services are: 22 | + Amazon Lex 23 | + Amazon Cognito Identity 24 | 25 | * Polly-Sample ([Swift](https://github.com/awslabs/aws-sdk-ios-samples/tree/main/Polly-Sample/Swift/)). This is a sample mobile application that demonstrates how to get the list of voices and synthesize speech using Amazon Polly. Involved AWS Services are: 26 | + Amazon Polly 27 | + Amazon Cognito Identity 28 | 29 | ### Getting Help 30 | 31 | We use [AWS iOS SDK GitHub issues](https://github.com/aws-amplify/aws-sdk-ios/issues) for tracking questions, bugs, and feature requests. 32 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/Podfile: -------------------------------------------------------------------------------- 1 | ENV['SWIFT_VERSION'] = '5' 2 | platform :ios, '12.0' 3 | use_frameworks! 4 | 5 | target 'S3TransferUtilitySampleObjC' do 6 | pod 'AWSS3' 7 | end 8 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/README.md: -------------------------------------------------------------------------------- 1 | # The Amazon S3 Background Transfer Sample 2 | 3 | This sample demonstrates how to use `AWSS3TransferUtility` to download / upload files in background. 4 | 5 | ## Requirements 6 | 7 | * Xcode 9.2 and later 8 | * iOS 8 and later 9 | 10 | ## Using the Sample 11 | 12 | 1. The AWS Mobile SDK for iOS is available through [CocoaPods](http://cocoapods.org). If you have not installed CocoaPods, install CocoaPods: 13 | 14 | sudo gem install cocoapods 15 | pod setup 16 | 17 | 1. To install the AWS Mobile SDK for iOS, change the current directory to the one with your **Podfile** in it and run the following command: 18 | 19 | pod install 20 | 21 | 1. Create an Amazon S3 bucket. (For details on creating a bucket in the Amazon S3 console, see [Create a Bucket](http://docs.aws.amazon.com/AmazonS3/latest/gsg/CreatingABucket.html).) 22 | 23 | 1. Upload a image in the bucket. Open `Constants.m` or `Constants.swift` and update the following lines with the appropriate constants: 24 | 25 | Swift 26 | 27 | let S3BucketName: String = "YourS3BucketName" 28 | 29 | Objective-C 30 | 31 | NSString *const S3BucketName = @"YourS3BucketName"; 32 | NSString *const S3DownloadKeyName = @"YourDownloadKeyName"; 33 | 34 | 1. This sample requires Cognito to authorize to Amazon S3 in order to access the bucket. Use Amazon Cognito to create a new identity pool: 35 | 1. In the [Amazon Cognito Console](https://console.aws.amazon.com/cognito/), press the `Manage Federated Identities` button and on the resulting page press the `Create new identity pool` button. 36 | 1. Give your identity pool a name and ensure that `Enable access to unauthenticated identities` under the `Unauthenticated identities` section is checked. This allows the sample application to assume the unauthenticated role associated with this identity pool. Press the `Create Pool` button to create your identity pool. 37 | 38 | **Important**: see note below on unauthenticated user access. 39 | 40 | 1. As part of creating the identity pool, Cognito will setup two roles in [Identity and Access Management (IAM)](https://console.aws.amazon.com/iam/home#roles). These will be named something similar to: `Cognito_PoolNameAuth_Role` and `Cognito_PoolNameUnauth_Role`. You can view them by pressing the `View Details` button. Now press the `Allow` button to create the roles. 41 | 1. Save the `Identity pool ID` value that shows up in red in the "Getting started with Amazon Cognito" page, it should look similar to: `us-east-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" and note the region that is being used. These will be used in the application code later. 42 | 1. Now we will attach a policy to the unauthenticated role which has permissions to access the required Amazon S3 API. This is done by attaching an IAM Policy to the unauthenticated role in the [IAM Console](https://console.aws.amazon.com/iam/home#roles). First, search for the unauth role that you created in step 3 above (named something similar to `Cognito_PoolNameUnauth_Role`) and select its hyperlink. In the resulting "Summary" page press the `Attach Policy` button in the "Permissions" tab. 43 | 1. Search for "S3" and check the box next to the policy named `AmazonS3FullAccess` and then press the `Attach Policy` button. This policy allows the application to perform all operations on the Amazon Polly service. 44 | 45 | More information on AWS IAM roles and policies can be found [here](http://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage.html). More information on Amazon S3 policies can be found [here](http://docs.aws.amazon.com/AmazonS3/latest/dev/using-iam-policies.html). 46 | 47 | **Note**: To keep this example simple it makes use of unauthenticated users in the identity pool. This can be used for getting started and prototypes but unauthenticated users should typically only be given read-only permissions in production applications. More information on Cognito identity pools including the Cognito developer guide can be found [here](http://aws.amazon.com/cognito/). 48 | 49 | 1. Open `S3BackgroundTransferSampleObjC.xcworkspace` or `S3BackgroundTransferSampleSwift.xcworkspace`. 50 | 51 | 1. Open `Info.plist` and update the following lines with the your values: 52 | 53 | **AWS --> CredentialsProvider --> CognitoIdentity --> Default --> PoolId** (put your Cognito IdentityPoolID here) 54 | 55 | **AWS --> CredentialsProvider --> CognitoIdentity --> Default --> Region** (for example: USEast1) 56 | 57 | **AWS --> S3TransferUtility --> Default --> Region** (for example: USEast1) 58 | 59 | 1. Build and run the sample app. 60 | 61 | ## NOTES 62 | 63 | 1. The TransferUtility uses a `NSURL Background Session` to upload and download files. To make sure that the transfers continue to run when the app is moved to the background, the `handleEventsForBackgroundURLSession` method has to be implemented in the `AppDelegate`. The sample implements this as follows 64 | 65 | Swift 66 | 67 | func application(_ application: UIApplication, 68 | handleEventsForBackgroundURLSession identifier: String, 69 | completionHandler: @escaping () -> Void) { 70 | 71 | //provide the completionHandler to the TransferUtility to support background transfers. 72 | AWSS3TransferUtility.interceptApplication(application, 73 | handleEventsForBackgroundURLSession: identifier, 74 | completionHandler: completionHandler) 75 | } 76 | 77 | Objective-C 78 | 79 | (void) application:(UIApplication *)application 80 | handleEventsForBackgroundURLSession:(NSString *)identifier 81 | completionHandler:(void (^)(void))completionHandler { 82 | 83 | //provide the completionHandler to the TransferUtility to support background transfers. 84 | [AWSS3TransferUtility interceptApplication:application 85 | handleEventsForBackgroundURLSession:identifier 86 | completionHandler:completionHandler]; 87 | } 88 | 89 | 1. If, you get a bunch of warnings that look similar to the one below when you run the sample and try doing an upload: 90 | 91 | Function boringssl_session_errorlog: line 2868 [boringssl_session_write] SSL_ERROR_SYSCALL(5): operation failed externally to the library 92 | 2017-12-22 10:46:37.105342-0800 S3TransferManagerSampleSwift[59012:3381604] [BoringSSL] 93 | 94 | You can disable OS logging in Xcode to make them go away. With your project window open, go to Project -> Scheme -> Edit Scheme... and add "OS_ACTIVITY_MODE" to the Environment Variables section and set its value to "disable". When you rerun the app those warnings should now not appear. 95 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | #import 17 | 18 | @interface AppDelegate : UIResponder 19 | 20 | @property (strong, nonatomic) UIWindow *window; 21 | @property (copy) void (^backgroundDownloadSessionCompletionHandler)(void); 22 | @property (copy) void (^backgroundUploadSessionCompletionHandler)(void); 23 | 24 | @end 25 | 26 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | #import "AppDelegate.h" 17 | #import 18 | #import "Constants.h" 19 | 20 | @implementation AppDelegate 21 | 22 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 23 | return YES; 24 | } 25 | 26 | - (void) application:(UIApplication *)application 27 | handleEventsForBackgroundURLSession:(NSString *)identifier 28 | completionHandler:(void (^)(void))completionHandler { 29 | 30 | //provide the completionHandler to the TransferUtility to support background transfers. 31 | [AWSS3TransferUtility interceptApplication:application 32 | handleEventsForBackgroundURLSession:identifier 33 | completionHandler:completionHandler]; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/Constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | #import 17 | @import AWSCore; 18 | 19 | FOUNDATION_EXPORT NSString *const S3BucketName; 20 | FOUNDATION_EXPORT NSString *const S3DownloadKeyName; 21 | 22 | FOUNDATION_EXPORT NSString *const S3UploadKeyName; 23 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/Constants.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | #import "Constants.h" 17 | 18 | #warning To run this sample correctly, you must set the following constants. 19 | NSString *const S3BucketName = @"YourS3BucketNameHere"; // Update this to your bucket name 20 | NSString *const S3DownloadKeyName = @"S3DownloadKeyName"; // Name of file to be downloaded 21 | NSString *const S3UploadKeyName = @"uploadfileobj.txt"; // Name of file to be uploaded 22 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/FirstViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | #import 17 | 18 | @interface FirstViewController : UIViewController 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/FirstViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | #import "FirstViewController.h" 17 | #import 18 | #import "Constants.h" 19 | 20 | @interface FirstViewController () 21 | 22 | @property (weak, nonatomic) IBOutlet UIProgressView *progressView; 23 | @property (weak, nonatomic) IBOutlet UILabel *statusLabel; 24 | 25 | @end 26 | 27 | @implementation FirstViewController 28 | 29 | - (void)viewDidLoad { 30 | [super viewDidLoad]; 31 | dispatch_async(dispatch_get_main_queue(), ^{ 32 | self.statusLabel.text = @""; 33 | self.progressView.progress = 0; 34 | }); 35 | 36 | } 37 | 38 | - (IBAction)start:(id)sender { 39 | dispatch_async(dispatch_get_main_queue(), ^{ 40 | self.statusLabel.text = @"Creating a test file..."; 41 | self.progressView.progress = 0; 42 | }); 43 | 44 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 45 | // Create a test file in the temporary directory 46 | NSMutableString *dataString = [NSMutableString new]; 47 | for (int32_t i = 1; i < 10000000; i++) { 48 | [dataString appendFormat:@"%d\n", i]; 49 | } 50 | 51 | [self uploadData:[dataString dataUsingEncoding:NSUTF8StringEncoding]]; 52 | }); 53 | } 54 | 55 | - (void)uploadData:(NSData *)testData { 56 | //Initalize the screen elements 57 | dispatch_async(dispatch_get_main_queue(), ^{ 58 | self.progressView.progress = 0; 59 | self.statusLabel.text = @""; 60 | }); 61 | 62 | 63 | __weak FirstViewController *weakSelf = self; 64 | 65 | //Create the completion handler for the transfer 66 | AWSS3TransferUtilityUploadCompletionHandlerBlock completionHandler = ^(AWSS3TransferUtilityUploadTask *task, NSError *error) { 67 | dispatch_async(dispatch_get_main_queue(), ^{ 68 | if (error) { 69 | weakSelf.statusLabel.text = @"Failed to Upload"; 70 | } else { 71 | weakSelf.statusLabel.text = @"Successfully Uploaded"; 72 | weakSelf.progressView.progress = 1.0; 73 | } 74 | }); 75 | }; 76 | 77 | //Create the TransferUtility expression and add the progress block to it. 78 | //This would be needed to report on progress tracking 79 | AWSS3TransferUtilityUploadExpression *expression = [AWSS3TransferUtilityUploadExpression new]; 80 | expression.progressBlock = ^(AWSS3TransferUtilityTask *task, NSProgress *progress) { 81 | dispatch_async(dispatch_get_main_queue(), ^{ 82 | if ( weakSelf.progressView.progress < progress.fractionCompleted) { 83 | weakSelf.progressView.progress = progress.fractionCompleted; 84 | } 85 | }); 86 | }; 87 | 88 | AWSS3TransferUtility *transferUtility = [AWSS3TransferUtility defaultS3TransferUtility]; 89 | [[transferUtility uploadData:testData 90 | bucket:S3BucketName 91 | key:S3UploadKeyName 92 | contentType:@"text/plain" 93 | expression:expression 94 | completionHandler:completionHandler] continueWithBlock:^id(AWSTask *task) { 95 | if (task.error) { 96 | NSLog(@"Error: %@", task.error); 97 | } 98 | if (task.result) { 99 | dispatch_async(dispatch_get_main_queue(), ^{ 100 | self.statusLabel.text = @"Uploading..."; 101 | }); 102 | } 103 | return nil; 104 | }]; 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/Images.xcassets/first.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "first.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/Images.xcassets/first.imageset/first.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-sdk-ios-samples/0343d828361b5b9f21e57d3d23cb6d18f45689a7/S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/Images.xcassets/first.imageset/first.pdf -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/Images.xcassets/second.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "second.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/Images.xcassets/second.imageset/second.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-sdk-ios-samples/0343d828361b5b9f21e57d3d23cb6d18f45689a7/S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/Images.xcassets/second.imageset/second.pdf -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIcons 10 | 11 | CFBundleIcons~ipad 12 | 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | $(PRODUCT_NAME) 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1 27 | LSRequiresIPhoneOS 28 | 29 | NSAppTransportSecurity 30 | 31 | NSExceptionDomains 32 | 33 | amazonaws.com 34 | 35 | NSIncludesSubdomains 36 | 37 | NSThirdPartyExceptionMinimumTLSVersion 38 | TLSv1.0 39 | NSThirdPartyExceptionRequiresForwardSecrecy 40 | 41 | 42 | amazonaws.com.cn 43 | 44 | NSIncludesSubdomains 45 | 46 | NSThirdPartyExceptionMinimumTLSVersion 47 | TLSv1.0 48 | NSThirdPartyExceptionRequiresForwardSecrecy 49 | 50 | 51 | 52 | 53 | UILaunchStoryboardName 54 | Launch Screen 55 | UIMainStoryboardFile 56 | Main 57 | UIRequiredDeviceCapabilities 58 | 59 | armv7 60 | 61 | UIStatusBarTintParameters 62 | 63 | UINavigationBar 64 | 65 | Style 66 | UIBarStyleDefault 67 | Translucent 68 | 69 | 70 | 71 | UISupportedInterfaceOrientations 72 | 73 | UIInterfaceOrientationPortrait 74 | UIInterfaceOrientationLandscapeLeft 75 | UIInterfaceOrientationLandscapeRight 76 | 77 | AWS 78 | 79 | CredentialsProvider 80 | 81 | CognitoIdentity 82 | 83 | Default 84 | 85 | PoolId 86 | YourCognitoIdentityPoolId 87 | Region 88 | YourCognitoIdentityRegion 89 | 90 | 91 | 92 | S3TransferUtility 93 | 94 | Default 95 | 96 | Region 97 | YourS3Region 98 | 99 | 100 | 101 | NSPhotoLibraryUsageDescription 102 | Give permission to let the app get access to the images from the Photo Library 103 | 104 | 105 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/Launch Screen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/SecondViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | #import 17 | 18 | @interface SecondViewController : UIViewController 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/SecondViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | #import "SecondViewController.h" 17 | #import "AppDelegate.h" 18 | #import 19 | #import "Constants.h" 20 | 21 | @interface SecondViewController () 22 | 23 | @property (weak, nonatomic) IBOutlet UIImageView *imageView; 24 | @property (weak, nonatomic) IBOutlet UIProgressView *progressView; 25 | @property (weak, nonatomic) IBOutlet UILabel *statusLabel; 26 | 27 | @end 28 | 29 | @implementation SecondViewController 30 | 31 | - (void)viewDidLoad { 32 | [super viewDidLoad]; 33 | dispatch_async(dispatch_get_main_queue(), ^{ 34 | self.progressView.progress = 0; 35 | self.statusLabel.text = @""; 36 | }); 37 | 38 | 39 | } 40 | 41 | - (IBAction)start:(id)sender { 42 | 43 | //Initalize the screen elements 44 | dispatch_async(dispatch_get_main_queue(), ^{ 45 | self.progressView.progress = 0; 46 | self.statusLabel.text = @""; 47 | self.imageView.image = nil; 48 | }); 49 | 50 | __weak SecondViewController *weakSelf = self; 51 | 52 | //Create the completion handler for the transfer 53 | AWSS3TransferUtilityDownloadCompletionHandlerBlock completionHandler = ^(AWSS3TransferUtilityDownloadTask *task, NSURL *location, NSData *data, NSError *error) { 54 | dispatch_async(dispatch_get_main_queue(), ^{ 55 | if (error) { 56 | weakSelf.statusLabel.text = @"Failed to Download"; 57 | } 58 | if (data) { 59 | weakSelf.statusLabel.text = @"Successfully Downloaded"; 60 | weakSelf.imageView.image = [UIImage imageWithData:data]; 61 | weakSelf.progressView.progress = 1.0; 62 | } 63 | }); 64 | }; 65 | 66 | 67 | //Create the TransferUtility expression and add the progress block to it. 68 | //This would be needed to report on progress tracking 69 | AWSS3TransferUtilityDownloadExpression *expression = [AWSS3TransferUtilityDownloadExpression new]; 70 | expression.progressBlock = ^(AWSS3TransferUtilityTask *task, NSProgress *progress) { 71 | dispatch_async(dispatch_get_main_queue(), ^{ 72 | weakSelf.progressView.progress = progress.fractionCompleted; 73 | }); 74 | }; 75 | 76 | 77 | AWSS3TransferUtility *transferUtility = [AWSS3TransferUtility defaultS3TransferUtility]; 78 | [[transferUtility downloadDataFromBucket:S3BucketName 79 | key:S3DownloadKeyName 80 | expression:expression 81 | completionHandler:completionHandler] continueWithBlock:^id(AWSTask *task) { 82 | if (task.error) { 83 | NSLog(@"Error: %@", task.error); 84 | } 85 | if (task.result) { 86 | dispatch_async(dispatch_get_main_queue(), ^{ 87 | self.statusLabel.text = @"Downloading..."; 88 | }); 89 | } 90 | 91 | return nil; 92 | }]; 93 | } 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/TemplateIcon2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-sdk-ios-samples/0343d828361b5b9f21e57d3d23cb6d18f45689a7/S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/TemplateIcon2x.png -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3BackgroundTransferSampleObjC/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | #import 17 | #import "AppDelegate.h" 18 | 19 | int main(int argc, char * argv[]) { 20 | @autoreleasepool { 21 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3TransferUtilitySampleObjC.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Objective-C/S3TransferUtilitySampleObjC.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/.gitignore: -------------------------------------------------------------------------------- 1 | amplify 2 | amplify/\#current-cloud-backend 3 | amplify/.config/local-* 4 | amplify/backend/amplify-meta.json 5 | amplify/backend/awscloudformation 6 | build/ 7 | dist/ 8 | node_modules/ 9 | aws-exports.js 10 | awsconfiguration.json -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '12.0' 2 | use_frameworks! 3 | 4 | target 'S3TransferUtilitySampleSwift' do 5 | pod 'AWSMobileClient' 6 | pod 'AWSS3' 7 | end 8 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/README.md: -------------------------------------------------------------------------------- 1 | # The Amazon S3 Background Transfer Sample 2 | 3 | This sample demonstrates how to use `AWSS3TransferUtility` to download / upload files in background. 4 | 5 | ## Requirements 6 | 7 | * Xcode 9.2 and later 8 | * iOS 8 and later 9 | 10 | ## Using the Sample 11 | 12 | 1. The AWS Mobile SDK for iOS is available through [CocoaPods](http://cocoapods.org). If you have not installed CocoaPods, install CocoaPods: 13 | 14 | sudo gem install cocoapods 15 | pod setup 16 | 17 | 1. To install the AWS Mobile SDK for iOS, change the current directory to the one with your **Podfile** in it and run the following command: 18 | 19 | pod install 20 | 21 | 1. Create new AWS backend resources and pull the AWS services configuration into the app by running the following command: 22 | 23 | amplify init # accept default options to get started 24 | amplify push # create the configuration file 25 | 26 | 1. Add the required S3 resource to your app's cloud-enabled backend using the following CLI command: 27 | 28 | amplify add storage 29 | 30 | 1. Choose `Content` as your storage service. 31 | 32 | ❯ Content (Images, audio, video, etc.) 33 | 34 | 1. The CLI walks you through the options to enable Auth (if not enabled previously), to name your S3 bucket, and to decide who should have access (select Auth and guest users and read/write for both auth and guest users). 35 | 36 | 1. Confirm that you have storage and auth set up with the following command: 37 | 38 | amplify status 39 | 40 | 1. Create the specified backend by running the following command: 41 | 42 | amplify push 43 | 44 | 1. Open `S3TransferUtilitySampleSwift.xcworkspace`. 45 | 46 | 1. Add the cli-generated `awsconfiguration.json` by right-clicking the project in Xcode project navigator, selecting `Add Files to "S3TransferUtilitySampleSwift"..."` and following instructions in the dialog window. 47 | 48 | 1. Build and run the sample app. 49 | 50 | ## NOTES 51 | 52 | 1. The TransferUtility uses a `NSURL Background Session` to upload and download files. To make sure that the transfers continue to run when the app is moved to the background, the `handleEventsForBackgroundURLSession` method has to be implemented in the `AppDelegate`. The sample implements this as follows 53 | 54 | Swift 55 | 56 | func application(_ application: UIApplication, 57 | handleEventsForBackgroundURLSession identifier: String, 58 | completionHandler: @escaping () -> Void) { 59 | 60 | //provide the completionHandler to the TransferUtility to support background transfers. 61 | AWSS3TransferUtility.interceptApplication(application, 62 | handleEventsForBackgroundURLSession: identifier, 63 | completionHandler: completionHandler) 64 | } 65 | 66 | Objective-C 67 | 68 | (void) application:(UIApplication *)application 69 | handleEventsForBackgroundURLSession:(NSString *)identifier 70 | completionHandler:(void (^)(void))completionHandler { 71 | 72 | //provide the completionHandler to the TransferUtility to support background transfers. 73 | [AWSS3TransferUtility interceptApplication:application 74 | handleEventsForBackgroundURLSession:identifier 75 | completionHandler:completionHandler]; 76 | } 77 | 78 | 1. If, you get a bunch of warnings that look similar to the one below when you run the sample and try doing an upload: 79 | 80 | Function boringssl_session_errorlog: line 2868 [boringssl_session_write] SSL_ERROR_SYSCALL(5): operation failed externally to the library 81 | 2017-12-22 10:46:37.105342-0800 S3TransferManagerSampleSwift[59012:3381604] [BoringSSL] 82 | 83 | You can disable OS logging in Xcode to make them go away. With your project window open, go to Project -> Scheme -> Edit Scheme... and add "OS_ACTIVITY_MODE" to the Environment Variables section and set its value to "disable". When you rerun the app those warnings should now not appear. 84 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/S3BackgroundTransferSampleSwift/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import UIKit 17 | import AWSS3 18 | import AWSMobileClient 19 | 20 | @UIApplicationMain 21 | class AppDelegate: UIResponder, UIApplicationDelegate { 22 | 23 | var window: UIWindow? 24 | 25 | func application(_ application: UIApplication, 26 | handleEventsForBackgroundURLSession identifier: String, 27 | completionHandler: @escaping () -> Void) { 28 | 29 | AWSMobileClient.sharedInstance().initialize { (userState, error) in 30 | guard error == nil else { 31 | print("Error initializing AWSMobileClient. Error: \(error!.localizedDescription)") 32 | return 33 | } 34 | print("AWSMobileClient initialized.") 35 | } 36 | 37 | //provide the completionHandler to the TransferUtility to support background transfers. 38 | AWSS3TransferUtility.interceptApplication(application, 39 | handleEventsForBackgroundURLSession: identifier, 40 | completionHandler: completionHandler) 41 | } 42 | 43 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 44 | return true 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/S3BackgroundTransferSampleSwift/Constants.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import Foundation 17 | import AWSCore 18 | 19 | // Warning: To run this sample correctly, you must set the following constants. 20 | 21 | let S3DownloadKeyName: String = "public/test-image.png" // Name of file to be downloaded 22 | let S3UploadKeyName: String = "public/test-image.png" // Name of file to be uploaded 23 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/S3BackgroundTransferSampleSwift/DownloadViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import UIKit 17 | import AWSS3 18 | 19 | class DownloadViewController: UIViewController{ 20 | 21 | @IBOutlet var imageView: UIImageView! 22 | @IBOutlet var progressView: UIProgressView! 23 | @IBOutlet var statusLabel: UILabel! 24 | 25 | @objc var completionHandler: AWSS3TransferUtilityDownloadCompletionHandlerBlock? 26 | 27 | @objc lazy var transferUtility = { 28 | AWSS3TransferUtility.default() 29 | }() 30 | 31 | override func viewDidLoad() { 32 | super.viewDidLoad() 33 | // Do any additional setup after loading the view, typically from a nib. 34 | 35 | self.progressView.progress = 0.0; 36 | self.statusLabel.text = "Ready" 37 | } 38 | 39 | override func didReceiveMemoryWarning() { 40 | super.didReceiveMemoryWarning() 41 | // Dispose of any resources that can be recreated. 42 | } 43 | 44 | @IBAction func start(_ sender: UIButton) { 45 | 46 | DispatchQueue.main.async(execute: { 47 | self.statusLabel.text = "" 48 | self.progressView.progress = 0 49 | }) 50 | 51 | self.imageView.image = nil; 52 | 53 | let expression = AWSS3TransferUtilityDownloadExpression() 54 | expression.progressBlock = {(task, progress) in 55 | DispatchQueue.main.async(execute: { 56 | if (self.progressView.progress < Float(progress.fractionCompleted)) { 57 | self.progressView.progress = Float(progress.fractionCompleted) 58 | } 59 | }) 60 | } 61 | 62 | self.completionHandler = { (task, location, data, error) -> Void in 63 | DispatchQueue.main.async(execute: { 64 | if let error = error { 65 | NSLog("Failed with error: \(error)") 66 | self.statusLabel.text = "Failed" 67 | } 68 | else if(self.progressView.progress != 1.0) { 69 | self.statusLabel.text = "Failed" 70 | } 71 | else{ 72 | self.statusLabel.text = "Success" 73 | self.imageView.image = UIImage(data: data!) 74 | } 75 | }) 76 | } 77 | 78 | transferUtility.downloadData( 79 | forKey: S3DownloadKeyName, 80 | expression: expression, 81 | completionHandler: completionHandler).continueWith { (task) -> AnyObject? in 82 | if let error = task.error { 83 | NSLog("Error: %@",error.localizedDescription); 84 | DispatchQueue.main.async(execute: { 85 | self.statusLabel.text = "Failed" 86 | }) 87 | } 88 | 89 | if let _ = task.result { 90 | DispatchQueue.main.async(execute: { 91 | self.statusLabel.text = "Downloading..." 92 | }) 93 | NSLog("Download Starting!") 94 | // Do something with uploadTask. 95 | } 96 | return nil; 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/S3BackgroundTransferSampleSwift/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/S3BackgroundTransferSampleSwift/Images.xcassets/first.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "first.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/S3BackgroundTransferSampleSwift/Images.xcassets/first.imageset/first.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-sdk-ios-samples/0343d828361b5b9f21e57d3d23cb6d18f45689a7/S3TransferUtility-Sample/Swift/S3BackgroundTransferSampleSwift/Images.xcassets/first.imageset/first.pdf -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/S3BackgroundTransferSampleSwift/Images.xcassets/second.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "second.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/S3BackgroundTransferSampleSwift/Images.xcassets/second.imageset/second.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-sdk-ios-samples/0343d828361b5b9f21e57d3d23cb6d18f45689a7/S3TransferUtility-Sample/Swift/S3BackgroundTransferSampleSwift/Images.xcassets/second.imageset/second.pdf -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/S3BackgroundTransferSampleSwift/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UILaunchStoryboardName 6 | Launch Screen 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSExceptionDomains 30 | 31 | amazonaws.com 32 | 33 | NSThirdPartyExceptionMinimumTLSVersion 34 | TLSv1.0 35 | NSThirdPartyExceptionRequiresForwardSecrecy 36 | 37 | NSIncludesSubdomains 38 | 39 | 40 | amazonaws.com.cn 41 | 42 | NSThirdPartyExceptionMinimumTLSVersion 43 | TLSv1.0 44 | NSThirdPartyExceptionRequiresForwardSecrecy 45 | 46 | NSIncludesSubdomains 47 | 48 | 49 | 50 | 51 | UIMainStoryboardFile 52 | Main 53 | UIRequiredDeviceCapabilities 54 | 55 | armv7 56 | 57 | UIStatusBarTintParameters 58 | 59 | UINavigationBar 60 | 61 | Style 62 | UIBarStyleDefault 63 | Translucent 64 | 65 | 66 | 67 | UISupportedInterfaceOrientations 68 | 69 | UIInterfaceOrientationPortrait 70 | UIInterfaceOrientationLandscapeLeft 71 | UIInterfaceOrientationLandscapeRight 72 | 73 | NSPhotoLibraryUsageDescription 74 | Give permission to let the app get access to the images from the Photo Library 75 | 76 | 77 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/S3BackgroundTransferSampleSwift/Launch Screen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/S3BackgroundTransferSampleSwift/UploadViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import UIKit 17 | import AWSS3 18 | 19 | class UploadViewController: UIViewController, UINavigationControllerDelegate { 20 | 21 | @IBOutlet var progressView: UIProgressView! 22 | @IBOutlet var statusLabel: UILabel! 23 | 24 | @objc var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock? 25 | @objc var progressBlock: AWSS3TransferUtilityProgressBlock? 26 | 27 | @objc let imagePicker = UIImagePickerController() 28 | 29 | @objc lazy var transferUtility = { 30 | AWSS3TransferUtility.default() 31 | }() 32 | 33 | override func viewDidLoad() { 34 | super.viewDidLoad() 35 | // Do any additional setup after loading the view, typically from a nib. 36 | 37 | self.progressView.progress = 0.0; 38 | self.statusLabel.text = "Ready" 39 | self.imagePicker.delegate = self 40 | 41 | self.progressBlock = {(task, progress) in 42 | DispatchQueue.main.async(execute: { 43 | if (self.progressView.progress < Float(progress.fractionCompleted)) { 44 | self.progressView.progress = Float(progress.fractionCompleted) 45 | } 46 | }) 47 | } 48 | 49 | self.completionHandler = { (task, error) -> Void in 50 | DispatchQueue.main.async(execute: { 51 | if let error = error { 52 | print("Failed with error: \(error)") 53 | self.statusLabel.text = "Failed" 54 | } 55 | else if(self.progressView.progress != 1.0) { 56 | self.statusLabel.text = "Failed" 57 | NSLog("Error: Failed - Likely due to invalid region / filename") 58 | } 59 | else{ 60 | self.statusLabel.text = "Success" 61 | } 62 | }) 63 | } 64 | } 65 | 66 | @IBAction func selectAndUpload(_ sender: UIButton) { 67 | imagePicker.allowsEditing = false 68 | imagePicker.sourceType = .photoLibrary 69 | 70 | present(imagePicker, animated: true, completion: nil) 71 | } 72 | 73 | @objc func uploadImage(with data: Data) { 74 | let expression = AWSS3TransferUtilityUploadExpression() 75 | expression.progressBlock = progressBlock 76 | 77 | DispatchQueue.main.async(execute: { 78 | self.statusLabel.text = "" 79 | self.progressView.progress = 0 80 | }) 81 | 82 | transferUtility.uploadData( 83 | data, 84 | key: S3UploadKeyName, 85 | contentType: "image/png", 86 | expression: expression, 87 | completionHandler: completionHandler).continueWith { (task) -> AnyObject? in 88 | if let error = task.error { 89 | print("Error: \(error.localizedDescription)") 90 | 91 | DispatchQueue.main.async { 92 | self.statusLabel.text = "Failed" 93 | } 94 | } 95 | 96 | if let _ = task.result { 97 | 98 | DispatchQueue.main.async { 99 | self.statusLabel.text = "Uploading..." 100 | print("Upload Starting!") 101 | } 102 | 103 | // Do something with uploadTask. 104 | } 105 | 106 | return nil; 107 | } 108 | } 109 | } 110 | 111 | extension UploadViewController: UIImagePickerControllerDelegate { 112 | 113 | public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { 114 | // Local variable inserted by Swift 4.2 migrator. 115 | let info = convertFromUIImagePickerControllerInfoKeyDictionary(info) 116 | 117 | if "public.image" == info[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey.mediaType)] as? String { 118 | let image: UIImage = info[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey.originalImage)] as! UIImage 119 | self.uploadImage(with: image.pngData()!) 120 | } 121 | 122 | 123 | dismiss(animated: true, completion: nil) 124 | } 125 | } 126 | 127 | // Helper function inserted by Swift 4.2 migrator. 128 | fileprivate func convertFromUIImagePickerControllerInfoKeyDictionary(_ input: [UIImagePickerController.InfoKey: Any]) -> [String: Any] { 129 | return Dictionary(uniqueKeysWithValues: input.map {key, value in (key.rawValue, value)}) 130 | } 131 | 132 | // Helper function inserted by Swift 4.2 migrator. 133 | fileprivate func convertFromUIImagePickerControllerInfoKey(_ input: UIImagePickerController.InfoKey) -> String { 134 | return input.rawValue 135 | } 136 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/S3TransferUtilitySampleSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/S3TransferUtilitySampleSwift.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/S3TransferUtilitySampleSwiftUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/S3TransferUtilitySampleSwiftUITests/S3TransferUtilitySampleSwiftUITests.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"). 5 | * You may not use this file except in compliance with the License. 6 | * A copy of the License is located at 7 | * 8 | * http://aws.amazon.com/apache2.0 9 | * 10 | * or in the "license" file accompanying this file. This file is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | * express or implied. See the License for the specific language governing 13 | * permissions and limitations under the License. 14 | */ 15 | 16 | import XCTest 17 | 18 | class S3TransferUtilitySampleSwiftUITests: XCTestCase { 19 | 20 | override func setUp() { 21 | super.setUp() 22 | 23 | // Put setup code here. This method is called before the invocation of each test method in the class. 24 | 25 | // In UI tests it is usually best to stop immediately when a failure occurs. 26 | continueAfterFailure = false 27 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 28 | XCUIApplication().launch() 29 | 30 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 31 | } 32 | 33 | override func tearDown() { 34 | // Put teardown code here. This method is called after the invocation of each test method in the class. 35 | super.tearDown() 36 | } 37 | 38 | func testButtons() { 39 | // Use recording to get started writing UI tests. 40 | // Use XCTAssert and related functions to verify your tests produce the correct results. 41 | 42 | let app = XCUIApplication() 43 | let tabBarsQuery = app.tabBars 44 | let uploadButton = tabBarsQuery.buttons["Upload"] 45 | uploadButton.tap() 46 | app.buttons["Select Image and Upload"].tap() 47 | let cancelButton = app.navigationBars["Photos"].buttons["Cancel"] 48 | let exists = NSPredicate(format: "exists == 1") 49 | 50 | expectation(for: exists, evaluatedWith: cancelButton, handler: nil) 51 | waitForExpectations(timeout: 5, handler: nil) 52 | cancelButton.tap() 53 | let readyStaticText = app.staticTexts["Ready"] 54 | readyStaticText.tap() 55 | tabBarsQuery.buttons["Download"].tap() 56 | readyStaticText.tap() 57 | uploadButton.tap() 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /S3TransferUtility-Sample/Swift/awsconfiguration.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awslabs/aws-sdk-ios-samples/0343d828361b5b9f21e57d3d23cb6d18f45689a7/S3TransferUtility-Sample/Swift/awsconfiguration.json --------------------------------------------------------------------------------