Hành vi đối với API vị trí thay đổi đáng kể khi bị chấm dứt / tạm ngừng?


108

Đây là phần từ tài liệu CLLocationManager mô tả hành vi của ứng dụng với startMo MonitoringSignificantLocationChanges :

Nếu bạn khởi động dịch vụ này và ứng dụng của bạn sau đó bị chấm dứt, hệ thống sẽ tự động khởi chạy lại ứng dụng ở chế độ nền nếu có sự kiện mới. Trong trường hợp như vậy, từ điển tùy chọn được chuyển đến ứng dụng: didFinishLaunchingWithOptions: phương thức đại biểu ứng dụng của bạn chứa khóa UIApplicationLaunchOptionsLocationKey để chỉ ra rằng ứng dụng của bạn đã được khởi chạy do một sự kiện vị trí. Sau khi khởi chạy lại, bạn vẫn phải định cấu hình đối tượng trình quản lý vị trí và gọi phương thức này để tiếp tục nhận các sự kiện vị trí. Khi bạn khởi động lại dịch vụ vị trí, sự kiện hiện tại sẽ được chuyển đến người đại diện của bạn ngay lập tức. Ngoài ra, thuộc tính vị trí của đối tượng trình quản lý vị trí của bạn được điền với đối tượng vị trí gần đây nhất ngay cả trước khi bạn bắt đầu dịch vụ vị trí.

Vì vậy, sự hiểu biết của tôi là nếu ứng dụng của bạn kết thúc (và tôi giả sử nếu bạn không gọi stopMo MonitoringSignificantLocationChanges từ applicationWillTermina ), bạn sẽ bị đánh thức với tham số UIApplicationLaunchOptionsLocationKey cho ứng dụng: didFinishLaunchingWithOptions . Tại thời điểm đó, bạn tạo CLLocationManager của mình , gọi startMo MonitoringSignificantLocationChanges và xử lý vị trí nền của bạn trong một khoảng thời gian giới hạn . Vì vậy, tôi ổn với chút này.

Đoạn trước chỉ nói về những gì sẽ xảy ra khi ứng dụng bị chấm dứt, nó không đề xuất bạn làm gì khi ứng dụng bị tạm ngưng. Tài liệu cho didFinishLaunchingWithOptions cho biết:

Ứng dụng theo dõi các cập nhật vị trí trong nền, đã bị xóa và hiện đã được khởi chạy lại. Trong trường hợp này, từ điển chứa một khóa cho biết rằng ứng dụng đã được khởi chạy lại do một sự kiện vị trí mới.

Đề xuất rằng bạn sẽ chỉ nhận được cuộc gọi này khi ứng dụng của bạn được khởi chạy (do thay đổi vị trí) sau khi bạn đã bị chấm dứt.

Tuy nhiên, đoạn về Dịch vụ Thay đổi Đáng kể trong Hướng dẫn Lập trình Nhận thức Vị trí có nội dung sau:

Nếu bạn để dịch vụ này chạy và ứng dụng của bạn sau đó bị tạm ngưng hoặc chấm dứt, dịch vụ sẽ tự động đánh thức ứng dụng của bạn khi dữ liệu vị trí mới đến. Vào thời điểm đánh thức, ứng dụng của bạn được đặt ở chế độ nền và có một khoảng thời gian nhỏ để xử lý dữ liệu vị trí. Bởi vì ứng dụng của bạn ở chế độ nền, nó sẽ thực hiện công việc tối thiểu và tránh bất kỳ tác vụ nào (chẳng hạn như truy vấn mạng) có thể ngăn ứng dụng trở lại trước khi hết thời gian được phân bổ. Nếu không, ứng dụng của bạn có thể bị chấm dứt.

Điều này cho thấy bạn được đánh thức với dữ liệu vị trí nếu ứng dụng của bạn đã bị tạm ngưng, nhưng không đề cập đến cách bạn được đánh thức:

  • Liệu UIApplicationDelegate nhận được một cuộc gọi lại nói với tôi rằng tôi đang khôi phục từ trạng thái lơ lửng vào trạng thái nền?
  • Trình quản lý vị trí (đã được làm khô khi ứng dụng bị tạm ngừng) có bắt đầu nhận các lệnh gọi lại locationManager: didUpdateToLocation: fromLocation không?
  • Tôi có chỉ cần triển khai mã trong thông báo didUpdateToLocation của mình để kiểm tra trạng thái ứng dụng và thực hiện xử lý tối thiểu nếu ở chế độ nền không?

Trong quá trình viết ra điều này, tôi nghĩ rằng tôi có thể vừa trả lời câu hỏi của riêng mình, nhưng sẽ thật tuyệt nếu sự hiểu biết của tôi về điều này được xác nhận bởi một người hiểu biết hơn.

Câu trả lời:


80

Kể từ khi tôi hỏi câu hỏi này, tôi đã thực hiện một chút thử nghiệm (chủ yếu là trên tàu giữa nhà và nơi làm việc) và đã xác nhận rằng hành vi đối với các ứng dụng bị tạm ngưng như tôi đã nghi ngờ ở cuối câu hỏi.

