6

Tôi đang làm việc trên một biến chứng để nhận dữ liệu được lên lịch từ một dịch vụ web. Mỗi 20-30 phút (hoặc theo cách thủ công), tôi lên lịch WKRefreshBackgroundTask để thực hiện việc này.WKURLSessionRefreshBackgroundTask không được gọi khi cố gắng làm lại nền trong watchOS

Theo đề xuất của Apple, tôi muốn hệ điều hành xử lý việc tìm nạp dữ liệu này qua nền NSURLSession.

Đây là chức năng tôi sử dụng để tải về dữ liệu tôi cần:

func scheduleURLSession() 
{ 
    print("\nScheduling URL Session...") 

    let backgroundSessionConfig:URLSessionConfiguration = URLSessionConfiguration.background(withIdentifier: NSUUID().uuidString) 
    backgroundSessionConfig.sessionSendsLaunchEvents = true 

    let backgroundSession = URLSession(configuration: backgroundSessionConfig) 

    let downloadTask = backgroundSession.downloadTask(with: URL(string: "https://www.myserver.com/somedata")!) 
    downloadTask.resume() 
} 

Một vài điều về vấn đề này:

  1. Nó được gọi khi tôi sắp xếp nó. Tôi thấy câu lệnh in của nó trong bảng điều khiển.
  2. Nó gần giống với ví dụ của Apple.
  3. Tôi đã bỏ qua URL. URL tương tự đó hoạt động trong các ứng dụng iOS/watchOS tốt nên không có gì sai với nó.

Vấn đề là, mặc dù tôi đang gọi resume() về nhiệm vụ và cho phép ứng dụng đánh thức ứng dụng của tôi khi nó hoàn tất, có vẻ như nó không hoạt động.

Khi nó hoàn thành, nó sẽ được trở lại với một handler WKExtensionDelegate:

func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) 

như một WKURLSessionRefreshBackgroundTask, nhưng nó không.

Mã của tôi, giống với mã mẫu của Apple, sau đó tạo một phiên khác nhưng tham gia lại phiên đó thông qua mã nhận dạng WKURLSessionRefreshBackgroundTask. Đây là nơi đại biểu được thiết lập để xử lý dữ liệu đã tải xuống. Kiểm tra mã:

func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) { 
    for task in backgroundTasks { 
     switch task { 

     case let backgroundTask as WKApplicationRefreshBackgroundTask: 
      print("\nWatchKit - WKApplicationRefreshBackgroundTask") 
      // self.updateComplicationDataArrivalTimes(backgroundTask) 
      self.scheduleURLSession() 
      backgroundTask.setTaskCompleted() 

     case let snapshotTask as WKSnapshotRefreshBackgroundTask: 
      // Snapshot tasks have a unique completion call, make sure to set your expiration date 
      print("\nWatchKit - WKSnapshotRefreshBackgroundTask") 
      snapshotTask.setTaskCompleted(restoredDefaultState: true, estimatedSnapshotExpiration: Date.distantFuture, userInfo: nil) 

     case let connectivityTask as WKWatchConnectivityRefreshBackgroundTask: 
      print("\nWatchKit - WKWatchConnectivityRefreshBackgroundTask") 
      connectivityTask.setTaskCompleted() 

     case let urlSessionTask as WKURLSessionRefreshBackgroundTask: 
      print("\nWatchKit - WKURLSessionRefreshBackgroundTask") 
      let backgroundConfigObject = URLSessionConfiguration.background(withIdentifier: urlSessionTask.sessionIdentifier) 
      let backgroundSession = URLSession(configuration: backgroundConfigObject, delegate: self, delegateQueue: nil) 

      print("Rejoining session ", backgroundSession) 
      urlSessionTask.setTaskCompleted() 

     default: 
      // make sure to complete unhandled task types 
      task.setTaskCompleted() 
     } 
    } 
} 

Nhưng một lần nữa, dường như không bao giờ quay lại. Tôi dường như không thể hiểu tại sao điều này hoạt động mặc dù mã giống hệt mã mẫu của Apple cho dự án này: WatchBackgroundRefresh: Using WKRefreshBackgroundTask to update WatchKit apps in the background.

Có một số cài đặt trong dự án của tôi mà tôi bị thiếu không? Tôi đang đặt tất cả mã này vào số ExtensionDelegate, mới trong watchOS 3. Tôi cũng tuân theo WKExtensionDelegateURLSessionDownloadDelegate.

