2012-06-27 34 views
5

Tôi đang chạy một dịch vụ trong nền mà đọc GPS/Vị trí mạng và cần phải làm như sau:Dịch vụ Android và nhiệm vụ lặp đi lặp lại chạy trong chủ đề

  • chạy ở chế độ nền mà không bị gián đoạn trên ứng dụng khởi động lại và giữ nó sống càng nhiều càng tốt mà không bị giết chết (Điều này được giải quyết với sự giúp đỡ của Merlin của bình luận dưới đây)

  • trên một vị trí mới nhận được, gọi một dịch vụ web và gửi vị trí đọc

  • có một repeti nhiệm vụ bổ sung chạy mỗi 60 giây và gửi lại vị trí cuối cùng đến dịch vụ web. Điều này sẽ giúp trong trường hợp người dùng ở trong cùng một vị trí.

Có một vài điều tôi đã xem xét và tôi không chắc liệu tôi có hiểu đúng hay không. Dịch vụ này chạy trong cùng một luồng với ứng dụng chính, vì vậy việc gửi vị trí đến máy chủ trên cùng một luồng vì chuỗi giao diện người dùng có thể kích hoạt giao diện người dùng bị đóng băng và điều này không tốt. Ngoài ra tôi không chắc chắn nếu người nghe GPS/Mạng có chủ đề riêng của họ hoặc sử dụng các chủ đề tương tự như các ứng dụng.

Đây là một mã số rút gọn của dịch vụ để làm cho mọi việc rõ ràng hơn:

public class GPSLoggerService extends Service { 
@Override 
public void onCreate() { 
    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 
} 

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 

    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 50, locationListenerNetwork); 
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 50, locationListenerGps); 

    scheduleTaskExecutor = Executors.newScheduledThreadPool(5); 
    scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() { 
     @Override 
     public void run() { 
       updateLocation(lastLocation); 
     }, 60, 60, TimeUnit.SECONDS); 

    return START_STICKY; 
} 

LocationListener locationListenerGps = new LocationListener() { 
    @Override 
    public void onLocationChanged(Location location) { 
     updateLocation(location); 
    } 
... 
}  

LocationListener locationListenerNetwork = new LocationListener() { 
    @Override 
    public void onLocationChanged(Location location) { 
     updateLocation(location); 
    } 
... 
} 

private void updateLocation(Location readLocation) { 
    //web service call 
    String response = WebServiceCalls.updateLocation(readLocation); 

    //log data in a local Sqlite database 
    saveLocation(readLocation) 
} 

mối quan tâm chính của tôi là làm thế nào để xử lý các cuộc gọi updateLocation và có nó trong một thread riêng biệt từ các chủ đề ứng dụng chính. ScheduleTaskExecutor Tôi tin rằng đó không phải là cách để đi. Đôi khi, ngay cả sau khi tôi gọi stopService() dịch vụ vẫn còn sống, ngay cả khi tôi nói với TaskExecutor để shutDown. Tôi không thể tìm thấy lời giải thích khác cho dịch vụ không dừng lại. Vì vậy, để tóm tắt: Tôi cần phải gửi vị trí mỗi khi người nghe nhận được một vị trí mới và gửi lại nó mỗi 60 giây. Tôi cũng cần có khả năng dừng dịch vụ nhanh chóng với các chủ đề đang hoạt động bị hủy.

Bạn đề nghị tôi xử lý trường hợp của tôi như thế nào?

+0

bạn cần để bắt đầu nó dính? – Merlin

Trả lời

0

Để ngăn chặn dịch vụ của bạn phá hủy, bạn có thể bắt đầu dịch vụ của mình với tư cách là foreground service.

Và sau khi nhận được vị trí từ phương thức onLocationChanged(), bạn có thể sử dụng asynctask để gửi vị trí tới webservice để nó không chặn giao diện người dùng của bạn.

Sửa

  1. Bạn có thể thiết lập thời gian tối thiểu và khoảng cách tối thiểu đi trong requestLocationUpdates bạn phương pháp. Vì vậy, tôi không nghĩ bạn nên sử dụng tác vụ lên lịch để gửi vị trí đến máy chủ. Theo các đối số về thời gian min và min khoảng cách người quản lý vị trí sẽ kiểm tra vị trí.Nếu có một vị trí thay đổi thì nó sẽ gọi phương thức onLocationChanged() với vị trí mới. Bây giờ, giải pháp của bạn về việc người dùng ở cùng một vị trí. bạn có thể thay đổi một số logic sang phía máy chủ như nếu có sự khác biệt 1 giờ giữa hai vị trí kế tiếp location1 và location2 có nghĩa là người dùng đã ở lại 1 giờ tại location1.

  2. Bạn có thể sử dụng một lớp LocationListener duy nhất để nghe vị trí GPS và NETWORK.

  3. Khi bạn nhận được vị trí trong phương thức onLocationChanged(), bạn có thể gửi vị trí đó bằng cách sử dụng asynctask.
  4. Sau khi nhận được vị trí, bạn có thể lưu vị trí đó trong tùy chọn hoặc cơ sở dữ liệu để kiểm tra thời tiết GPS và nhà cung cấp mạng gửi cho bạn cùng một vị trí, vì vậy nếu bạn theo dõi thì bạn có thể lưu cuộc gọi webAPI của mình và để bạn có thể lưu một số phần ắc quy.
