Cách để Dịch vụ Android liên lạc với Hoạt động


251

Tôi đang viết ứng dụng Android đầu tiên của mình và cố gắng tập trung vào giao tiếp giữa các dịch vụ và hoạt động. Tôi có một Dịch vụ sẽ chạy trong nền và thực hiện ghi nhật ký dựa trên gps và thời gian. Tôi sẽ có một Hoạt động sẽ được sử dụng để bắt đầu và dừng Dịch vụ.

Vì vậy, trước tiên, tôi cần có khả năng tìm hiểu xem Dịch vụ có chạy khi Hoạt động được bắt đầu hay không. Có một số câu hỏi khác ở đây về điều đó, vì vậy tôi nghĩ rằng tôi có thể tìm ra điều đó (nhưng hãy thoải mái đưa ra lời khuyên).

Vấn đề thực sự của tôi: nếu Hoạt động đang chạy và Dịch vụ được khởi động, tôi cần một cách để Dịch vụ gửi tin nhắn đến Hoạt động. Chuỗi đơn giản và số nguyên tại thời điểm này - chủ yếu là thông điệp trạng thái. Các tin nhắn sẽ không xảy ra thường xuyên, vì vậy tôi không nghĩ rằng bỏ phiếu dịch vụ là một cách tốt để đi nếu có một cách khác. Tôi chỉ muốn giao tiếp này khi Người dùng đã bắt đầu Hoạt động - Tôi không muốn bắt đầu Hoạt động từ Dịch vụ. Nói cách khác, nếu bạn bắt đầu Hoạt động và Dịch vụ đang chạy, bạn sẽ thấy một số thông báo trạng thái trong Giao diện người dùng hoạt động khi có điều gì đó thú vị xảy ra. Nếu bạn không bắt đầu Hoạt động, bạn sẽ không thấy những tin nhắn này (chúng không thú vị lắm).

Có vẻ như tôi sẽ có thể xác định xem Dịch vụ có đang chạy hay không và nếu có, hãy thêm Hoạt động làm người nghe. Sau đó xóa Hoạt động dưới dạng người nghe khi Hoạt động tạm dừng hoặc dừng. Điều đó có thực sự khả thi không? Cách duy nhất tôi có thể tìm ra để làm điều đó là để Activity thực hiện Parcelable và xây dựng tệp AIDL để tôi có thể chuyển nó qua giao diện từ xa của Dịch vụ. Điều đó có vẻ như quá mức cần thiết và tôi không biết Activity nên triển khai writeToParcel () / readFromParcel () như thế nào.

Có cách nào dễ hơn hay tốt hơn không? Cảm ơn vì bất kì sự giúp đỡ.

BIÊN TẬP:

Đối với bất kỳ ai quan tâm đến vấn đề này sau này, có mã mẫu từ Google để xử lý việc này thông qua AIDL trong thư mục mẫu: /apis/app/RemoteService.java

Câu trả lời:


94

Có ba cách rõ ràng để giao tiếp với các dịch vụ:

  1. Sử dụng ý định
  2. Sử dụng AIDL
  3. Sử dụng chính đối tượng dịch vụ (dưới dạng singleton)

Trong trường hợp của bạn, tôi sẽ sử dụng tùy chọn 3. Tạo một tham chiếu tĩnh cho dịch vụ mà nó tự cung cấp và điền nó vào onCreate ():

void onCreate(Intent i) {
  sInstance = this;
}

Tạo một hàm tĩnh MyService getInstance(), trả về tĩnh sInstance.

Sau đó, khi Activity.onCreate()bạn bắt đầu dịch vụ, hãy chờ một cách không đồng bộ cho đến khi dịch vụ thực sự bắt đầu (bạn có thể yêu cầu dịch vụ của bạn thông báo cho ứng dụng của bạn, nó đã sẵn sàng bằng cách gửi một ý định đến hoạt động.) Và lấy ví dụ của nó. Khi bạn có thể hiện, hãy đăng ký đối tượng người nghe dịch vụ của bạn cho dịch vụ của bạn và bạn đã được đặt. LƯU Ý: khi chỉnh sửa Chế độ xem bên trong Hoạt động, bạn nên sửa đổi chúng trong luồng UI, dịch vụ có thể sẽ chạy Chủ đề của chính nó, vì vậy bạn cần gọi Activity.runOnUiThread().