Tức là, ứng dụng bị tạm ngưng của bạn được đánh thức, bạn không nhận được bất kỳ cuộc gọi lại nào về người đại diện ứng dụng của mình, thay vào đó bạn nhận được thông tin cập nhật về vị trí của mình thông qua CLLocationManagerDelegate hiện có . Bạn có thể phát hiện ra rằng bạn đang chạy trong nền bằng cách kiểm tra Trạng thái ứng dụng và thực hiện công việc hạn chế đối với trường hợp bạn bị đánh thức từ trạng thái bị treo để thực hiện xử lý vị trí.

[UIApplication sharedApplication].applicationState == UIApplicationStateBackground

Tôi đã đưa ra kết luận này với một bộ khai thác kiểm tra vị trí mà bạn có thể tải xuống và dùng thử. Đây là một ứng dụng khá đơn giản cho phép bạn bật các API thay đổi đáng kể và GPS thông qua giao diện người dùng và ghi lại tất cả các phản hồi mà bạn nhận được.

NB Điểm sáu trong câu trả lời trước không đúng. Đóng băng các ứng dụng bị treo đã làm khô nhận được lệnh gọi lại CLLocationManagerDelegate khi chúng được đánh thức từ trạng thái tạm ngừng.


1
Viết ra số 6 trong câu trả lời của tôi để không gây nhầm lẫn cho mọi người.
Aaron

Trớ trêu thay, tôi cũng cảm thấy bối rối tương tự khi phát triển cho sự thay đổi quan trọng. Tôi vẫn còn một số nghi ngờ về điều gì sẽ xảy ra nếu ứng dụng bị đóng. gọi lại UIApplicationDelegate sẽ không xảy ra? đó có phải là cách phù hợp để khởi động ứng dụng không. nếu người quản lý vị trí vẫn chưa được kích hoạt, làm thế nào nó có thể nhận thông báo trong nền? (thời gian cho một số R & D hơn)
darshansonde

Cảm ơn rất nhiều vì ứng dụng mẫu, nó rất hữu ích cho tôi. Tôi có một câu hỏi: Điều gì sẽ xảy ra nếu tôi đang sử dụng dịch vụ vị trí tiêu chuẩn trong nền, không phải dịch vụ quan trọng, ứng dụng cũng sẽ được khởi chạy lại sau khi chấm dứt trong trường hợp đó? Tôi hỏi câu hỏi này ở đây một cách chi tiết, tôi muốn được vui mừng nếu bạn có thể làm sáng tôi dậy:] stackoverflow.com/questions/12239967/...
aslisabanci

2
Không hoạt động trên ios7 stackoverflow.com/questions/18946881/…
Igor

Bạn có biết mất bao lâu để ứng dụng của bạn bị chấm dứt không? Và sau đó nhận được một cuộc gọi lại appDelegate thay thế? (Có phải 30 phút không? 2 giờ? 5 giờ?) Lý do tôi hỏi điều này là vì tôi đã thiết lập một khu vực để giám sát. Đã cố gắng nhiều lần để thấy ứng dụng của tôi được khởi chạy nhưng chỉ một lần tôi phải khởi chạy lại ứng dụng. Giờ khác didExitRegiongọi lại nhưng tôi đã không thể startLocationUpdatestừ đó như nó đã không qua mắt ứng dụng ...
Mật ong

25

Sự hiểu biết của tôi như sau (Tôi đang trong quá trình viết một ứng dụng dựa trên API này, nhưng chưa hoàn thành đủ thành phần này để bắt đầu thử nghiệm):

  1. Ứng dụng của bạn được chạy lần đầu tiên, bạn đăng ký startMoosystemSignificantLocationChanges và cung cấp chức năng gọi lại. Trong khi ứng dụng của bạn đang chạy, nó sẽ gọi lại cuộc gọi đó bất cứ khi nào nó nhận được một thay đổi đáng kể.
  2. Nếu ứng dụng của bạn được đặt ở chế độ nền, UIApplication sẽ nhận applicationWillResignActive , tiếp theo là applicationDidEnterBackground .
  3. Nếu ứng dụng của bạn bị giết trong khi nó bị treo ở chế độ nền, bạn sẽ không được thông báo; tuy nhiên, nếu ứng dụng của bạn bị tắt khi đang chạy (nền trước hoặc nền theo hiểu biết của tôi), bạn sẽ có được một khoảnh khắc với ứng dụng applicationWillTermina . Bạn không thể yêu cầu thêm thời gian nền từ chức năng này.
  4. Mặc dù bị giết trong nền, hệ điều hành sẽ khởi chạy lại ứng dụng của bạn. Nếu ứng dụng của bạn chỉ được khởi chạy bởi HĐH để thay đổi, bạn sẽ nhận được cuộc gọi đến ứng dụng didFinishLaunchingWithOptions :

    if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey])

    sẽ giúp bạn xác định xem bạn có quay lại sau khi thay đổi vị trí nền hay không.

  5. Thay vào đó, nếu bạn hiện đang chạy ở chế độ nền và ứng dụng của bạn được người dùng khởi chạy lại theo cách thủ công, bạn sẽ nhận được một applicationWillEnterForeground theo sau là applicationDidBecomeActive .
  6. Bất kể điều đó xảy ra như thế nào, khi ứng dụng của bạn được khởi chạy lại (trừ khi nó vẫn đang chạy ở chế độ nền do tác vụ nền và tác vụ được cho biết đã bắt đầu theo dõi các thay đổi), bạn cần phải thông báo rõ ràng cho ứng dụng của bạn startMoosystemSignificantLocationChanges một lần nữa vì lệnh gọi lại không còn gắn liền sau khi "làm khô đông lạnh." Và có, bạn chỉ cần triển khai mã trong didUpdateToLocation sau khi bạn đã đính kèm lại một trình xử lý vị trí của một loại nào đó sau khi quay trở lại từ trạng thái bị treo.

