12/08/2018, 11:26

Mode Background iOS

Các ứng dụng chạy trên nền iOS hầu như sẽ bị dừng lại khi bạn bấm nút "Home" hoặc bạn chuyển sang chạy một ứng dụng khác, mặc dù nó vẫn còn tồn tại trong bộ nhớ nhưng nó sẽ không chạy bất cứ đoạn mã nào cho đến khi người dùng bật nó lên một lần nữa. Tuy nhiên trong một số trường hợp cụ thể ứng dụng ...

Các ứng dụng chạy trên nền iOS hầu như sẽ bị dừng lại khi bạn bấm nút "Home" hoặc bạn chuyển sang chạy một ứng dụng khác, mặc dù nó vẫn còn tồn tại trong bộ nhớ nhưng nó sẽ không chạy bất cứ đoạn mã nào cho đến khi người dùng bật nó lên một lần nữa. Tuy nhiên trong một số trường hợp cụ thể ứng dụng của bạn có thể tiếp tục chạy các đoạn mã trong chế độ nền. Như bạn đã biết Apple nổi tiếng nhờ sự khó tính và khắc khe với các nhà phát triển ứng dụng do đó các trường hợp chạy ở chế độ nền cũng được Apple quy định rất cụ thể.

  1. Ứng dựng chơi nhạc
  2. Ứng dụng cập nhật vị trí
  3. Ứng dụng push notification
  4. Ứng dụng chạy trong quầy báo (Newsstand)
  5. Ứng dụng chạy nền với thời gian hữu hạn
  6. Ứng dụng VoIP

Sau đây tôi sẽ giới thiệu 2 trường hợp iOS cho phép ứng dụng của bạn chạy trong nền của nó là cập nhật vị trí và nhận push notification.

Push notification

Tôi sẽ demo 1 ví dụ update 1 ảnh khi app đang ở chế độ nền nếu nhận được push. Để chạy được push thì bạn có thể dùng file php và pem tôi đính kèm ở cuối

Tạo new project

Sửa file plist như hình sau

Screen Shot 2015-09-22 at 4.42.11 PM.png

Click vào project và chọn Capabilities/Background modes và tích vào Remote Notification

Screen Shot 2015-09-22 at 11.24.22 PM.png

Trong Appdelegate -> didFinishLaunchingWithOptions thêm dòng code đăng ký push notification

UIApplication.sharedApplication().registerForRemoteNotificationTypes( [.Alert, .Badge, .Sound])

Trong Appdelegate thêm hàm didRegisterForRemoteNotificationsWithDeviceToken để lấy device token, bạn hãy thay device token này vào file push_dev.php.

func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
    let replacing1 = deviceToken.description.stringByReplacingOccurrencesOfString("<", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
    let replacing2 = replacing1.stringByReplacingOccurrencesOfString("<", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
    let replacing3 = replacing2.stringByReplacingOccurrencesOfString(">", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
    let deviceTokenString: NSString = replacing3.stringByReplacingOccurrencesOfString(" ", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
    NSLog("------Device_Token-----> %@", deviceTokenString);
}

Trong Appdelegate thêm hàm lắng nghe khi có remote notification, trong hàm này sẽ lấy được tên file ảnh trả về và cập nhật lại view.

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
    if application.applicationState == UIApplicationState.Background {
        print("didReceiveRemoteNotification-->UIBackgroundFetchResult")
        print(userInfo.description)
        //get image url from payload
        if let apsData = userInfo["aps"] as? NSDictionary {
            if let imageUrl = apsData["image_url"] as? String {
                imageViewController.setImage(imageUrl)
            }
        }
    }
    completionHandler(.NewData)
}

link source: https://github.com/phanthanhhai/push_notification_background

update current location

Tôi sẽ demo 1 ví dụ app khi đang ở chế độ nền sẽ liên tục cập nhật vị trí hiện tại và push local về máy. Tạo 1 project mới

Click vào project và chọn Capabilities/Background modes và tích vào Remote Notification

Screen Shot 2015-09-22 at 11.24.41 PM.png

Thêm key NSLocationAlwaysUsageDescription cho plist file

Screen Shot 2015-09-22 at 11.28.22 PM.png

Thêm đoạn code sau để lấy location

 locationManager = CLLocationManager()
        locationManager?.delegate = self
        locationManager?.desiredAccuracy = kCLLocationAccuracyBest
        locationManager?.startUpdatingLocation()
        locationManager?.requestAlwaysAuthorization()

        if( CLLocationManager.authorizationStatus() == CLAuthorizationStatus.AuthorizedWhenInUse ||
            CLLocationManager.authorizationStatus() == CLAuthorizationStatus.AuthorizedAlways){
                let currentLocation = locationManager?.location
                longtitudeLb.text = "(currentLocation!.coordinate.longitude)"
                latitudeLb.text = "(currentLocation!.coordinate.latitude)"
        }

Thêm 2 delegates sau để lắng nghe khi có thông tin vị trí gửi về

func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
   print("Error while updating location " + error.localizedDescription)
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler: { (placemarks, error) -> Void in
        if (error != nil) {
            print("Reverse geocoder failed with error" + error.localizedDescription)
            return
        }
        if placemarks.count > 0 {
            let pm = placemarks[0] as? CLPlacemark
            self.displayLocationInfo(pm)
        } else {
            print("Problem with the data received from geocoder")
        }
    })
}

Khi nhận được vị trí thì push local để nhắc

func displayLocationInfo(placemark: CLPlacemark?) {
    if placemark != nil {
//    stop updating location to save battery life
//    locationManager?.stopUpdatingLocation()
    print(placemark!.locality)
    print(placemark!.postalCode)
    print(placemark!.administrativeArea)
    print(placemark!.country)
    self.pushLocalTouched()
    }
}

func pushLocalTouched() {
        let notification = UILocalNotification()
        notification.alertBody = "New location" // text that will be displayed in the notification
        notification.alertAction = "open" // text that is displayed after "slide to..." on the lock screen - defaults to "slide to view"
        notification.fireDate = NSDate(timeIntervalSinceNow: 3)
        notification.soundName = UILocalNotificationDefaultSoundName;
        notification.applicationIconBadgeNumber = 1;
        notification.userInfo = ["UUID": "aaaaaaaa", ] // assign a unique identifier to the notification so that we can retrieve it later
        UIApplication.sharedApplication().scheduleLocalNotification(notification)
}

link source: https://github.com/phanthanhhai/location_background

Thank you!

0