Điều cuối cùng bạn cần làm là xóa tham chiếu đến đối tượng người nghe của bạn Activity.onPause(), nếu không, một trường hợp bối cảnh hoạt động của bạn sẽ bị rò rỉ, không tốt.

LƯU Ý: Phương pháp này chỉ hữu ích khi ứng dụng / Hoạt động / tác vụ của bạn là quá trình duy nhất sẽ truy cập dịch vụ của bạn. Nếu đây không phải là trường hợp bạn phải sử dụng tùy chọn 1. hoặc 2.


2
Làm thế nào tôi có thể busy-waithoạt động? Bạn có thể giải thích được không ?
iTurki

1
Vì vậy, sau khi onCreate hoặc sau onStartCommand trong lớp dịch vụ của bạn đặt một biến tĩnh công khai, hãy gọi nó là Kết nối hoặc một cái gì đó thành đúng. Sau đó, trong Hoạt động của bạn thực hiện việc này: Ý định = Ý định mới (hành động, YourService. Class); startService (ý định); while (! YourService.isConnected) {ngủ (300); } Sau vòng lặp đó, dịch vụ của bạn đang chạy và bạn có thể liên lạc với nó .. Theo kinh nghiệm của tôi, chắc chắn có một số hạn chế khi tương tác với một dịch vụ như thế này.
Matt Wolfe

Tại sao nó chỉ có thể được bắt đầu trong Activity.onCreate()?
skywall

Bất kỳ từ nào về lý do tại sao bạn không muốn sử dụng Intentsbằng cách gửi dữ liệu qua Parcellabletin nhắn giữa chúng?
Aman Alam

2
Điều này hoạt động, nhưng câu trả lời của @ MaximumGoat sạch hơn nhiều và không liên quan đến bất kỳ sự chờ đợi bận rộn nào.
Matt

262

Người hỏi có lẽ đã chuyển qua điều này từ lâu, nhưng trong trường hợp người khác tìm kiếm ...

Có một cách khác để xử lý việc này, mà tôi nghĩ có thể là đơn giản nhất.

Thêm một BroadcastReceivervào hoạt động của bạn. Đăng ký nó để nhận được một số ý định tùy chỉnh onResumevà hủy đăng ký nó onPause. Sau đó gửi ý định đó từ dịch vụ của bạn khi bạn muốn gửi thông tin cập nhật trạng thái của bạn hoặc những gì có bạn.

Hãy chắc chắn rằng bạn sẽ không vui nếu một số ứng dụng khác lắng nghe Intent(mọi người có thể làm gì độc hại không?), Nhưng ngoài điều đó, bạn sẽ ổn thôi.

Mẫu mã đã được yêu cầu:

Trong dịch vụ của tôi, tôi có điều này:

// Do stuff that alters the content of my local SQLite Database
sendBroadcast(new Intent(RefreshTask.REFRESH_DATA_INTENT));

( RefreshTask.REFRESH_DATA_INTENTchỉ là một chuỗi không đổi.)

Trong hoạt động nghe của tôi, tôi xác định BroadcastReceiver:

private class DataUpdateReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(RefreshTask.REFRESH_DATA_INTENT)) {
          // Do stuff - maybe update my view based on the changed DB contents
        }
    }
}

Tôi tuyên bố người nhận của tôi ở đầu lớp:

private DataUpdateReceiver dataUpdateReceiver;

Tôi ghi đè onResume để thêm điều này:

if (dataUpdateReceiver == null) dataUpdateReceiver = new DataUpdateReceiver();
IntentFilter intentFilter = new IntentFilter(RefreshTask.REFRESH_DATA_INTENT);
registerReceiver(dataUpdateReceiver, intentFilter);

Và tôi ghi đè onPause để thêm:

if (dataUpdateReceiver != null) unregisterReceiver(dataUpdateReceiver);