Đây là những gì tôi đang làm với quá trình phát triển mã của mình ngay bây giờ. Như tôi đã đề cập trước đây, tôi chưa sẵn sàng để kiểm tra điều này trên một thiết bị vì vậy tôi không thể biết liệu mình đã diễn giải mọi thứ một cách chính xác hay chưa, vì vậy những người bình luận, vui lòng sửa cho tôi (mặc dù tôi đã đọc đáng kể về đề tài).

Ồ, và nếu không may mắn xảy ra, bạn phát hành một ứng dụng làm những gì tôi muốn, tôi có thể khóc :)

Chúc may mắn!


1
@Tegeril +1 Cảm ơn vì câu trả lời. Tôi đã bắt đầu nghe thấy tiếng dế kêu trên cái này. :) Tôi rất ngạc nhiên khi các ứng dụng bắt đầu bị tạm ngưng cần phải gọi lại startMoosystemSignificantLocationChanges. Bạn có liên kết đến doco nơi mô tả điều này không? Tôi hiểu rằng được tải từ trạng thái bị tạm ngưng sẽ khởi tạo tất cả các đối tượng của bạn như khi ứng dụng bị tạm ngưng. Vì vậy, tôi hy vọng yêu cầu thay đổi đáng kể sẽ có hiệu lực.
RedBlueThing

Bạn có thể đang nói về điều này? "Sau khi khởi chạy lại, bạn vẫn phải định cấu hình đối tượng trình quản lý vị trí và gọi phương thức này để tiếp tục nhận các sự kiện vị trí" Nhưng tôi nghĩ điều này đề cập đến trường hợp ứng dụng của bạn đã khởi chạy từ trạng thái đã kết thúc (bởi một sự kiện vị trí). Về cơ bản đây là gốc rễ của câu hỏi của tôi, 'điều gì xảy ra đối với vụ án bị đình chỉ?'.
RedBlueThing

Morgan Grainger trên các diễn đàn Dev đề xuất điều này: "Bạn cần tạo CLLocationManager, đặt một đại biểu và gọi startMoosystemSignificantLocationChanges khi ứng dụng của bạn được khởi chạy, nếu không, Core Location sẽ không có nơi nào để cung cấp các bản cập nhật." trong bối cảnh khởi động lại một ứng dụng bất kể từ trạng thái bị chấm dứt hay bị tạm ngưng. Từ "ứng dụng đã được khởi chạy lại sau startMoosystemSignificantLocationChanges và bây giờ là gì?"
Aaron

Tôi đồng ý rằng điều này vẫn có thể mơ hồ ngay cả trong bối cảnh của bài đăng trên diễn đàn đó (người đăng đang thảo luận về việc đánh thức từ nền, nhưng Morgan đã sử dụng cách khởi động lại ứng dụng tổng quát hơn). Tôi vẫn nghĩ rằng bạn cần phải gọi để theo dõi lại khi ứng dụng của bạn khởi chạy lại nếu bạn muốn làm việc với chức năng thay đổi quan trọng. Thay vào đó, nếu bạn muốn khởi chạy một tác vụ nền và cập nhật với dịch vụ vị trí tiêu chuẩn và chức năng GPS, thì đó là một tùy chọn thay thế. Tuy nhiên, tôi không tin rằng bạn cần phải đăng ký lại mỗi lần khởi chạy với những thay đổi đáng kể để được khởi chạy lại.
Aaron

1
Tôi vui mừng một cái gì đó dứt khoát bước ra khỏi đây, sẽ giúp tôi trong tương lai :)
Aaron

1

Nếu ứng dụng được kích hoạt từ trạng thái bị treo do thay đổi vị trí, ứng dụng sẽ khởi chạy ở trạng thái nền.

Tất cả các đối tượng sẽ hoạt động và bạn sẽ nhận được cập nhật vị trí trong đại biểu hiện có.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.