+0

Như bạn có thể thấy có đọc từ cả gps và mạng và cũng gửi đúng tiến độ. Điều này có nghĩa là tôi sẽ có 3 cuộc gọi cho asynctask cùng một lúc. Làm thế nào tôi sẽ hủy bỏ chúng? – Alin

+0

Tôi phải gửi vị trí ngay cả khi người lái xe ở cùng vị trí vì đây là một phần của thông số kỹ thuật của dự án. Vì vậy, tôi không thể thay đổi điều này. Tuy nhiên tôi không thấy asynctask như một giải pháp tốt cho trường hợp của tôi. Hãy tưởng tượng tôi có thể nhận được vị trí mới sau mỗi 1 giây nếu người dùng đang lái xe xung quanh. Điều này có nghĩa cứ sau 1 giây tôi phải kích hoạt asynctask vì vậy tôi có thể có 2-3 tác vụ đang chạy ... Làm thế nào tôi có thể hủy bỏ chúng khi dịch vụ dừng lại? – Alin

+0

Chỉ cần nghĩ về trường hợp bạn muốn gửi vị trí cứ sau 1 giây. Bạn muốn xử lý cuộc gọi webAPI của bạn cứ sau 1 giây (không phải mọi lần nhưng trong trường hợp thay đổi vị trí liên tiếp). Nếu bạn hủy cái cuối cùng và nếu bạn cập nhật cái mới thì việc hủy bỏ vị trí cuối cùng sẽ bị bỏ qua. – Dharmendra

4

Tôi muốn sử dụng IntentService và chỉ sử dụng AlarmManager để kích hoạt các ý định.

Ưu điểm lớn của việc này là không có mã đề phải lo lắng vì nó làm công việc của mình trong nền

CẬP NHẬT

Một cách tiếp cận thú vị có thể được tìm thấy trong https://stackoverflow.com/a/7709140/808940

+0

Còn cuộc gọi onLocationChanged thì sao? Liệu nó có chủ đề riêng của mình hoặc bắn một IntentService inthere quá? Tôi cũng cần biết liệu cuộc gọi tới trang web có thành công hay không. Điều này một phần tôi không nghĩ rằng nó sẽ được dễ dàng để thực hiện với một IntentService. Tôi tin rằng phải có một phát sóng gửi đi, phải không? – Alin

2
  • Dịch vụ chạy cùng quy trình với ứng dụng chính chứ không phải chuỗi. Ngoài ra, nếu bạn muốn chạy dịch vụ trong một quy trình khác, thì bạn có thể sử dụng thẻ android:process.

  • Tôi không chắc chắn lý do tại sao bạn muốn gọi WebService cứ sau 60 giây, vì 60 giây quá ít. Ngoài ra, bạn nên bỏ qua gọi WebService khi vị trí không thay đổi, bởi vì nó đòi hỏi một giao tiếp mạng và nó là một hoạt động tốn kém.

  • Không cần sử dụng Executors. Bạn nên giữ số lượng các chủ đề càng ít càng tốt. Để thực hiện một nhiệm vụ tại một khoảng thời gian cụ thể, sử dụng AlarmManager để cung cấp ý định tại một thời điểm cụ thể. Kiểm tra phương thức setRepeating() để cài đặt báo thức.

  • Một điều khác là, bạn nên cố gắng tránh thực hiện bất kỳ tác vụ nào trong Trình nghe. Bởi vì có một timeout trong 10 giây mà hệ thống cho phép trước khi xem xét người nhận/người nghe bị chặn và một ứng cử viên bị giết. Bạn nên sử dụng Handler để thực hiện các tác vụ trong chuỗi nền (tức là bất cứ khi nào bạn nhận được bản cập nhật từ người nghe, hãy thêm thông báo vào hàng đợi Trình xử lý và nó sẽ được chọn khi chuỗi trình xử lý miễn phí).

-1

Bạn nên sử dụng AsynchTask:

public class RefreshTask extends AsyncTask<Integer, Void, Integer> { 



    /** 
    * The system calls this to perform work in a worker thread and delivers 
    * it the parameters given to AsyncTask.execute() 
    */ 

    public RefreshTask() { 

    } 

    protected Integer doInBackground(Integer... millis) { 
     try{ 
      int waitTime = 0; 
      while(waitTime<60000){ 
       Thread.sleep(100); 
       waitTime += 100; 
      } 

      //update location here 

     }catch(InterruptedException e){ 

     } 



     return 1; 
    } 

    /** 
    * The system calls this to perform work in the UI thread and delivers 
    * the result from doInBackground() 
    */ 
    protected void onPostExecute(Integer result) { 
     new RefreshTask.execute(); 
    } 


} 
+0

Không sử dụng 'AsyncTask' cho loại sự cố này. Tùy thuộc vào phiên bản API, điều này sẽ chặn tất cả các AsyncTask khác. – chrulri

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