如何让Android服务与活动进行通信

我正在编写我的第一个Android应用程序,并试图让我的头脑围绕服务和活动之间的沟通。 我有一个将在后台运行的服务,并执行一些gps和基于时间的日志记录。 我将有一个将用于启动和停止服务的活动。

所以首先,我需要能够确定活动开始时服务是否正在运行。 这里还有其他一些问题,所以我想我可以弄清楚(但随时提供建议)。

我真正的问题:如果活动正在运行并且服务已启动,我需要一种服务将消息发送到活动的方式。 简单的字符串和整数在这一点上 - 主要是状态消息。 这些消息不会定期发生,所以我不认为如果有其他方式,投票服务是一个好方法。 我只在用户启动活动时才需要此通信 - 我不想从服务启动活动。 换句话说,如果您启动“活动”并且“服务”正在运行,那么当发生有趣的事情时,您将在活动用户界面中看到一些状态消息。 如果你没有启动活动,你将不会看到这些消息(他们并不那么有趣)。

看起来我应该能够确定服务是否正在运行,如果是,请将该活动添加为侦听器。 然后在Activity暂停或停止时将Activity作为侦听器移除。 这实际上可能吗? 我唯一能找到的方法就是让Activity实现Parcelable并构建一个AIDL文件,这样我就可以通过Service的远程接口传递它。 这似乎是矫枉过正,但我​​不知道Activity应该如何实现writeToParcel()/ readFromParcel()。

有没有更容易或更好的方法? 谢谢你的帮助。

编辑:

对于稍后对此感兴趣的任何人,Google都会提供示例代码,用于通过样本目录中的AIDL处理此问题:/apis/app/RemoteService.java


有三种明显的与服务交流的方式:

  • 使用意图
  • 使用AIDL
  • 使用服务对象本身(作为单例)
  • 在你的情况下,我会选择3.对它自己的服务进行静态引用,并将其填充到onCreate()中:

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

    创建一个静态函数MyService getInstance() ,它返回静态sInstance

    然后在Activity.onCreate()启动服务,异步等待,直到服务实际启动(您可以通过向活动发送一个意向来通知您的应用程序已准备就绪),并获取它的实例。 当你有这个实例时,注册你的服务监听器对象给你服务,并且你被设置了。 注意:在活动中编辑视图时,您应该在UI线程中修改它们,该服务可能会运行它自己的线程,因此您需要调用Activity.runOnUiThread()

    你需要做的最后一件事是在Activity.onPause()删除对你的监听器对象的引用,否则你的活动上下文的一个实例会泄漏,不好。

    注意:只有当您的应用程序/活动/任务是唯一可以访问您的服务的进程时,此方法才有用。 如果不是这种情况,您必须使用选项1或2。


    提问者可能已经过去了很久,但如果有人搜索这个......

    还有另一种方法来处理这个问题,我认为这可能是最简单的。

    将BroadcastReceiver添加到您的活动。 注册它以在onResume中接收一些自定义意图并在onPause中注销它。 然后,当你想发送你的状态更新或你有什么时,发送你的服务意图。

    如果其他应用程序倾听了您的意图(任何人都可以做任何恶意操作?),请确保您不会不高兴,但除此之外,您应该没问题。

    代码示例请求:

    在我的服务中,我有:

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

    (RefreshTask.REFRESH_DATA_INTENT只是一个常量字符串。)

    在我的聆听活动中,我定义了我的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
            }
        }
    }
    

    我在课堂顶部宣布我的接收器:

    private DataUpdateReceiver dataUpdateReceiver;
    

    我重写onResume来添加:

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

    我重写onPause添加:

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

    现在我的活动正在倾听我的服务,说“嘿,去更新你自己”。 我可以在Intent中传递数据而不是更新数据库表,然后返回查找我的活动中的更改,但由于我希望更改仍然存在,因此通过db传递数据是有意义的。


    使用LocalBroadcastManager注册一个接收器来监听你的应用中从本地服务发送的广播,参考这里:

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

    链接地址: http://www.djcxy.com/p/26977.html

    上一篇: How to have Android Service communicate with Activity

    下一篇: C# datetime Exception on insert query using Nhibernate and MS sql server