How to continue Alamofire Download task after suspend it, terminate the app, and reopen the app - alamofire

I need to write a downloader for my app, and It can pause, continue and cancel the downloads. Also it must support to pause download, kill the app, and reopen the app and continue from where it paused.
How can i keep the downloaded data and how can I continue it?
import UIKit
import Foundation
import Alamofire
class DownloaderViewController: UIViewController {
#IBOutlet weak var label: UILabel!
let progressIndicatorView = UIProgressView()
var request: Alamofire.Request?
override func viewDidLoad() {
super.viewDidLoad()
}
}
#IBAction func cancelBtn(sender: AnyObject) {
self.request?.cancel()
self.label.text = "% 0.0"
}
#IBAction func pauseBtn(sender: AnyObject) {
self.request?.suspend()
}
#IBAction func continueBtn(sender: AnyObject) {
self.request?.resume()
}
#IBAction func startBtn(sender: AnyObject) {
var localPath: NSURL?
self.request = Alamofire.download(.GET, "https://dl.dropboxusercontent.com/u/11563257/3.%20Interactive_iPad_test_for_PDF_EXPERT.pdf", destination: { (temporaryURL, response) in
let directoryURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
let pathComponent = response.suggestedFilename
localPath = directoryURL.URLByAppendingPathComponent(pathComponent!)
return localPath!
}).progress() {
(_, totalBytesRead, totalBytesExpectedToRead) in
dispatch_async(dispatch_get_main_queue()) {
self.progressIndicatorView.setProgress(Float(totalBytesRead) / Float(totalBytesExpectedToRead), animated: true)
self.updateProgress(self.progressIndicatorView)
if totalBytesRead == totalBytesExpectedToRead {
self.progressIndicatorView.removeFromSuperview()
}
}
}
func updateProgress(prg:UIProgressView) {
let stepSize:Float = 0.1
prg.setProgress(prg.progress + stepSize, animated: true)
self.label.text = "% " + String(format: "%.2f", prg.progress*100)
}
}
This works while the app is running. But I need to save the data when the app is terminated and continue it when the app started. I have no i idea how to keep the downloaded data and how to continue it. Any help will be appriciated.

I find this in Alamofire documentation :
Alamofire.download(.GET, "https://httpbin.org/stream/100", destination: destination)
.response { _, _, data, _ in
if let
data = data,
resumeDataString = NSString(data: data, encoding: NSUTF8StringEncoding)
{
print("Resume Data: \(resumeDataString)")
} else {
print("Resume Data was empty")
}
}
But I get "Resume Data was empty" everytime. I give the same destination. But It can't catct the Resume Data. And I couldn't find an example with Alamofire.

Related

CallKit + WebRTC: CallKit call is getting disconnected when pressing lock / Power button in iOS

