从 Android 中的两个不同活动访问已启动服务的结果
Access the results of a started service from two different activities in Android
我有一项服务可以获取用户的位置并在意图中广播纬度和经度。
我认为我需要该服务成为启动服务(而不是绑定服务),因为我希望它能够在来自 firebase 的新 geoFire 条目进入时向用户发送推送通知即使应用程序关闭,它们的半径也是如此。
目前,该服务设置为广播位置。
鉴于位置服务将是一项启动服务,我不知道如何从两个单独的活动访问广播。
如果它是绑定服务,我相信我可以实现这一点,但由于我希望它无限期地保持活力,我不确定该怎么做。
这里是minimal example that demonstrates my issue.
具体来说,我在第一个activity上注册了一个广播接收器就可以获取到显示的经纬度,但是在第二个activity上获取不到显示的经纬度通过注册一个单独的广播接收器。
我已经阅读 Android's documentation on Services 但仍然不知道我应该怎么做才能解决这个问题。
我一直在 Android Studio 的模拟器上测试这一切:Nexus 5X API 25 x86.
2017 年 11 月 8 日更新:我更新了 github 项目以包含下面提供的 EventBus 解决方案。它在 eventBus 分支中。 master 分支仍然包含与问题相关的已更改、有问题的代码。
查看:
git clone https://github.com/Atticus29/locationServiceMCV.git
git checkout eventBus
然后,像往常一样打开 AndroidStudio 或 IDE 和 view/run。
广播结果是解决此问题的一种方法。但是如果你愿意在你的项目中添加一个库,我会强烈推荐 Green Robot's EventBus. It's a very lightweight lib, as it's fast. Also, it's simple to post complex objects through it without having to implement the Parcelable
接口。
此库以 publisher/subscriber 方式工作,在您的情况下,两个 Activity 都是订阅者,而 Service 将是发布者。
首先,您必须添加对 build.gradle
文件的依赖,如下所示。
implementation 'org.greenrobot:eventbus:3.0.0'
如果你在 Kotlin 项目上,还要添加此依赖项:
kapt 'org.greenrobot:eventbus-annotation-processor:3.0.1'
然后,定义一个事件 class,它将负责通过应用程序传输您的数据。请注意,这可以从 Service
到 Activity
完成。从一个 Fragment
到另一个。在活动之间,等等。
public class MessageEvent {
public double lat;
public double lng;
// Add additional fields here if needed
public MessageEvent(double lat, double lng) {
this.lat= lat;
this.lng = lng;
}
}
之后,您必须在 Activity
上订阅这些活动。
public class MyActivity extends AppCompatActivity {
// ...
@Override
public void onResume() {
super.onResume();
// This line will register your Activity to the EventBus
// making sure that all the methods annotated with @Subscribe
// will be called if their specific Events are posted.
EventBus.getDefault().register(this);
}
@Override
public void onPause() {
super.onPause();
// This line will unregister your Activity.
// It's a good practice to put this on the onPause() method
// to make your event handling system tied to the Activity lifecycle.
EventBus.getDefault().unregister(this);
}
// The threadMode MAIN makes sure this method is called on the main Thread.
// But you could also set it up to be called on other threads if needed. Check the docs for more info.
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
/* Call this line below if you want to remove the sticky event.
* That will prevent that this event will be seen by other subscribers once they subscribe.
* In your specific use case, you don't have to remove the sticky event here.
*/
// EventBus.getDefault().removeStickyEvent(event);
double lat = event.lat;
double lng = event.lng;
// Do whatever you want with the data.
};
}
实施后,您就可以 post 您的活动了。现在,在您的 Service
中,当您获得新的 Lat/Lng 信息时调用以下代码。
EventBus.getDefault().postSticky(new MessageEvent(lat,lng));
您可以阅读有关如何设置和自定义 EventBus 的更多信息on the docs, or on this tutorial。
我有一项服务可以获取用户的位置并在意图中广播纬度和经度。
我认为我需要该服务成为启动服务(而不是绑定服务),因为我希望它能够在来自 firebase 的新 geoFire 条目进入时向用户发送推送通知即使应用程序关闭,它们的半径也是如此。
目前,该服务设置为广播位置。
鉴于位置服务将是一项启动服务,我不知道如何从两个单独的活动访问广播。
如果它是绑定服务,我相信我可以实现这一点,但由于我希望它无限期地保持活力,我不确定该怎么做。
这里是minimal example that demonstrates my issue.
具体来说,我在第一个activity上注册了一个广播接收器就可以获取到显示的经纬度,但是在第二个activity上获取不到显示的经纬度通过注册一个单独的广播接收器。
我已经阅读 Android's documentation on Services 但仍然不知道我应该怎么做才能解决这个问题。
我一直在 Android Studio 的模拟器上测试这一切:Nexus 5X API 25 x86.
2017 年 11 月 8 日更新:我更新了 github 项目以包含下面提供的 EventBus 解决方案。它在 eventBus 分支中。 master 分支仍然包含与问题相关的已更改、有问题的代码。
查看:
git clone https://github.com/Atticus29/locationServiceMCV.git
git checkout eventBus
然后,像往常一样打开 AndroidStudio 或 IDE 和 view/run。
广播结果是解决此问题的一种方法。但是如果你愿意在你的项目中添加一个库,我会强烈推荐 Green Robot's EventBus. It's a very lightweight lib, as it's fast. Also, it's simple to post complex objects through it without having to implement the Parcelable
接口。
此库以 publisher/subscriber 方式工作,在您的情况下,两个 Activity 都是订阅者,而 Service 将是发布者。
首先,您必须添加对 build.gradle
文件的依赖,如下所示。
implementation 'org.greenrobot:eventbus:3.0.0'
如果你在 Kotlin 项目上,还要添加此依赖项:
kapt 'org.greenrobot:eventbus-annotation-processor:3.0.1'
然后,定义一个事件 class,它将负责通过应用程序传输您的数据。请注意,这可以从 Service
到 Activity
完成。从一个 Fragment
到另一个。在活动之间,等等。
public class MessageEvent {
public double lat;
public double lng;
// Add additional fields here if needed
public MessageEvent(double lat, double lng) {
this.lat= lat;
this.lng = lng;
}
}
之后,您必须在 Activity
上订阅这些活动。
public class MyActivity extends AppCompatActivity {
// ...
@Override
public void onResume() {
super.onResume();
// This line will register your Activity to the EventBus
// making sure that all the methods annotated with @Subscribe
// will be called if their specific Events are posted.
EventBus.getDefault().register(this);
}
@Override
public void onPause() {
super.onPause();
// This line will unregister your Activity.
// It's a good practice to put this on the onPause() method
// to make your event handling system tied to the Activity lifecycle.
EventBus.getDefault().unregister(this);
}
// The threadMode MAIN makes sure this method is called on the main Thread.
// But you could also set it up to be called on other threads if needed. Check the docs for more info.
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
/* Call this line below if you want to remove the sticky event.
* That will prevent that this event will be seen by other subscribers once they subscribe.
* In your specific use case, you don't have to remove the sticky event here.
*/
// EventBus.getDefault().removeStickyEvent(event);
double lat = event.lat;
double lng = event.lng;
// Do whatever you want with the data.
};
}
实施后,您就可以 post 您的活动了。现在,在您的 Service
中,当您获得新的 Lat/Lng 信息时调用以下代码。
EventBus.getDefault().postSticky(new MessageEvent(lat,lng));
您可以阅读有关如何设置和自定义 EventBus 的更多信息on the docs, or on this tutorial。