首页 \ 问答 \ 如何保持对绑定服务的轮询?(How to keep polling a bound service?)

如何保持对绑定服务的轮询?(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?

更新时间:2023-03-22 19:03

最满意答案

您可以使用LocalBroadcastManagerService广播发送到您的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 your Service to your Activity. For example, in your Service 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 your Activity 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 a BroadcastReceiver:

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徽章。 如果它打开的应用程序,它将能 ...
  • 你不需要这样做。 如果要存储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.
  • 我通过使用一些更新的代码将服务属性从此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 ...
  • 我的猜测是你有某种竞争条件 ,只有大量的客户出现。 您为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 ...

相关文章

更多

最新问答

更多
  • 在javascript中创建类以创建对象并在Java中创建类和对象之间的区别(Difference between creating a class in javascript to create an object and creating an class and object in Java)
  • Facebook API:将身份验证详细信息从Javascript SDK发送到PHP SDK(Facebook API: Send authentication detail from Javascript SDK to PHP SDK)
  • 如何停止队列动画jquery?(How can I stop queue animation jquery?)
  • 使用C#的井字游戏中的人工智能(Artificial Intelligence in Tic-Tac-Toe using C#)
  • 多少流量可以共享虚拟主机(对于Python Django站点)支持?(How Much Traffic Can Shared Web Hosting (for a Python Django site) support?)
  • 带有CIFilters的CAShapeLayer(CAShapeLayer with CIFilters)
  • 如何在Angular 2中读取JSON #text(How to read in Angular 2 the JSON #text)
  • 如何在xml中读取自闭标签的属性?(How to read self closing tag's attribute in xml?)
  • 无法使用http put将图像上传到亚马逊S3(Cannot upload image to amazon s3 using http put)
  • 文件结束无限循环(end of file infinite while-loop)
  • 在cpp的模板(template in cpp)
  • 在构建库时,clang和clang ++有什么区别?(What's the difference between clang and clang++ when building a library?)
  • ng类中的表达式(expression inside ng-class)
  • 在PHP中获取随机布尔值true / false(Get random boolean true/false in PHP)
  • 管道的高效分块用于严格的字节串(Efficient chunking of conduit for strict bytestring)
  • Python ternary_operator(如果其他标志做了其他操作,则执行其他操作)(Python ternary_operator (do-somthing if flag else do-another))
  • Sencha Touch面具发布(Sencha Touch mask ondisclosure)
  • 验证脚本上的通知[重复](Notices on validation script [duplicate])
  • 朋友功能(friend function)
  • 基于角坐标平移和变换平面几何(Translate and transform plane geometry based on corner coordinates)
  • Rails:'如果在本地运行'条件javascript标记包括(Rails: 'if running locally' conditional javascript tag include)
  • 解压文件(Unzipping files)
  • 使用ui-router以角度加载变量状态(loading in variable states with ui-router in angular)
  • 创建Azure云服务需要多长时间?(how long does it take to create an Azure Cloud Service? How to view log information?)
  • 指向整数的指针数组(Array of pointers to integers)
  • Laravel服务提供商没有看到我的包的主要类(Laravel service provider does not see the main class of my package)
  • 这个关于VSS / RSS / PSS / USS的解释是否准确?(Is this explanation about VSS/RSS/PSS/USS accurate?)
  • 在Django-Admin中通过row-id排序显示项目(Ordering the display items by row-id in Django-Admin)
  • 如何使用cythonize启用`--embed`?(How to enable `--embed` with cythonize?)
  • 用于将文本多行设置的Excel脚本(Excel script for ereasing text multiple rows)