Skip to main content

Hướng dẫn chạy location ở dưới background trên iOS 6.0 và iOS 7.0

Mình bỏ nhiều thời gian nghiên cứu về vấn đề này nên hôm nay xin chia sẻ những kinh nghiệm mà mình tích góp được về vấn đề xử lý location ở dưới background trên iOS 6 và iOS 7. Sau này ra iOS 8 hay 9 mình sẽ cập nhật lại sau ^^.






Những thứ bạn cần nắm trước khi bắt đầu như:
- Hiểu cơ chế, các dịch vụ để  lấy location, cách sử dụng dịch vụ đó? Bạn cần xem tại đây.
Ở đây mình xin tóm tắt apple hỗ trợ chúng ta 2 dịch vụ để lấy location là "Standard Location Service" và "Significant Location Service".
  • "Standard Location Service": Là dịch vụ chuẩn thông thường đề lấy location của system. Nếu dùng service này bạn có thể chỉnh theo tuỳ thích mà bạn muốn, ví dụ như: Luôn luôn cập nhật location, cập nhật location theo thời gian (Lưu ý: nếu bạn ở trạng thái background thì phải tuân thủ thời gian cho phép chạy timer đó, cái này mình sẽ đề cập ở phần sau.), cập nhật location khi đi xa 1 khoảng cách là bao nhiêu, ...
  • "Significant Location Service": Là dịch vụ lấy location theo khi đã khi 1 khoảng cách xa nào đó do system của apple sẽ tự tính và trả về cho client. Apple khuyến khích dùng dịch vụ này ở dưới background, vì nó sẽ tiết kiệm pin nhất.
- Hiểu về độ chính xác của stardard location: ví dụ như kCLLocationAccuracyBestForNavigation, kCLLocationAccuracyBest, kCLLocationAccuracyNearestTenMeters, ... Theo mình được biết thì dự vào thông số này apple sẽ dùng GPS hay Cell Tower (Là các trạm sóng điện thoại để lấy location). Tài liệu tham khảo từ đây . Theo mình thấy thì độ chính xác cũng ảnh hưởng đến lượng pin tiêu thụ càng chính xác thì tốn pin nhiều hơn.

- Hiểu về thuộc tính "pausesLocationUpdatesAutomatically" được hỗ trợ từ iOS 6. Theo mình kiềm tra và test thì thằng này nó sẽ làm tắt location của bạn khi đang ở trạng thái background. Nhưng không biết nó có start lại không? Vì mình chưa có thời gian test. Ai biết về cái này nhiều xin comment ở dưới nha.

- Hiểu về thuộc tính "activityType" cái này mình chưa phân biệt được khi test ứng dụng. Apple nói có thể lấy location theo từng loại phương tiện hay cách thức bạn sử dụng. Ví dụ như bạn viết app dành cho viêc tập thể dục thì dùng loại CLActivityTypeFitness  , nếu bạn đi xe ô tô thì dùng loại CLActivityTypeAutomotiveNavigation,  .... Cái này chúng ta sẽ thảo luận sau khi mình có nhiều thời gian để test hơn.

Theo mình nghĩ thì lý thuyết chắc chỉ cần nhiêu đó là bạn có thể xử lý location 1 cách thuần thục rồi. Tiếp theo mình sẽ nói việc lấy location ở dưới background.

- Cách 1: Dùng significant-change location để lấy location ở trạng thái background: Cách này là cách tốt nhất để tiết kiệm pin cho user và có thể chạy location ở dưới background, nhưng mặt hạn chế của service này là mình không thể thiết lập việc lấy location theo thời gian hoặc khoảng cách di chuyển. Nếu muốn tối ưu pin cho user thì mình nghĩ vẫn dùng cách này là tối ưu nhất. Cách sử dụng service này thì cứ làm theo hướng dẫn trong trang hướng dẫn của Apple là được. Lưu ý theo mình nghĩ khi dùng service này các bạn nên thiết lập thuộc tính pausesLocationUpdatesAutomaticallyNo bởi vì có thể nó sẽ tự động huỷ service của bạn khi không cần thiết. Mình test cảm thấy như vậy tốt nhất không nên để hệ thống làm việc này cho mình để tránh bug tiềm tàng của hệ thống. 

