Liên kết dịch vụ với hoạt động trong Android


90

Tôi đang cố gắng viết một trình phát đa phương tiện đơn giản phát âm thanh trực tuyến bằng RTSP. Tôi có hoạt động GUI và dịch vụ thực hiện phát lại. Câu hỏi của tôi là làm thế nào để giao tiếp tốt nhất giữa hoạt động và dịch vụ (ví dụ: cập nhật GUI dựa trên trạng thái của trình phát).

Tôi biết rằng tôi có thể liên kết dịch vụ với hoạt động bằng cách sử dụng onBind (), nhưng nếu tôi hiểu chính xác, điều này sẽ dừng dịch vụ nếu hoạt động bị hủy. Tôi muốn tiếp tục phát lại ngay cả khi người dùng thoát khỏi hoạt động. Có bất kỳ tiêu chuẩn hoặc cách ưu tiên để giải quyết vấn đề này không?

Câu trả lời:


154

"Nếu bạn khởi động một Dịch vụ android với Dịch vụ startService(..)đó sẽ vẫn chạy cho đến khi bạn gọi một cách rõ ràng stopService(..). Có hai lý do khiến hệ thống có thể chạy một dịch vụ. Nếu ai đó gọi Context.startService()thì hệ thống sẽ truy xuất dịch vụ (tạo và gọi onCreate()phương thức của nó nếu cần thiết) và sau đó gọi onStartCommand(Intent, int, int)phương thức của nó với các đối số do máy khách cung cấp. Tại thời điểm này, dịch vụ sẽ tiếp tục chạy cho đến khi Context.stopService()hoặc stopSelf()được gọi. Lưu ý rằng nhiều lệnh gọi Context.startService()không lồng nhau (mặc dù chúng dẫn đến nhiều lệnh gọi tương ứng đến onStartCommand()), vì vậy không cho dù nó được khởi động bao nhiêu lần, một dịch vụ sẽ bị dừng một lần Context.stopService()hoặc stopSelf()được gọi; tuy nhiên, các dịch vụ có thể sử dụngstopSelf(int) phương pháp để đảm bảo dịch vụ không bị dừng cho đến khi các ý định bắt đầu được xử lý.

Khách hàng cũng có thể sử dụng Context.bindService()để có được kết nối liên tục với một dịch vụ. Điều này cũng tạo ra dịch vụ nếu nó chưa chạy (đang gọi onCreate()trong khi làm như vậy), nhưng không gọi onStartCommand(). Máy khách sẽ nhận IBinderđối tượng mà dịch vụ trả về từ onBind(Intent)phương thức của nó , cho phép máy khách sau đó thực hiện các cuộc gọi trở lại dịch vụ. Dịch vụ sẽ vẫn hoạt động miễn là kết nối được thiết lập (cho dù khách hàng có giữ lại tham chiếu trên Dịch vụ hay không IBinder). Thông thường, kết quả IBindertrả về dành cho một giao diện phức tạp đã được viết bằng AIDL.

Một dịch vụ có thể được khởi động và có các kết nối liên kết với nó. Trong trường hợp này, hệ thống sẽ giữ cho dịch vụ hoạt động miễn là nó được khởi động hoặc có một hoặc nhiều kết nối với nó với Context.BIND_AUTO_CREATEcờ. Khi cả hai tình huống này đều không xảy ra, onDestroy()phương thức của Dịch vụ được gọi và dịch vụ sẽ bị chấm dứt hiệu quả. Tất cả quá trình dọn dẹp (dừng luồng, hủy đăng ký bộ thu) phải hoàn tất khi quay trở lại onDestroy(). "


1
một chút nhầm lẫn: Có đúng là nếu hoạt động bị phá hủy thì dịch vụ cũng sẽ bị phá hủy? Hay dịch vụ đó không bị hủy chỉ khi tôi triển khai AIDL của riêng mình? Tôi đang hỏi vì khi tôi sử dụng startService (đặc biệt là IntentService), dịch vụ sẽ dừng khi công việc của nó được thực hiện trái ngược với khi hoạt động ngừng hoạt động. Vậy có đúng là nếu hoạt động chết, thì dịch vụ bị ràng buộc (độc quyền) cũng chết?
Katedral Pillon

1
nếu bạn đang sử dụng máy chủ đơn giản bằng cách gọi startService thì dịch vụ sẽ không dừng cho đến khi bạn gọi stopSelf () hoặc stopService (). Và tiếp theo nếu bạn sử dụng bindService thì dịch vụ có sẽ chết nếu tất cả thành phần kết nối / ràng buộc bị phá hủy.
Asif Mushtaq