Bây giờ hoạt động của tôi đang lắng nghe dịch vụ của tôi nói "Này, hãy tự cập nhật." Tôi có thể truyền dữ liệu Intentthay vì cập nhật các bảng cơ sở dữ liệu và sau đó quay lại để tìm các thay đổi trong hoạt động của mình, nhưng vì tôi muốn các thay đổi vẫn tiếp tục, nên việc truyền dữ liệu qua DB là điều hợp lý.


5
Làm sao? Những gì bạn mô tả là chính xác những gì tôi cần. Nhưng hơn thế, tôi cần mã mẫu hoàn chỉnh. Cảm ơn trước. FYI, lần cuối cùng tôi cố gắng viết một widget, phần nhắn tin đã khiến tôi mất 2 tháng. Cười nếu bạn muốn, nhưng các chuyên gia của bạn cần xuất bản nhiều hơn vì IMHO Android phức tạp hơn iOS!

1
aaaaaaa, Hướng dẫn bận rộn về phát triển Android nâng cao có một chương tuyệt vời về các widget. Đó là nguồn tài nguyên duy nhất giúp tôi vượt qua mớ hỗn độn đó. CommonsWare, tác giả, có danh tiếng 115k trên StackOverflow, và tôi đánh giá cao cuốn sách này. commonsware.com/AdvAndroid
MaximumGoat

64
Broadcastslà tuyệt vời và ngoài nếu bạn không muốn quảng bá của bạn để vượt qua quá trình riêng của bạn sau đó xem xét việc sử dụng một LocalBroadcast: developer.android.com/reference/android/support/v4/content/...
Cody Caughlan

2
Cảm ơn Cody, tôi đã không nhìn thấy điều đó trước đây.
MaximumGoat

3
Đây là cách giao tiếp rất tốt. Nhưng phải làm gì trong trường hợp kết quả được gửi, khi hoạt động ở trạng thái tạm dừng? Vì vậy, sau khi hoạt động onResume có thể chờ đợi một thời gian dài cho kết quả. Và không có dữ liệu sẽ được nhận, bởi vì dữ liệu đã bị bỏ lỡ.
Anton-M

39

Sử dụng LocalBroadcastManagerđể đăng ký người nhận để nghe phát sóng được gửi từ dịch vụ địa phương trong ứng dụng của bạn, tham khảo tại đây:

http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html


3
Vâng, một cuộc thảo luận rất tốt đẹp về localbroadcast đây liên kết
SohailAziz

1
LocalBroadcastManagerhiện không được ủng hộ LiveDatahoặc ủng hộ hoặc các công cụ mô hình quan sát viên khác: developer.android.com/reference/androidx/localbroadcastmanager/
Kẻ

20

Tôi ngạc nhiên khi không ai đưa ra tài liệu tham khảo về thư viện xe buýt sự kiện Otto

http://sapes.github.io/otto/

Tôi đã sử dụng điều này trong các ứng dụng Android của tôi và nó hoạt động trơn tru.


7
Ngoài ra, có thư viện EventBus của greenrobot .
Jazzer

