如何从绑定服务与处理程序进行通信?
Posted
技术标签:
【中文标题】如何从绑定服务与处理程序进行通信?【英文标题】:How to communicate back from a bound service with a Handler? 【发布时间】:2012-06-18 17:12:35 【问题描述】:我目前正在通过我的应用使用的插件与外部服务进行通信。
绑定的服务最终会启动一个活动,然后应通知主应用该活动已完成。
问题是,服务通过本地广播得到通知。我已经将 Messenger msg.replyTo
存储到一个变量中,所以我可以在 Handler 完成后访问它,但 Service 仍在绑定中。
它确实有效,但是我想完全确定不可能有 NullPointer,所以我不太喜欢这种方法。
有没有比将 Messenger 存储在变量中更好的方式与 Binder 进行通信?
这里有一些代码可以更好的理解:
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver()
@Override
public void onReceive(Context context, Intent intent)
try
if (intent.getAction().equals("activity_closed") && mReplyMessenger != null)
mReplyMessenger.send(Message.obtain(null, MSG_RESULT_ACTIVITY_FINISHED));
catch (RemoteException e)
e.printStackTrace();
;
class IncomingHandler extends Handler
@Override
public void handleMessage(Message msg)
mReplyMessenger = null;
try
switch (msg.what)
case MSG_START_ACTIVITY:
mReplyMessenger = msg.replyTo;
[...]
BridgeBinder.this.startActivity(i);
break;
[...]
default:
super.handleMessage(msg);
catch (RemoteException e)
e.printStackTrace();
final Messenger mMessenger = new Messenger(new IncomingHandler());
@Override
public IBinder onBind(Intent arg0)
return mMessenger.getBinder();
【问题讨论】:
AsyncTask 如何解决这个问题? 请在发布随机 cmets 之前阅读问题。它是关于绑定服务的,处理程序是主应用程序和外部服务之间的 IPC。 【参考方案1】:我正在以相同的方式实现双向 Messenger。我真的没有看到您的 Handler 获得对您的 Activity 的过时引用(因此是 NPE),但如果您想格外小心,您可以尝试在 onResume() 方法中每次更新引用,甚至每次您会收到一条消息。
【讨论】:
【参考方案2】:如果你需要我的课:
MessageManager.java
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import com.ubikinformatica.it.lib.commons.modules.log.EMaxLogger;
import java.util.ArrayList;
import java.util.List;
public class MessageManager
public interface IOnHandleMessage
// Message Whats
int MSG_HANDSHAKE = 0x1;
void onHandleMessage(Message msg);
private static final String TAG = MessageManager.class.getSimpleName();
private Messenger mMsgSender;
private Messenger mMsgReceiver;
private List<Message> mMessages;
public MessageManager(IOnHandleMessage callback, IBinder target)
mMsgReceiver = new Messenger(new MessageHandler(this, callback, MessageHandler.TYPE_ACTIVITY));
mMsgSender = new Messenger(target);
mMessages = new ArrayList<>();
public MessageManager(IOnHandleMessage callback)
mMsgReceiver = new Messenger(new MessageHandler(this, callback, MessageHandler.TYPE_SERVICE));
mMsgSender = null;
mMessages = new ArrayList<>();
/** 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);
/** 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)
EMaxLogger.onException(TAG, rE);
public void sendHandshake()
if(mMsgSender != null && mMsgReceiver != null)
sendMessage(IOnHandleMessage.MSG_HANDSHAKE, 0, 0, null);
MessageHandler.java
import android.os.Handler;
import android.os.Message;
public class MessageHandler extends Handler
// Types
final static int TYPE_SERVICE = 0x1;
final static int TYPE_ACTIVITY = 0x2;
private MessageManager mMessageManager;
private MessageManager.IOnHandleMessage mCallback;
private int mType;
public MessageHandler(MessageManager msgManager, MessageManager.IOnHandleMessage callback, int type)
this.mMessageManager = msgManager;
this.mCallback = callback;
this.mType = type;
/** Override Handler Methods **/
@Override
public void handleMessage(Message msg)
this.mMessageManager.addMessage(msg);
switch(msg.what)
case MessageManager.IOnHandleMessage.MSG_HANDSHAKE:
switch(mType)
case TYPE_SERVICE:
this.mMessageManager.setMsgSender(msg.replyTo);
this.mMessageManager.sendHandshake();
break;
case TYPE_ACTIVITY:
break;
break;
default:
if(mCallback != null)
mCallback.onHandleMessage(msg);
break;
更多信息在我的帖子中:CHECK MY POST HERE
实际上新的 JobService 和 JobIntentService 存在一些问题,因为它们不能返回比 JobScheduler IBinder Engine 另一个 IBinder,但我现在正在尝试解决它们:D
希望这对您有所帮助,编写一个漂亮的代码 :D 再见
[重要编辑时间:02/05/2019 - 10:57]
OK 问题已解决 大声笑你可以将 Messenger 放在一个包裹中并通过 Intent 将其发送到服务。 因此,在 JobIntentService 中,“onBind”方法将返回 JobScheduler IBinder Engine,您将在 Intent 中获取 Messenger 的 Binder!
因此,您仅使用回调在活动中初始化 MessageManager,通过“enqueueWork”启动服务,并在意图中放置 MessengerReceiver。在 JobIntentService 中,您可以通过在“onBind”和“onHandleWork”方法中获得的意图中使用 Messenger 的“getBinder()”方法获取 IBinder 来初始化 MessageManager。 当您拥有活动的 MessengerReceiver 的 IBinder 时,您可以使用构造函数“回调 + 活页夹”来初始化 MessageManager。 然后在服务中发送握手并在活动中设置他的发件人。
这样做:
您必须更改 MessageHandler 的“handleMessage”覆盖方法: 现在的方法是这样的:
@Override
public void handleMessage(Message msg)
this.mMessageManager.addMessage(msg);
switch(msg.what)
case MessageManager.IOnHandleMessage.MSG_HANDSHAKE:
switch(mType)
case TYPE_SERVICE:
this.mMessageManager.setMsgSender(msg.replyTo);
this.mMessageManager.sendHandshake();
break;
case TYPE_ACTIVITY:
break;
break;
default:
if(mCallback != null)
mCallback.onHandleMessage(msg);
break;
您需要删除该类型,因为您不再需要它。 所以在“MessageHandler”类里面的“handleMessage”方法的切换中,当你获取和握手时你必须这样做:
[...]
case MessageManager.IOnHandleMessage.MSG_HANDSHAKE:
if(this.mMessageManager.getMsgSender() == null)
this.mMessageManager.setMsgSender(msg.replyTo);
this.mMessageManager.sendHandshake();
[...]
这样解决了 JobIntentService 的问题 ;) 希望这对你有帮助! 好好编码
【讨论】:
以上是关于如何从绑定服务与处理程序进行通信?的主要内容,如果未能解决你的问题,请参考以下文章
adnroid四大组件之Service 绑定服务,数据通信-IBinder