- Cách 2: Là dùng standard location để lấy location: Cách này bạn có thể thiết lập những thông số bạn thích như lấy location theo thời gian, theo khoảng cách, theo loại phương tiện là gì.... Nếu lúc nào bạn cũng để service này chạy thì chắc chắn chạy được ở background, nhưng rất là tốn pin, không ai làm app như vậy cả. Khi bạn muốn dùng service này để lấy location thì nên chú ý những thuộc tính như: pausesLocationUpdatesAutomatically, activityTypeallowDeferredLocationUpdatesUntilTraveled:timeout:

Theo trước giờ mình làm thì khách hàng thường yêu cầu mình có thể viết location có thể chạy được ở dưới bacgkround theo thời gian hay theo khoảng cách di chuyển, mình xin phân tích ở dưới đây:
+ Nếu chạy location theo thời gian thì bạn cần phải để ý thời gian cho phép chạy những tác vụ trước khi hệ thống đưa xuống trạng thái background hoàn toàn. Thời gian cho phép trên iOS 5 và iOS 6 là 10 phút, nhưng iOS 7 thì chỉ có 3 phút. Vì thế trong khoảng thời gian này bạn phải gọi service location lên để đánh thức hệ thống chứ không nó rơi vào trạng thái background hoàn toàn thì ứng dụng của mình không thể chạy lại. Theo mình tìm hiểu trên mạng thì thời gian cho phép tối ưu trên iOS 7 là chỉ khoảng 1 phút thôi. Vì thế nếu chúng ta làm theo cách này thì cũng tốn pin lắm, cách này chỉ dùng cho những trường hợp khẩn cấp thôi. Hướng dẫn làm theo cách này các bạn có thể tham khảo tại đây.

*** Mình tìm ra cách có thể theo thời gian định kỳ có thể gởi location lên server được như thế này: Mình tham khảo hướng dẫn code ở trên và làm lại thử theo cách cứ 2 phút rưỡi (của ios 7, ios 6 thì có thể chỉnh cao hơn, có thể là 9 phút rưỡi) mình cho chạy location 1 lần và thiết lập giá trị tự động pause là No. Đúng theo thời gian setting như 5 phút, 15 phút, 30 phút, ... thì mình có thể chạy location theo đúng thời gian mong muốn để gởi lên server. -> Cách này đánh lừa hệ thống ios để ta có thể chạy suốt ở dưới background được. 

+ Nếu chạy location theo khoảng cách thì bạn nên chú ý thuộc tính pausesLocationUpdatesAutomaticallyNo. Theo Apple nói thì thuộc tính này kết hợp với activityType để có thể ngừng service khi không cần thiết. Nhưng theo mình test thì cảm giác nó bị ngừng hẳn chứ không được chạy lại. Vì thế tốt nhất chúng ta nên tắt nó đi, chứ không location của mình sẽ bị tắt khi xuống background. Làm cách này thì hơi tốn pin vì mình nghĩ có thể do lúc nào nó cũng chạy service nên mới tốn pin như vậy.

+ Theo mình nghĩ nếu bạn viết ứng dụng mà chạy trên xe ô tô hay tập thể dục bạn có thể kết hợp 2 thuộc tính pausesLocationUpdatesAutomaticallyactivityType để viết có thể chúng sẽ chạy được đó, cái này khi nào mình có thời gian sẽ test thử xem sao.     

+ Nếu bạn viết 1 ứng dụng cho chạy đến địa điểm nào đó thì tắt location để tiết kiệm pin thì nên dùng chức năng Deferring Location. Chức năng này mình chưa test thử nhưng thấy apple có ghi như vậy, ai có kinh nghiệm về cái này rồi thì share cho mọi người biết với nha.

+ Cách làm location chạy được ở background theo thời gian trên iOS 7.0: Theo mình xem log của 1 app làm chức năng theo dõi vị trí của user như Vismo. Mình để ý người ta có dùng significant-change location và cả remote notification để có thể gọi location theo thời gian được. Vì khi notification từ server trả về ta có thể gọi dịch vụ location để đánh thức system lại. Cách này cũng khá hay nhưng đòi hỏi app đó phải có internet thì mới làm dc.

Lưu ý:1 số app viết location chạy dưới background và phải gởi data lên server hay lưu xuống datbase thì nên để ý những library đó có hỗ trợ hay không nha, chứ không sẽ bị crash app. Ví dụ như connection bình thường thì có AFNetwork, nếu không dùng library thì bạn nên sử dụng NSOperationQueue để gọi connection. Còn nếu bạn dùng socket thì mình biết GCDAsyncSocket có thể hỗ trợ bạn. Database thì mình thấy có Core Database cũng hỗ trợ chạy dưới background, hướng dẫn tại đây hoặc tại thoughbot. Kinh nghiệm của mình chỉ cần tạo 2 NSManagedObjectContext là có thể làm được rồi. 
Ngoài ra khi đang chạy ở background bạn không nên cập nhật giao diện hay khởi tạo Alert vì hệ thống không cho phép ta làm việc đó, chúng ta nên có 1 đoạn kiểm tra những code như vậy ở background.