15
Nhưng hãy nhớ rằng EventBus và otto luôn trong một quy trình. Khi bạn đang sử dụng một dịch vụ theo quy trình riêng của mình (bắt đầu bằng việc cài đặt dịch vụ android:process=":my_service"mà họ không thể liên lạc.
Ron

20

Sử dụng Messenger là một cách đơn giản khác để liên lạc giữa Dịch vụ và Hoạt động.

Trong Hoạt động, tạo Trình xử lý với Messenger tương ứng. Điều này sẽ xử lý tin nhắn từ Dịch vụ của bạn.

class ResponseHandler extends Handler {
    @Override public void handleMessage(Message message) {
            Toast.makeText(this, "message from service",
                    Toast.LENGTH_SHORT).show();
    }
}
Messenger messenger = new Messenger(new ResponseHandler());

Messenger có thể được chuyển đến dịch vụ bằng cách đính kèm nó vào Tin nhắn:

Message message = Message.obtain(null, MyService.ADD_RESPONSE_HANDLER);
message.replyTo = messenger;
try {
    myService.send(message);
catch (RemoteException e) {
    e.printStackTrace();
}

Một ví dụ đầy đủ có thể được tìm thấy trong các bản trình diễn API: MessengerService và MessengerServiceActivity . Tham khảo ví dụ đầy đủ để biết MyService hoạt động như thế nào.


1
Nhiều đánh giá cao! Hoạt động hoàn hảo. Chỉ là một chi tiết trong mã: myService.send(message);nên được messenger.send(message);thay thế.
Federico Cristina

9

Phương thức khác không được đề cập trong các nhận xét khác là liên kết với dịch vụ từ hoạt động bằng bindService () và lấy một phiên bản của dịch vụ trong cuộc gọi lại ServiceConnection. Như được mô tả ở đây http://developer.android.com/guide/components/bound-service.html


4
Đây là cách đúng để có được tham chiếu của thể hiện dịch vụ.
김준호

9

Bạn cũng có thể sử dụng LiveDatahoạt động như một EventBus.

class MyService : LifecycleService() {
    companion object {
        var BUS = MutableLiveData<Object>()
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        super.onStartCommand(intent, flags, startId)

        val testItem : Object

        // expose your data
        if (BUS.hasActiveObservers()) {
            BUS.postValue(testItem)
        }

        return START_NOT_STICKY
    }
}

Sau đó thêm một người quan sát từ của bạn Activity.

MyService.BUS.observe(this, Observer {
    it?.let {
        // Do what you need to do here
    }
})

Bạn có thể đọc thêm từ blog này .


2

Một cách khác có thể là sử dụng các trình quan sát với lớp mô hình giả thông qua hoạt động và chính dịch vụ, thực hiện một biến thể mô hình MVC. Tôi không biết đó có phải là cách tốt nhất để thực hiện điều này không, nhưng đó là cách làm việc với tôi. Nếu bạn cần một số ví dụ yêu cầu và tôi sẽ đăng một cái gì đó.


Tôi đang vật lộn với suy nghĩ tương tự. Tôi có hoạt động và 2 dịch vụ có cùng Mô hình. Mô hình có thể được cập nhật trong bất kỳ hoạt động hoặc bất kỳ dịch vụ nào vì vậy tôi nghĩ về việc sử dụng Trình quan sát bằng cách nào đó nhưng không thể tìm ra. Bạn có thể gửi ví dụ để hiển thị ý tưởng của bạn?
pzo

2

Phương pháp của tôi:

Lớp để quản lý gửi và nhận tin nhắn từ / đến dịch vụ / hoạt động:

import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

public class MessageManager {

    public interface IOnHandleMessage{
        // Messages
        int MSG_HANDSHAKE = 0x1;

        void onHandleMessage(Message msg);
    }

    private static final String LOGCAT = MessageManager.class.getSimpleName();

    private Messenger mMsgSender;
    private Messenger mMsgReceiver;
    private List<Message> mMessages;

    public MessageManager(IOnHandleMessage callback, IBinder target){
        mMsgReceiver = new Messenger(new MessageHandler(callback, MessageHandler.TYPE_ACTIVITY));
        mMsgSender = new Messenger(target);
        mMessages = new ArrayList<>();
    }

    public MessageManager(IOnHandleMessage callback){
        mMsgReceiver = new Messenger(new MessageHandler(callback, MessageHandler.TYPE_SERVICE));
        mMsgSender = null;
        mMessages = new ArrayList<>();
    }

    /* START Getter & Setter Methods */
    public Messenger getMsgSender() {
        return mMsgSender;
    }

    public void setMsgSender(Messenger sender) {
        this.mMsgSender = sender;
    }

    public Messenger getMsgReceiver() {
        return mMsgReceiver;
    }

    public void setMsgReceiver(Messenger receiver) {
        this.mMsgReceiver = receiver;
    }

    public List<Message> getLastMessages() {
        return mMessages;
    }

    public void addMessage(Message message) {
        this.mMessages.add(message);
    }
    /* END Getter & Setter Methods */

    /* START Public Methods */
    public void sendMessage(int what, int arg1, int arg2, Bundle msgData){
        if(mMsgSender != null && mMsgReceiver != null) {
            try {
                Message msg = Message.obtain(null, what, arg1, arg2);
                msg.replyTo = mMsgReceiver;
                if(msgData != null){
                    msg.setData(msgData);
                }
                mMsgSender.send(msg);
            } catch (RemoteException rE) {
                onException(rE);
            }
        }
    }

    public void sendHandshake(){
        if(mMsgSender != null && mMsgReceiver != null){
            sendMessage(IOnHandleMessage.MSG_HANDSHAKE, 0, 0, null);
        }
    }
    /* END Public Methods */

    /* START Private Methods */
    private void onException(Exception e){
        Log.e(LOGCAT, e.getMessage());
        e.printStackTrace();
    }
    /* END Private Methods */

    /** START Private Classes **/
    private class MessageHandler extends Handler {

        // Types
        final static int TYPE_SERVICE = 0x1;
        final static int TYPE_ACTIVITY = 0x2;

        private IOnHandleMessage mCallback;
        private int mType;

        public MessageHandler(IOnHandleMessage callback, int type){
            mCallback = callback;
            mType = type;
        }

        @Override
        public void handleMessage(Message msg){
            addMessage(msg);
            switch(msg.what){
                case IOnHandleMessage.MSG_HANDSHAKE:
                    switch(mType){
                        case TYPE_SERVICE:
                            setMsgSender(msg.replyTo);
                            sendHandshake();
                            break;
                        case TYPE_ACTIVITY:
                            Log.v(LOGCAT, "HERE");
                            break;
                    }
                    break;
                default:
                    if(mCallback != null){
                        mCallback.onHandleMessage(msg);
                    }
                    break;
            }
        }

    }
    /** END Private Classes **/

}

Trong ví dụ hoạt động:

public class activity extends AppCompatActivity
      implements     ServiceConnection,
                     MessageManager.IOnHandleMessage { 

    [....]

    private MessageManager mMessenger;

    private void initMyMessenger(IBinder iBinder){
        mMessenger = new MessageManager(this, iBinder);
        mMessenger.sendHandshake();
    }

    private void bindToService(){
        Intent intent = new Intent(this, TagScanService.class);
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
        /* START THE SERVICE IF NEEDED */
    }

    private void unbindToService(){
    /* UNBIND when you want (onDestroy, after operation...)
        if(mBound) {
            unbindService(mServiceConnection);
            mBound = false;
        }
    }

    /* START Override MessageManager.IOnHandleMessage Methods */
    @Override
    public void onHandleMessage(Message msg) {
        switch(msg.what){
            case Constants.MSG_SYNC_PROGRESS:
                Bundle data = msg.getData();
                String text = data.getString(Constants.KEY_MSG_TEXT);
                setMessageProgress(text);
                break;
            case Constants.MSG_START_SYNC:
                onStartSync();
                break;
            case Constants.MSG_END_SYNC:
                onEndSync(msg.arg1 == Constants.ARG1_SUCCESS);
                mBound = false;
                break;
        }
    }
    /* END Override MessageManager.IOnHandleMessage Methods */

    /** START Override ServiceConnection Methods **/
    private class BLEScanServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            initMyMessenger(iBinder);
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mMessenger = null;
            mBound = false;
        }
    }
    /** END Override ServiceConnection Methods **/

Trong ví dụ dịch vụ:

public class Blablabla extends Service
    implements     MessageManager.IOnHandleMessage {

    [...]

    private MessageManager mMessenger;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        super.onBind(intent);
        initMessageManager();
        return mMessenger.getMsgReceiver().getBinder();
    }

    private void initMessageManager(){
        mMessenger = new MessageManager(this);
    }

    /* START Override IOnHandleMessage Methods */
    @Override
    public void onHandleMessage(Message msg) {
    /* Do what you want when u get a message looking the "what" attribute */
    }
    /* END Override IOnHandleMessage Methods */

Gửi tin nhắn từ Hoạt động / Dịch vụ:

mMessenger.sendMessage(what, arg1, arg2, dataBundle);

Cách thức hoạt động:

về hoạt động bạn bắt đầu hoặc ràng buộc dịch vụ. Các phương thức "OnBind" của dịch vụ trả lại Binder cho MessageManager của anh ta, trong Hoạt động thông qua triển khai phương thức giao diện "Kết nối dịch vụ" "OnServiceConnected", bạn nhận được IBinder này và khởi tạo Messagemanager bằng cách sử dụng nó. Sau khi Activity khởi tạo MessageManager, MessageHandler gửi và Bắt tay tới dịch vụ để nó có thể đặt người gửi "MessageHandler" của mình ("Messenger mMsgSender riêng tư" trong MessageManager). Làm điều này dịch vụ biết ai gửi tin nhắn của mình.

Bạn cũng có thể thực hiện việc này bằng cách sử dụng "người gửi" Danh sách / Hàng đợi của Messenger trong Trình quản lý tin nhắn để bạn có thể gửi nhiều tin nhắn đến các Hoạt động / Dịch vụ khác nhau hoặc bạn có thể sử dụng "người nhận" Danh sách / Hàng đợi của Messenger trong Trình quản lý tin nhắn để bạn có thể nhận nhiều tin nhắn tin nhắn từ các hoạt động / dịch vụ khác nhau.

Trong ví dụ "MessageManager", bạn có một danh sách tất cả các tin nhắn nhận được.

Như bạn có thể thấy kết nối giữa "Messenger của Activity" và "Service Messenger" bằng cách sử dụng đối tượng "MessageManager" này là tự động, nó được thực hiện thông qua phương thức "OnServiceConnected" và thông qua việc sử dụng "Bắt tay".

Hy vọng điều này hữu ích cho bạn :) Cảm ơn bạn rất nhiều! Tạm biệt: D


2

Để theo dõi câu trả lời @MrSnowflower với một ví dụ mã. Đây là Applicationlớp mã nguồn mở XABBER . Các Applicationlớp được tập trung và phối hợp Listenersvà ManagerInterfaces và nhiều hơn nữa. Các nhà quản lý của tất cả các loại được tải động. Activity´sbắt đầu trong Xabber sẽ báo cáo loại của Listenerchúng. Và khi Servicebắt đầu, nó báo cáo với Applicationlớp như đã bắt đầu. Bây giờ để gửi một thông điệp đến Activitytất cả những gì bạn phải làm là biến bạn Activitytrở thành một listenerloại bạn cần. Trong OnStart() OnPause()sổ đăng ký / hủy đăng ký. Họ Servicecó thể yêu cầu Applicationlớp chỉ listenercần nói chuyện và nếu có thì Hoạt động đã sẵn sàng để nhận.

Đi qua Applicationlớp bạn sẽ thấy có thêm một chiến lợi phẩm nữa.


Liên kết được cung cấp bây giờ dẫn đến một github 404. Nó có di chuyển không?
JE Carter II

Đúng, dường như làm việc bây giờ. Phải là một vấn đề tạm thời trên github.
JE Carter II

1

Ràng buộc là một cách khác để giao tiếp

Tạo một cuộc gọi lại

public interface MyCallBack{

   public void getResult(String result);

}

Hoạt động bên:

  1. Triển khai giao diện trong Hoạt động

  2. Cung cấp việc thực hiện cho phương thức

  3. Ràng buộc hoạt động với dịch vụ

  4. Đăng ký và hủy đăng ký gọi lại khi Dịch vụ bị ràng buộc và không bị ràng buộc với Hoạt động.

    public class YourActivity extends AppCompatActivity implements MyCallBack{
    
          private Intent notifyMeIntent;
          private GPSService gpsService;
          private boolean bound = false;
    
          @Override
          public void onCreate(Bundle sis){
    
              // activity code ...
    
              startGPSService();
    
          }
    
          @Override
          public void getResult(String result){
           // show in textView textView.setText(result);
          }
    
          @Override
          protected void onStart()
          {
              super.onStart();
              bindService();
          }
    
          @Override
          protected void onStop() {
              super.onStop();
              unbindService();
          }
    
          private ServiceConnection serviceConnection = new ServiceConnection() {
    
                @Override
                public void onServiceConnected(ComponentName className, IBinder service) {
    
                      GPSService.GPSBinder binder = (GPSService.GPSBinder) service;
                      gpsService= binder.getService();
                      bound = true;
                      gpsService.registerCallBack(YourActivity.this); // register
    
               }
    
               @Override
               public void onServiceDisconnected(ComponentName arg0) {
                      bound = false;
               }
          };
    
          private void bindService() {
    
               bindService(notifyMeIntent, serviceConnection, Context.BIND_AUTO_CREATE);
          }
    
          private void unbindService(){
               if (bound) {
                     gpsService.registerCallBack(null); // unregister            
                     unbindService(serviceConnection);
                     bound = false;
                }
          }
    
          // Call this method somewhere to start Your GPSService
          private void startGPSService(){
               notifyMeIntent = new Intent(this, GPSService.class);
               startService(myIntent );
          }
    
     }

Phía dịch vụ:

  1. Khởi tạo gọi lại

  2. Gọi phương thức gọi lại bất cứ khi nào cần

     public class GPSService extends Service{
    
         private MyCallBack myCallback;
         private IBinder serviceBinder = new GPSBinder();
    
         public void registerCallBack(MyCallBack myCallback){
              this.myCallback= myCallback;
         }
    
         public class GPSBinder extends Binder{
    
             public GPSService getService(){
                  return GPSService.this;
             }
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent){
             return serviceBinder;
        }
     }

của bạn serviceConnectionlà ra khỏi onCreate. Hãy chỉnh sửa nó.
Adeel Zafar

Nó không phải ở bên trong onCreate
Rohit Singh


0

Ngoài LocalBroadcastManager, Event Bus và Messenger đã được trả lời trong câu hỏi này, chúng tôi có thể sử dụng Pending Intent để liên lạc từ dịch vụ.

Như đã đề cập ở đây trong bài viết trên blog của tôi

Giao tiếp giữa dịch vụ và Hoạt động có thể được thực hiện bằng PendingIntent. Để chúng tôi có thể sử dụng createdPendingResult () .createPendingResult () tạo một đối tượng PendingIntent mới mà bạn có thể sử dụng để phục vụ để sử dụng và gửi dữ liệu kết quả về hoạt động của bạn bên trong onActivityResult int, Intent) gọi lại. Vì vậy, PendingIntent là Parcelable và do đó có thể được đưa vào một mục đích bổ sung, hoạt động của bạn có thể chuyển PendingIntent này đến dịch vụ. Đến lượt mình, dịch vụ có thể gọi phương thức send () trên PendingIntent để thông báo cho hoạt động thông qua onActivityResult của một sự kiện.