It is a conferencing app and I am initiating outgoing call to make my VoIP call as high priority and doesn't interrupt the incoming call when i am in VoIP call.
I am using WebRTC + CallKit in my App.
I started a call and when I press Lock / Power button then the CallKit call is getting disconnected and the My Voip call audio route changes to Receiver and remains.
Why locking the iPhone terminating the call.
Here is my Code.
var callUUID: UUID?
extension AppDelegate {
func initiateCallKitCall() {
let config = CXProviderConfiguration(localizedName: "AppName")
config.includesCallsInRecents = false;
config.supportsVideo = true;
config.maximumCallsPerCallGroup = 1
provider = CXProvider(configuration: config)
guard let provider = provider else { return }
provider.setDelegate(self, queue: nil)
callController = CXCallController()
guard let callController = callController else { return }
callUUID = UUID()
let transaction = CXTransaction(action: CXStartCallAction(call: callUUID!, handle: CXHandle(type: .generic, value: "AppName")))
callController.request(transaction, completion: { error in
print("Error is : \(String(describing: error))")
})
}
func endCallKitCall(userEnded: Bool) {
self.userEnded = userEnded
guard provider != nil else { return }
guard let callController = callController else { return }
if let uuid = callUUID {
let endCallAction = CXEndCallAction(call: uuid)
callController.request(
CXTransaction(action: endCallAction),
completion: { error in
if let error = error {
print("Error: \(error)")
} else {
print("Success")
}
})
}
}
func isCallGoing() -> Bool {
let callController = CXCallController()
if callController.callObserver.calls.count != 0 {
return true
}
return false
}
}
extension AppDelegate: CXProviderDelegate {
func providerDidReset(_ provider: CXProvider) {
print("-Provider-providerDidReset")
}
func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
print("-Provider-perform action: CXAnswerCallAction")
action.fulfill()
}
func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
action.fulfill()
print("-Provider: End Call")
}
func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
action.fulfill()
DispatchQueue.main.asyncAfter(wallDeadline: DispatchWallTime.now() + 3) {
provider.reportOutgoingCall(with: action.callUUID, startedConnectingAt: Date())
DispatchQueue.main.asyncAfter(wallDeadline: DispatchWallTime.now() + 1.5) {
provider.reportOutgoingCall(with: action.callUUID, connectedAt: Date())
}
}
}
func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {
action.fulfill()
}
func provider(_ provider: CXProvider, didActivate audioSession: AVAudioSession) {
RTCAudioSession.sharedInstance().audioSessionDidActivate(audioSession)
RTCAudioSession.sharedInstance().isAudioEnabled = true
}
func provider(_ provider: CXProvider, didDeactivate audioSession: AVAudioSession) {
RTCAudioSession.sharedInstance().audioSessionDidDeactivate(audioSession)
RTCAudioSession.sharedInstance().isAudioEnabled = false
}
}
The power button ends a call if and only if the call is running through the built-in speaker on top of the screen (receiver). In any other case (i.e. the audio is playing through headphones, Bluetooth or built-in loudspeaker) the power button will not end the call.
The same is true with the native phone calls.
I would like to answer all issues related to CallKit here.
Answer for my question is:
You need to set the AudioSession mode to .default after your voip call established successfully.
try AVAudioSession.sharedInstance().setMode(.default)
AudioRouteManager.shared.fourceRouteAudioToSpeakers()

Swift 3 NTLM authentication