1
@UnKnown Nếu dịch vụ được bắt đầu bằng startService () thì bất kể bạn ràng buộc hay hủy liên kết nó, nó sẽ tiếp tục chạy và chỉ có thể bị phá hủy bằng cách gọi stopService () hoặc stopSelf (). Vì vậy, ngay cả khi hoạt động được liên kết với dịch vụ bị hủy, dịch vụ sẽ không bị hủy.
CopsOnRoad

Bạn có thể vui lòng giúp tôi với câu hỏi này stackoverflow.com/questions/51508046/…
Rajesh K

25

Trước hết, 2 điều mà chúng ta cần hiểu

Khách hàng

  • nó yêu cầu máy chủ cụ thể

    bindService(new 
        Intent("com.android.vending.billing.InAppBillingService.BIND"),
            mServiceConn, Context.BIND_AUTO_CREATE);`

đây mServiceConnlà thể hiện của ServiceConnectionlớp (inbuilt) nó thực sự là giao diện mà chúng ta cần triển khai với hai phương thức (thứ nhất cho mạng được kết nối và thứ hai không được kết nối mạng) để theo dõi trạng thái kết nối mạng.

Người phục vụ

  • Nó xử lý yêu cầu của máy khách và tạo bản sao của chính nó, riêng tư đối với khách hàng chỉ gửi yêu cầu và bản sao của máy chủ này chạy trên chuỗi khác.

Bây giờ ở phía máy khách, làm thế nào để truy cập tất cả các phương thức của máy chủ?

  • máy chủ gửi phản hồi với IBind Object. Vì vậy, đối tượng IBind là trình xử lý của chúng tôi, nó truy cập tất cả các phương thức của dịch vụ bằng cách sử dụng toán tử (.).

    MyService myService;
    public ServiceConnection myConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder binder) {
            Log.d("ServiceConnection","connected");
            myService = binder;
        }
        //binder comes from server to communicate with method's of 
    
        public void onServiceDisconnected(ComponentName className) {
            Log.d("ServiceConnection","disconnected");
            myService = null;
        }
    }

bây giờ làm thế nào để gọi phương thức nằm trong dịch vụ

myservice.serviceMethod();

đây myServicelà đối tượng và serviceMethodelà phương thức trong dịch vụ. Và bằng cách này, giao tiếp được thiết lập giữa máy khách và máy chủ.


10

tôi đã cố gọi

startService(oIntent);
bindService(oIntent, mConnection, Context.BIND_AUTO_CREATE);

do đó và tôi có thể tạo một dịch vụ cố định và liên kết với nó. Hướng dẫn chi tiết cho Ví dụ về dịch vụ ràng buộc .


5

Có một phương thức gọi là unbindService sẽ sử dụng ServiceConnection mà bạn sẽ tạo khi gọi bindService. Điều này sẽ cho phép bạn ngắt kết nối khỏi dịch vụ trong khi vẫn để nó chạy.

Điều này có thể gây ra sự cố khi bạn kết nối lại với nó, vì bạn có thể không biết liệu nó có đang chạy hay không khi bạn bắt đầu lại hoạt động, vì vậy bạn sẽ phải xem xét điều đó trong mã hoạt động của mình.

Chúc may mắn!


-1

Đây là một câu trả lời thiên vị, nhưng tôi đã viết một thư viện có thể đơn giản hóa việc sử dụng các Dịch vụ Android, nếu chúng chạy cục bộ trong cùng một quy trình với ứng dụng: https://github.com/germnix/acacia

Về cơ bản, bạn xác định một giao diện được chú thích bằng @Service và lớp triển khai của nó, và thư viện tạo và liên kết dịch vụ, xử lý kết nối và luồng công nhân nền:

@Service(ServiceImpl.class)
public interface MyService {
    void doProcessing(Foo aComplexParam);
}

public class ServiceImpl implements MyService {
    // your implementation
}

MyService service = Acacia.createService(context, MyService.class);
service.doProcessing(foo);

<application
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">
    ...
    <service android:name="com.gmr.acacia.AcaciaService"/>
    ...
</application>

Bạn có thể lấy một phiên bản của android.app.Service được liên kết để ẩn / hiển thị các thông báo liên tục, sử dụng android.app.Service của riêng bạn và xử lý luồng thủ công nếu bạn muốn.


-5

Nếu người dùng lùi lại, onDestroy()phương thức sẽ được gọi. Phương pháp này là để dừng bất kỳ dịch vụ nào được sử dụng trong ứng dụng. Vì vậy, nếu bạn muốn tiếp tục dịch vụ ngay cả khi người dùng lùi ứng dụng, chỉ cần xóa onDestroy(). Hy vọng điều này giúp đỡ.


Bạn sẽ phải ghi đè hàm và xóa lệnh gọi mặc định đến onDestroy () của lớp cha nếu IDE của bạn tự động tạo một. nhưng tại sao bạn lại muốn làm điều này?
Riptyde 4
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.