我是一个正在寻找关于如何在Android中正确使用服务的一些建议。我正在构建一个应用程序,它将连接到Internet上的服务器以通过TCP获取数据流。然后,该数据需要发送到通过蓝牙串口连接的另一台设备。我希望在用户查看不同的活动时继续在后台运行。
该应用程序将是一个NTRIP客户端,它从互联网上提取实时RTK校正数据并将其发送到我通过蓝牙连接的RTK GPS接收器。数据速率约为500字节/秒。用户界面是用于连接或断开数据流的单个按钮,以及用于显示GPS接收器状态的一些文本。还有一些设置需要由用户配置,例如要连接的服务器的IP /端口以及要与之通信的蓝牙设备。
我认为我需要让主要活动产生一个本地服务,然后让服务为TCP流产生一个线程,为蓝牙连接产生另一个线程。听起来不错吗?
在这种情况下,该服务的最佳模型是什么?
- 每次活动开始时启动(绑定)服务,并使用connect / disconnect按钮向服务发送命令以启动/停止线程。如果我走这条路线,服务将在用户断开连接后继续运行并转到另一个应用程序。该服务需要一个不活动计时器才能自行终止。
- 当用户按下连接/断开连接按钮时启动并停止服务。该服务仅在数据移动时运行。如果我这样做,活动将需要查看活动启动时服务是否正在运行,以便知道它是否应绑定到服务或告诉用户链接已断开连接。
感谢。
答案 0 :(得分:1)
我会选择你的第二个选项。检查服务是否正在运行是一项简单的任务,您也不会消耗不必要的处理时间,这对于电池寿命来说会更好。
仅仅因为你可以在后台长时间运行服务并不一定意味着你也应该这样做。至少不是所有的时间。
答案 1 :(得分:0)
由于android支持多个入口点,你可以在Manifest.xml中定义两个入口点。
<category android:name="android.intent.category.LAUNCHER" />
定义此类可以从启动器启动。我想这也适用于服务。我会做两个切入点。首先生成活动并为用户提供一些配置控制。而另一个只是产生服务。
由于您无法控制活动的生命周期,因此我不会建议您执行任何不应由系统终止的操作。如果您有来电,您的活动就会死亡。 如果用户启动该服务,您可以使用该按钮创建一个小部件。如果用户启动活动,您可以启动服务和小部件。 如果用户启动小部件,则用户决定该服务应该发生什么。
答案 2 :(得分:0)
我不是Java或Android程序员,所以我带着一点点说法。在Java中处理阻塞IO的常规方法是使用线程。听起来数据流是单向的,但为了获得最大的灵活性,我将创建3个线程,一个用于UI,一个用于TCP连接,一个用于蓝牙连接。 UI和两个工作线程之间的通信可以使用共享变量完成(需要注意同步,竞争条件等)。我会使用多线程队列数据结构将数据NTRIP数据传递给另一个worker。
NTRIP数据的工作线程大概是:
while (app running) {
if (connection enabled) {
if (not connected) {
c = connect to remote
}
data = get data from c
queue.put(data)
if (options reconfigured) {
close c
}
}
}
对于蓝牙线程:
while (app runnning) {
data = queue.get()
if (UI settings changed and connected) {
close connection
}
if (not connected) {
c = connect to remote
}
send data over connection
}
在正常状态下,两个工作程序都在阻塞IO并且基本上不占用CPU时间。根据我的经验,我建议你编写代码来处理通信错误。为了使您的代码在现实世界中运行良好,您必须处理关闭,挂起等连接。使其稳健可能是开发中最耗时的部分。