Cảm ơn sự giúp đỡ của bạn trước!

+0

Bạn đã bao giờ giải quyết vấn đề này chưa? –

+1

Nó rất cồng kềnh. Khi tôi gửi một lỗi, đại diện Apple nói với tôi rằng điều này chỉ hoạt động trên một thiết bị vật lý (không phải là trình mô phỏng). Tôi ước họ đã nói điều này trong tài liệu thực tế cho dự án mẫu mà họ đã đăng trên trang web của họ. Ngoài ra, phải mất một lúc. Bạn phải thực sự chờ đợi cho các cuộc gọi lại cho tuy nhiên bạn có lịch trình nó. Ngoài ra, có vẻ như bạn có thể chạy ra khỏi các công việc nền được phân bổ hàng ngày của bạn bởi vì sau một thời gian, nó dường như ngừng hoạt động cho đến ngày hôm sau - khi hệ thống cho phép nhiều tác vụ nền hơn. –

+0

Cảm ơn! Thats .... tốt, tin khủng khiếp. Nhưng nó cũng giải thích lý do tại sao tôi không thể lấy ví dụ về Apple làm việc trong trình mô phỏng. Tôi không sở hữu một chiếc đồng hồ Apple, vì vậy hoặc là tôi mua một cái hoặc rút lại ứng dụng của tôi: ( –

Trả lời

3

Tôi chưa bao giờ làm ví dụ của Apple hoạt động, nhưng tôi đã làm việc nền làm mới. Không giống như ví dụ của họ, bạn sẽ cần phải làm cho mình đại biểu của phiên. Vì vậy, tạo phiên nền của bạn như thay vì điều này:

hãy backgroundSession = URLSession (cấu hình: backgroundSessionConfig, đại biểu: tự, delegateQueue: nil)

Tôi có một mã ví dụ chi tiết ở đây (xem mã của câu hỏi):

WatchOS 3 WKApplicationRefreshBackgroundTask didReceiveChallenge

Hy vọng điều đó sẽ hữu ích.

+0

Tôi không thể thấy sự khác biệt với những gì bạn đăng trong câu hỏi –

+0

Mã của câu hỏi đang hoạt động trong sản xuất – CodenameDuchess

4

Tôi đã làm việc đó! Tôi bắt đầu bằng cách tìm kiếm rất nhiều video/ghi chú của WWDC'16, so sánh chúng với ví dụ WatchBackgroundRefresh từ Apple.Sau đó, trong khi duyệt diễn đàn Apple Dev, tôi đã tìm thấy this thread, với cùng một vấn đề mà chúng tôi gặp phải. Ở đó, một anh chàng, "Daniel Fontes" đăng bài 'công thức' của mình để làm cho nó hoạt động (lưu ý, không phải câu trả lời được chấp nhận!), Và kết hợp với các video làm việc cho tôi.

Tôi đã làm gì để làm cho Apple dụ làm việc:

  1. Tận dụng tối MainInterfaceController một URLSessionDelegate
  2. Tạo một biến địa phương: var savedTask:WKRefreshBackgroundTask?
  3. Trong handle(backgroundTasks:) chức năng, lưu WKURLSessionRefreshBackgroundTask vào biến địa phương self.savedTask = task - không task.setTaskCompleted() (!!)
  4. Trong urlSession - didFinishDownloading:, đặt tác vụ đã lưu để hoàn thành: self.savedTask?.setTaskCompleted() sau khi bạn đã rea d dữ liệu nhận được.
  5. Đảm bảo rằng tài nguyên bạn đang truy cập là https: //, nếu không hãy thêm "Cài đặt bảo mật giao thông ứng dụng" vào tệp Info.plist của bạn.

Hy vọng điều này có thể hữu ích!

ps. điều này làm việc trong simnulator (xcode 8.3.3, watchOS 3.2)

+0

Mẹo tuyệt vời @ Jens Peter !! Nhưng bây giờ các đại biểu đang ở trên ExtensionDelegate của tôi và nó hoạt động.Nhưng hai điều tôi không thể giải quyết: 1 - Tôi tiếp tục nhận được thông báo rằng phiên nền với mã định danh mà tôi sử dụng đã tồn tại. dù sao đi nữa. 2 - bạn đặt lệnh gọi 'invalidateAndCancel()' ở đâu? Tôi không sử dụng nó. Tôi có nên không? – francisaugusto

Các vấn đề liên quan