2011-08-31 25 views
14

Tôi có dịch vụ nền đôi khi bị hệ điều hành giết khi bộ nhớ sắp hết bộ nhớ.Cách khởi động lại dịch vụ?

  1. Làm cách nào để mô phỏng hành vi này để tôi có thể gỡ lỗi?

Hướng dẫn dev chỉ nói "nếu dịch vụ của bạn được bắt đầu, thì bạn phải thiết kế để xử lý khởi động một cách duyên dáng bởi hệ thống. Nếu hệ thống ngừng hoạt động, hệ thống sẽ khởi động lại ngay khi tài nguyên trở lại".

  1. Chuỗi các cuộc gọi từ khi nó bị giết khi kết thúc khởi động lại là gì?

Câu hỏi phụ, điều gì xảy ra với AsyncTask đang hoạt động bắt đầu trong dịch vụ khi dịch vụ bị hệ điều hành giết, tức là không có dịch vụ.onDestroy được gọi? Liệu nó có tiếp tục chạy hoặc bị xé âm thầm cùng với dịch vụ không?

Trả lời

6

Theo các phiên bản mới hơn, một dịch vụ sẽ có những sự kiện sau đây gây ra:

onCreate() 

Tiếp theo là ...

int onStartCommand(Intent intent, int flags, int startid) 

tôi biết trong các ý kiến ​​ở trên bạn đề cập đến sử dụng đó, nhưng nó có giá trị lặp lại: Không sử dụng sự kiện "onStart()" cũ. onStartCommand là cách làm mới.

onCreate() có thể được sử dụng để tạo bất kỳ đối tượng nào, v.v ... nhưng thực sự mã dịch vụ của bạn trong onStartCommand().

Khi hoàn tất với onStartCommand(), bạn nên trả lại kết quả. Sử dụng "START_STICKY" cho hệ điều hành biết nó có thể khởi động lại nếu nó cần phải giết nó. Sử dụng "START_NOT_STICKY" yêu cầu hệ điều hành không bận tâm cố gắng khởi động lại sau khi bộ nhớ có sẵn trở lại. Điều đó có nghĩa là ứng dụng của bạn sẽ cần phải khởi động lại dịch vụ theo cách thủ công. Cũng có các tùy chọn khác - kiểm tra tài liệu API.

Kiểm tra các cờ đó sẽ cho phép bạn xem lý do dịch vụ của bạn đã bắt đầu - nếu ứng dụng của riêng bạn khởi chạy ứng dụng hoặc nếu hệ điều hành khởi chạy ứng dụng để khởi động lại. Bạn sẽ cần định kỳ lưu trữ trạng thái của bất kỳ biến quan trọng nào để nếu hệ điều hành đã khởi động lại nó, bạn có thể truy xuất chúng - bạn có thể sử dụng bộ nhớ riêng SharedPreferences để lưu trữ chúng. Chắc chắn lưu trữ bất kỳ sự kiện nào trong sự kiện onDestroy, nhưng không được tính vào sự kiện được gọi.

Ngoài ra, bạn nên lưu trữ trường startID trong một biến và sử dụng nó với stopSelfResult (startId) khi dịch vụ của bạn được thực hiện xong.

Hãy nhớ rằng nếu dịch vụ của bạn bị hệ điều hành giết chết, bạn có thể không có cơ hội lưu trữ bất kỳ biến nào. Bạn cần có thể biết trạng thái của bạn là nơi bạn mong đợi khi hệ điều hành khởi động lại và nếu không chỉ cần thiết lập lại mọi thứ hoặc có thể chết một cách duyên dáng.

Theo như gỡ lỗi, bạn đã cân nhắc viết một ứng dụng khác không làm gì ngoài việc hút bộ nhớ trong một Hoạt động để buộc điều kiện bộ nhớ thấp? Hoạt động hàng đầu nên được ưu tiên cho bộ nhớ và buộc dịch vụ phải chết.

Các chủ đề bổ sung được khởi chạy trong dịch vụ vẫn là một phần của cùng một quy trình đăng ký, để chúng có thể bị xóa cùng với dịch vụ (và phần còn lại của ứng dụng.) Bạn có thể xác minh điều này bằng cách thêm các câu lệnh log thông thường bên trong chủ đề và sau đó giết chết dịch vụ.

Điều gì đó có thể hữu ích cho bạn đang kiểm tra xem dịch vụ của bạn đã chạy từ bên trong ứng dụng chưa. Dưới đây là một chức năng để làm điều đó:

// Determine if one of my services is currently running 
public static boolean isMyServiceRunning(Context context, String servicename) { 
    ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { 
     if (servicename.equals(service.service.getClassName())) { 
      return true; 
     } 
    } 
    return false; 
} 
+0

Kết thúc trong DDMS (như yjw đã đề cập) sẽ cho tôi hành vi khởi động lại. Và cảm ơn lời giải thích kỹ lưỡng. –

+0

Mẹo hay về DDMS và không có vấn đề gì về giải thích. Nó chỉ xảy ra rằng tôi đã đi qua gần như cùng một vấn đề viết một ứng dụng quét mã vạch đã làm tất cả các công việc như một dịch vụ để màn hình sẽ không cần phải được trên. –

3

Nếu đó là Dịch vụ cục bộ (mặc định), trái ngược với Dịch vụ từ xa thì nó đang chạy trong cùng một quá trình với ứng dụng của bạn. Điều này có nghĩa là bạn có thể mô phỏng giết chết nó bằng cách giết chết quá trình của ứng dụng của bạn. Bạn có thể làm điều đó bằng cách sử dụng ddms ví dụ trong nhật thực hoặc từ dòng lệnh, hoặc thậm chí từ điện thoại của bạn (cài đặt -> ứng dụng).

+1

Tôi có thể thực hiện việc giết nhưng không có khởi động lại được liên kết với nó. –

+0

kiểm tra giá trị bạn trả về từ dịch vụ onStartCommand của Dịch vụ. Tôi nghĩ rằng đây là một trong những bạn muốn: http://developer.android.com/reference/android/app/Service.html#START_STICKY – Erdal

+0

Vâng đó là những gì tôi đang sử dụng. Vấn đề chính của tôi là tôi không có ý tưởng làm thế nào để mô phỏng hành vi giết chết-khởi động lại dịch vụ Android. –