For a recent project I tried to pull some data from a server in the SOAP and oData format respectively, that is protected with a Microsoft NTLM authentication, and it has been a nightmare figuring out how to do it, none of the online examples really worked.
So here is my solution; I had to adapt, expand and combine a few different sources. I hope this helps someone in the future.
You might have to allow arbitrary loads!!
Adapted from:
https://gist.github.com/stevenschobert/f374c999e5cba6ccf09653b846967c83
https://blogs.msdn.microsoft.com/chiranth/2013/09/20/ntlm-want-to-know-how-it-works/
import UIKit
class ViewController: UIViewController {
var username: String? = nil
var password: String? = nil
lazy var conn: URLSession = {
let config = URLSessionConfiguration.ephemeral
let session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
return session
}()
override func viewDidLoad() {
super.viewDidLoad()
username = "<username>"
password = "<password>"
ntlm()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func ntlm() {
let urlString = "<url>"
let url = URL(string: urlString)
let request = NSMutableURLRequest(url: url!, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 60000)
request.httpMethod = "GET"
let task = conn.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
print(response)
print(error)
print(String(data: data!, encoding: .utf8))
})
task.resume()
}
func doesHaveCredentials() -> Bool {
guard let _ = self.username else { return false }
guard let _ = self.password else { return false }
return true
}
}
extension ViewController: URLSessionDelegate {
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: #escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
print("got challenge")
guard challenge.previousFailureCount == 0 else {
print("too many failures")
challenge.sender?.cancel(challenge)
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM else {
print("unknown authentication method \(challenge.protectionSpace.authenticationMethod)")
challenge.sender?.cancel(challenge)
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
guard self.doesHaveCredentials() else {
challenge.sender?.cancel(challenge)
completionHandler(.cancelAuthenticationChallenge, nil)
DispatchQueue.main.async {
print("Userdata not set")
};
return
}
let credentials = URLCredential(user: self.username!, password: self.password!, persistence: .forSession)
challenge.sender?.use(credentials, for: challenge)
completionHandler(.useCredential, credentials)
}
}

How to add snooze effect once a notification is delivered in ios 10

I am implementing UserNotification in my app. When the notification gets fired it shows two action, in one i want to add snooze effect, it must snooze after 5 mins again. How to handle it ? thanks for all ! help if any one do have idea
Well to snooze notification you can create another notification with same details of current notification and increase the fire date by 5 mins.
Here is the code I used :
func snoozeScheduledNotification(notification:UILocalNotification) -> Void {
// Snooze for 10 mins
let localNotification = UILocalNotification()
localNotification.fireDate = notification.fireDate?.addingTimeInterval(60*10)
localNotification.repeatInterval = NSCalendar.Unit(rawValue: 0) // 0 = No Repeat
localNotification.alertBody = notification.alertBody
localNotification.soundName = notification.soundName
localNotification.userInfo = notification.userInfo
localNotification.category = notification.category
UIApplication.shared.scheduleLocalNotification(localNotification)
}
Hope it helps you.
The shortest and simplest code I found about it
For Swift 3/4
extension UNNotification {
func snoozeNotification(for hours: Int, minutes: Int, seconds: Int) {
let content = UNMutableNotificationContent()
content.title = "Another Alert"
content.body = "Your message"
content.sound = .default()
let identifier = self.request.identifier
guard let oldTrigger = self.request.trigger as? UNCalendarNotificationTrigger else {
debugPrint("Cannot reschedule notification without calendar trigger.")
return
}
var components = oldTrigger.dateComponents
components.hour = (components.hour ?? 0) + hours
components.minute = (components.minute ?? 0) + minutes
components.second = (components.second ?? 0) + seconds
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: false)
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { error in
if let error = error {
debugPrint("Rescheduling failed", error.localizedDescription)
} else {
debugPrint("rescheduled success")
}
}
}
}
You just need to call it this way :
response.notification.snoozeNotification(for: 0, minutes: 0, seconds: 30)
Credit goes to Simon Ljungberg : https://gist.github.com/simme/96264d5ceee394083d18e2c64f42a3a9
For iOS10, use this code.
Use this code in AppDelegate.swift file.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
let center = UNUserNotificationCenter.current()
let category = UNNotificationCategory(identifier: "identifier", actions: [], intentIdentifiers: [])
center.setNotificationCategories([category])
center.requestAuthorization(options: [.badge, .alert , .sound]) { (greanted, error) in
print(error)
}
return true
}
You can put this code in any view controller.
let content = UNMutableNotificationContent.init()
content.title = "Notification Title"
content.subtitle = "Notification Sub-Title"
content.body = "Notification Body"
content.sound = UNNotificationSound.default()
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
let request = UNNotificationRequest(identifier: "identifier", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { error in
UNUserNotificationCenter.current().delegate = self
if (error != nil){
//handle here
}
}
You can handle notification using following method:
extension UIViewController: UNUserNotificationCenterDelegate {
public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Swift.Void) {
completionHandler( [.alert, .badge, .sound])
}
public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Swift.Void) {
print("Tapped in notification")
}
}
You can use this Blog as reference and Example.

No sound from remote notification

Could some one help me to understand why i'm not receiving sound from remote notifications in IOS 10 Swift 3.
Here is my code:
AppDelegate:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]?) -> Bool {
let settings = UNUserNotificationCenter.current()
settings.requestAuthorization(options: [.badge, .alert, .sound]) {(granted, error) in
}
return true
}
// Override point for customization after application launch.
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
let viewController = self.window?.rootViewController as! LoadingCloudDataViewController
let notification: CKNotification = CKNotification(fromRemoteNotificationDictionary: userInfo as! [String: NSObject])
if(notification.notificationType == CKNotificationType.query) {
let queryNotification = notification as! CKQueryNotification
let recordID = queryNotification.recordID
viewController.fetchRecord(recordID: recordID!)
}
}
And here is the notification subscription code:
func subscriptionNotificationsKcal() {
publicDatabase = container.publicCloudDatabase
let predicate = NSPredicate(format: "TRUEPREDICATE")
let subscription = CKQuerySubscription(recordType: "Kcal", predicate: predicate, options: .firesOnRecordCreation)
let notificationInfo = CKNotificationInfo()
notificationInfo.alertBody = "New Calories Item was Added"
notificationInfo.shouldBadge = true
subscription.notificationInfo = notificationInfo
publicDatabase?.save(subscription, completionHandler: ({returnRecord, error in
if let err = error {
print("subscription failed %#", err.localizedDescription)
}else{
print("sub success")
}
}))
}
By default the sound is muted. To activate it, in the case of this example, use the following code:
notificattionInfo.soundName = "default"