Comments

  1. Bài viết rất hay và bổ ích, cảm ơn bạn !

    ReplyDelete

Post a Comment

Popular posts from this blog

So sánh những framework hỗ trợ viết ứng dụng trên SmartPhone

Khi lập trình trên SmartPhone bạn không nhất thiết phải học những ngôn ngữ đặc thù trên từng loại hệ điều hành thì mới có thể lập trình được. Ví dụ như muốn lập trình trên iOS thì phải học ngôn ngữ Objective-C hay Swift, muốn lập trình được trên Android thì học ngôn ngữ Java, muốn lập trình trên WinPhone thì học ngôn ngữ C#. Hiện nay có rất nhiều những framework giúp đỡ cho các bạn rất nhiều khi các bạn muốn viết trên nhiều nền tảng smartphone bằng ngôn ngữ mà bạn yêu thích. Theo mình thấy thì hiện nay có 3 loại như: Native App, Hybrid Mobile App, Native Cross-Platform App. 1. Native App: là những ứng dụng sử dụng những framework và ngôn ngữ lập trình của hệ thống cung cấp sẵn. Ví dụ như bạn muốn lập trình iOS thì phải cài XCode, học ngôn ngữ Objective-C hay Swift, lập trình Android thì cài Android Studio và học ngôn ngữ Java. - Ưu điểm: Hiệu năng thực thi ứng dụng trên nền tảng nhanh và hiệu quả. Không bị phụ thuộc vào bên thứ 3. Khi phát hành ứng dụng trên những Mobile Store cũng dễ...

Phân biệt biến kiểu Property, Public, Protected, Private trong ngôn ngữ Objective C

- Theo kinh nghiệm làm việc của mình với các bạn trong nhóm khi lập trình Objective-C và cũng đọc qua code của những project cũ. Ít khi nào mọi người để ý và khai báo đúng với ý đồ của từng đối tượng, và vi phạm quy tắc tính đóng gói, tính bảo mật thông tin của đối tượng trong lập trình hướng đối tượng (Tham khảo lý thuyết Lập trình hướng đối tượng tại trang Wiki ). - Theo ngôn ngữ lập trình Java, người ta khuyến khích mỗi khi dùng biến kiểu public thì nên đặt 1 biến private và hỗ trợ những hàm getter/setter để truy suất biến private đó.     + Nguyên nhân họ nói là đảm bảo tính đóng gói, và nếu sau này có thay đổi gì trên biến đó bạn có thể sửa được dễ dàng, chi tiết về vấn đề này ở đây .     + Nói tóm tại thì nguyên nhân chính là có thể kiểm soát được truy xuất đến giá trị của 1 đối tượng từ bên ngoài, có thể dễ dàng mở rộng code bằng cách override lại những hàm getter/setter. - Các bạn có thể áp dụng nguyên tắc đó từ bên Java qua ngôn ngữ lập trình Object...

Hướng dẫn dùng Serverless sử dụng Lambda AWS

1. Lambda function là gì? AWS Lambda cho phép bạn chạy mã mà không cần cung cấp hay quản lý máy chủ. Bạn chỉ phải trả tiền cho thời gian xử lý thông tin đã sử dụng. Với Lambda, bạn có thể chạy mã cho gần như toàn bộ các loại ứng dụng hay dịch vụ backend – tất cả đều không cần quản trị. Chỉ cần tải đoạn mã của bạn lên và Lambda sẽ lo hết những gì cần làm để chạy và mở rộng mã của bạn với mức độ có sẵn cao. Bạn có thể thiết lập mã của bạn tự động kích hoạt từ các dịch vụ AWS khác, hoặc gọi trực tiếp từ bất cứ ứng dụng web hay di động nào. Chi phí chạy trên lambda function rẻ so với chi phí bạn mua 1 con server, duy trì và quản trị nó ( ví dụ như bạn phải xử lý bất đồng bộ những request, khi lượng user bạn tăng đột biến bạn phải có cơ chế auto scale, chứ không thì server bị sẽ bị treo, khi server bị treo bạn phải tự động khởi động lại sẽ mất thời gian,... ).