Hoạt động

public class PendingIntentActivity extends AppCompatActivity
{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

PendingIntent pendingResult = createPendingResult(
100, new Intent(), 0);
Intent intent = new Intent(getApplicationContext(), PendingIntentService.class);
intent.putExtra("pendingIntent", pendingResult);
startService(intent);

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100 && resultCode==200) {
Toast.makeText(this,data.getStringExtra("name"),Toast.LENGTH_LONG).show();
}
super.onActivityResult(requestCode, resultCode, data);
}
}

Dịch vụ

public class PendingIntentService extends Service {

    private static final String[] items= { "lorem", "ipsum", "dolor",
            "sit", "amet", "consectetuer", "adipiscing", "elit", "morbi",
            "vel", "ligula", "vitae", "arcu", "aliquet", "mollis", "etiam",
            "vel", "erat", "placerat", "ante", "porttitor", "sodales",
            "pellentesque", "augue", "purus" };
    private PendingIntent data;

    @Override
    public void onCreate() {
        super.onCreate();
    }

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

        data = intent.getParcelableExtra("pendingIntent");

        new LoadWordsThread().start();
        return START_NOT_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    class LoadWordsThread extends Thread {
        @Override
        public void run() {
            for (String item : items) {
                if (!isInterrupted()) {

                    Intent result = new Intent();
                    result.putExtra("name", item);
                    try {
                        data.send(PendingIntentService.this,200,result);
                    } catch (PendingIntent.CanceledException e) {

                        e.printStackTrace();
                    }
                    SystemClock.sleep(400);

                }
            }
        }
    }
}
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.