如何保持对绑定服务的轮询?(How to keep polling a bound service?)
我在互联网上查了一下,但找不到涵盖我的情景的例子。 我想做的是:
1)一旦我的活动开始(完成)就开始并绑定到服务
2)然后服务将自己绑定到另一个服务,寻找来自连接设备的用户输入,并将字符串保存到变量(完成)
3)我想将此字符串发送回活动,因此我可以检查它是什么,并基于它来进行网络呼叫。
现在排名第3)是我的挑战。 我设法用一个运行一秒钟的Timer,然后检查服务中写入的值,但不知怎的,这似乎不是正确的方式,我认为可能有一个更成熟的解决方案。 但是,我似乎无法弄明白。
我从文档中获取了代码,只添加了计时器。 在这个例子中只有一个服务只生成一个随机数(这通常会被我的第二个服务所取代)。 这是服务的代码:
public class LocalService extends Service { private final IBinder mBinder = new LocalBinder(); private final Random mGenerator = new Random(); public class LocalBinder extends Binder { LocalService getService() { return LocalService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } public int getRandomNumber() { return mGenerator.nextInt(100); } }
这是我活动中的代码:
public class MainActivity extends AppCompatActivity { LocalService mService; boolean mBound = false; Timer timer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); timer = new Timer(); } @Override protected void onStart() { super.onStart(); Intent intent = new Intent(this, LocalService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); timer.schedule(new MyTimerTask(new Handler(), this), 1000, 1000); // run on every second } @Override protected void onStop() { super.onStop(); if (mBound) { unbindService(mConnection); mBound = false; } timer.cancel(); timer.purge(); } private class MyTimerTask extends TimerTask { Handler handler; MainActivity ref; public MyTimerTask(Handler handler, MainActivity ref) { super(); this.handler = handler; this.ref = ref; } @Override public void run() { handler.post(new Runnable() { @Override public void run() { if (mBound) { int num = ref.mService.getRandomNumber(); // just as an example, raise a toast to see if it works // but otherwise the value will be handled Toast.makeText(ref, "number: " + num, Toast.LENGTH_SHORT).show(); } } }); } } private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { LocalService.LocalBinder binder = (LocalService.LocalBinder) service; mService = binder.getService(); mBound = true; } @Override public void onServiceDisconnected(ComponentName arg0) { mBound = false; } }; }
我的问题是:这是一个好的方法(它的工作原理)还是不好的,有什么选择?
I looked up on the internet, but couldn't find an example covering my scenario. What I am trying to do is:
1) To start and bind to a service as soon as my activity starts (done)
2) The service then binds itself to another service looking for a user input from a connected device, and saves a string a string to a variable (done)
3) I would like to send back this string to the activity, so I can check what it is and based on it to make a network call.
Now number 3) is my challenge. I managed to do it with a Timer that runs for one second and then checks the value written in the service, but somehow this doesn't seem to be the right way and I think that there might be a more mature solution. However, I can't seem to figure it out.
I've taken the code from the documentation and only added the timer. It is just one service in this example that just generates a random number (this will normally be replaced by my second service). This is the code for the service:
public class LocalService extends Service { private final IBinder mBinder = new LocalBinder(); private final Random mGenerator = new Random(); public class LocalBinder extends Binder { LocalService getService() { return LocalService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } public int getRandomNumber() { return mGenerator.nextInt(100); } }
And this is the code in my activity:
public class MainActivity extends AppCompatActivity { LocalService mService; boolean mBound = false; Timer timer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); timer = new Timer(); } @Override protected void onStart() { super.onStart(); Intent intent = new Intent(this, LocalService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); timer.schedule(new MyTimerTask(new Handler(), this), 1000, 1000); // run on every second } @Override protected void onStop() { super.onStop(); if (mBound) { unbindService(mConnection); mBound = false; } timer.cancel(); timer.purge(); } private class MyTimerTask extends TimerTask { Handler handler; MainActivity ref; public MyTimerTask(Handler handler, MainActivity ref) { super(); this.handler = handler; this.ref = ref; } @Override public void run() { handler.post(new Runnable() { @Override public void run() { if (mBound) { int num = ref.mService.getRandomNumber(); // just as an example, raise a toast to see if it works // but otherwise the value will be handled Toast.makeText(ref, "number: " + num, Toast.LENGTH_SHORT).show(); } } }); } } private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { LocalService.LocalBinder binder = (LocalService.LocalBinder) service; mService = binder.getService(); mBound = true; } @Override public void onServiceDisconnected(ComponentName arg0) { mBound = false; } }; }
My question is: is this a good approach (it works) or is it bad and what's the alternative?
最满意答案
您可以使用
LocalBroadcastManager
将Service
广播发送到您的Activity
。 例如,在您的Service
声明中:public static final String BROADCAST_INTENT = "broadcast_intent"; public static final String BROADCAST_VALUE = "broadcast_value"; private LocalBroadcastManager broadcastManager; public void onCreate() { super.onCreate(); broadcastManager = LocalBroadcastManager.getInstance(this); }
现在,只要您想将
String
发送到Activity
,就可以这样做:private void sendBroadcast(String value) { Intent intent = new Intent(BROADCAST_INTENT); intent.putExtra(BROADCAST_VALUE, value); broadcastManager.sendBroadcast(intent); }
在您的
Activity
声明一个BroadcastReceiver
:private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { handleIntent(intent); } };
绑定到
Service
时注册接收方:IntentFilter broadcastIntentFilter = new IntentFilter(); broadcastIntentFilter.addAction(StreamService.BROADCAST_INTENT); LocalBroadcastManager.getInstance(context).registerReceiver((broadcastReceiver), broadcastIntentFilter);
并取消注册您从
Service
取消绑定的位置:LocalBroadcastManager.getInstance(context).unregisterReceiver(broadcastReceiver);
现在,当您的服务发送广播时,您可以在您的
Activity
处理它:private void handleIntent(Intent intent) { if (intent.getAction().equals(StreamService.BROADCAST_INTENT)) { String value = intent.getStringExtra(StreamService.BROADCAST_VALUE, "default"); } }
You can use
LocalBroadcastManager
to send broadcasts from yourService
to yourActivity
. For example, in yourService
declare:public static final String BROADCAST_INTENT = "broadcast_intent"; public static final String BROADCAST_VALUE = "broadcast_value"; private LocalBroadcastManager broadcastManager; public void onCreate() { super.onCreate(); broadcastManager = LocalBroadcastManager.getInstance(this); }
Now whenever you want to send a
String
to yourActivity
you can do so like this:private void sendBroadcast(String value) { Intent intent = new Intent(BROADCAST_INTENT); intent.putExtra(BROADCAST_VALUE, value); broadcastManager.sendBroadcast(intent); }
In your
Activity
declare aBroadcastReceiver
:private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { handleIntent(intent); } };
Register the receiver when you bind to your
Service
:IntentFilter broadcastIntentFilter = new IntentFilter(); broadcastIntentFilter.addAction(StreamService.BROADCAST_INTENT); LocalBroadcastManager.getInstance(context).registerReceiver((broadcastReceiver), broadcastIntentFilter);
And unregister where you unbind from your
Service
:LocalBroadcastManager.getInstance(context).unregisterReceiver(broadcastReceiver);
Now when your service sends the broadcast you can handle it in your
Activity
:private void handleIntent(Intent intent) { if (intent.getAction().equals(StreamService.BROADCAST_INTENT)) { String value = intent.getStringExtra(StreamService.BROADCAST_VALUE, "default"); } }
相关问答
更多-
Re Android:是的,这也是可能的,就像iPhone一样,你需要的准确性越低,它就越快。 它也是异步的,因此您需要一种类似的方法。 与iPhone相反,您可以启动GPS并等待后台服务中的位置更新,以便您可以随时将当前位置发送到服务器。 Re Android: yes, this is also possible, and just as with the iPhone, the less accuracy you need, the faster this will be. It is also as ...
-
Apple PUSH通知不是一个好的解决方案 1)您只能打包数量有限的数据2)可能很难弄清楚用户是否启动了应用程序或已退出。 如果您在用户退出应用程序后继续发送PUSH消息,则最终会收到大量垃圾邮件。 如果您尝试将某些内容发送到服务器以表明用户已关闭应用程序,以便它停止发送PUSH,则在应用程序崩溃时它可能不起作用。 我建议你使用套接字。 或者只是使用预定的循环来每分钟发出一次请求。 ..... 但是我想知道你是否可以发送一个没有警告的声音和声音的PUSH,然后发送一个0徽章。 如果它打开的应用程序,它将能 ...
-
了解绑定服务文档(Understand Bound Service Documentation)[2022-06-12]
你不需要这样做。 如果要存储LocalBinder,则可以。 如果要为每个客户端绑定返回一个新的Binder实例,则可以。 如果您希望它可以绑定到您(如果您希望服务仅通过startService而不是通过bindService工作,则只需返回null),您唯一需要做的就是返回非null。 You don't need to do it that way. If you want to store a LocalBinder, you can. If you want to return a new Bind ... -
您可以使用消息在活动和服务之间发送信息。 这是发送简单数据的简便方法,但如果您需要非常频繁地发送数据或发送复杂数据,则可能不是最佳选择。 这是我的一个应用程序中的一些代码示例,其中包含一项服务和一项通信活动: 活动代码: //this is where you set what you want to happen class IncomingHandler extends Handler { @Override public void handleMessage(Message msg) ...
-
您必须return一些数据 - 并且不要将timeout逻辑放入服务中 - 应该包含在控制器代码中。 您可以重构以处理控制器中的响应以及服务中包含的数据调用: cadApp.controller('statsController', function ($scope, $timeout, DashboardStats) { pollData(); function pollData() { DashboardStats.poll().then(function(data) ...
-
是的,我们可以为绑定和未绑定调用一个服务。 Yes,we can call one service for both bound and unbound.
-
使用Windows服务轮询(Polling using Windows Service)[2022-09-11]
我通过使用一些更新的代码将服务属性从此This Account更改为Local System Account ,找到了解决方案。 using (TcpClient newclient = new TcpClient("192.168.0.151", 4000)) { NetworkStream ns = newclient.GetStream(); byte[] outbytes = Encoding.ASCII.GetBytes(command); ns.Write(ou ... -
你的函数pollGet正在参与基于可重用原则返回Observable
,因此最终订阅不适合这里,因为它会将返回类型转换为subscription 。 关于switchMap : switchMap用于组合可观察链,其中switchMap中的Observable基于原始Observable的结果。 所以在这里你应该在switchMap返回Observable类型。 根据你的代码, switchMap中的observable与任何原始的可观察结果无关,所以在这里你可以简单地使用map ... -
推动或轮询(Pushing OR Polling)[2022-08-17]
我的猜测是你有某种竞争条件 ,只有大量的客户出现。 您为WCF服务使用哪些并发和实例化模式? (请参阅MSDN:WCF会话,实例化和并发性,请访问http://msdn.microsoft.com/en-us/library/ms731193.aspx ) 如果您“丢失”响应,我要做的第一件事就是开始记录或跟踪服务器上发生的事情。 例如,当客户端“看不到”响应时,服务器是否收到请求? (如果是这样,会发生什么,等等) 我还会关注内存使用情况 - 你没有说你正在使用什么操作系统,但这些天512 MB是非常瘦的 ... -
您可以使用LocalBroadcastManager将Service广播发送到您的Activity 。 例如,在您的Service声明中: public static final String BROADCAST_INTENT = "broadcast_intent"; public static final String BROADCAST_VALUE = "broadcast_value"; private LocalBroadcastManager broadcastManager; public ...