Swift / How to parse json from java spring code

I want to parse json from java spring code (Xcode 7.3 / Swift). I tried almost every solution from all sites.
When I register it gives the following error message at the console:
Response = Optional(<NSHTTPURLResponse: 0x7a7607e0> { URL: http://www.____.com/saveRegistrationJson.htm } { status code: 405, headers {
Allow = GET;
Connection = "Keep-Alive";
"Content-Length" = 1089;
"Content-Type" = "text/html;charset=utf-8";
Date = "Wed, 04 May 2016 12:21:34 GMT";
"Keep-Alive" = "timeout=15, max=100";
Server = "Apache-Coyote/1.1";
} })
before json
Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.}
This is my Code:
import UIKit
class RegistrationViewController: UIViewController {
#IBOutlet weak var userfnametextfield: UITextField!
#IBOutlet weak var userlnametextfield: UITextField!
#IBOutlet weak var useremailtextfield: UITextField!
#IBOutlet weak var userpwdtextfield: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func RegisterbtnTapped(sender: AnyObject) {
let fname = userfnametextfield.text
let lname = userlnametextfield.text
let Email = useremailtextfield.text
let pwd = userpwdtextfield.text
//check empty fields
if(fname!.isEmpty || lname!.isEmpty || Email!.isEmpty || pwd!.isEmpty )
{
DisplayMyAlertMessage("All Fields are required")
return
}
//store data
NSUserDefaults.standardUserDefaults().setObject(fname, forKey: "fname")
NSUserDefaults.standardUserDefaults().setObject(lname, forKey: "lname")
NSUserDefaults.standardUserDefaults().setObject(Email, forKey: "Email")
NSUserDefaults.standardUserDefaults().setObject(pwd, forKey: "password")
NSUserDefaults.standardUserDefaults().synchronize()
//send user data to server side
let myurl = NSURL(string: "http://www.____.com/saveRegistrationJson.htm")
let request = NSMutableURLRequest(URL: myurl!)
request.HTTPMethod = "POST"
let poststring = "fname\(fname!)&lname\(lname!)&email\(Email!)&password\(pwd!)"
request.HTTPBody = poststring.dataUsingEncoding(NSUTF8StringEncoding)
//request.HTTPBody = postData
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){data,response, error in
if error != nil{
print("Error\(error)")
return
}
print("Response = \(response)")
do{
var err : NSError?
print("before json")
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as? NSDictionary
print(json)
print("After json")
//print("demo : \(response?.description)")
guard let parseJSON = json else{
print("parsing json here:")
return
}
// guard let value = NSString(data: data!, encoding: NSUTF8StringEncoding) else{
// print("parsed")
// return
//}
//print("FirstName\(value)")
var requestValue = parseJSON[" "] as? String
print("result:\(requestValue)")
var isUserRegistered:Bool = false
if(requestValue=="Success") { isUserRegistered = true}
var messageToDisplay:String = parseJSON["Success"] as! String
if(!isUserRegistered){
messageToDisplay = parseJSON[" "] as! String
}
dispatch_async(dispatch_get_main_queue(), {
let myAlert = UIAlertController(title: "Alert", message: messageToDisplay, preferredStyle: UIAlertControllerStyle.Alert)
let onAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default) { (ACTION) -> Void in
self.dismissViewControllerAnimated(true, completion: nil)
}
myAlert.addAction(onAction)
self.presentViewController(myAlert, animated: true, completion: nil)
})
}
catch let error as NSError
{
print(error)
}
}
task.resume()
Help is very appreciated.