Android - 从另一个服务以固定间隔调用系统服务

时间:2011-04-15 20:42:22

标签: android multithreading service broadcastreceiver android-context

正如问题所暗示的那样,我想知道如何编写一个调用系统服务的线程,然后等待一段时间再调用系统服务的函数,该函数从已注册的{onReceive调用BroadcastReceiver {1}}。

换句话说,我正在尝试在我的自定义服务中调用Wifi扫描服务(在BroadcastReceiver注册IntentFilters),以便我可以获得当前的SSID。我知道我最终会对收到的数据做些什么,这与这个问题无关。但是,我需要等待一段时间才能在startScan内再次致电onReceive,这就是我要确定最佳行动方案的地方。

我设法尝试在我的线程中以这种方式调用wifi扫描程序:

    private Object _lock = new Object();

    private final long SLEEP_TIME = 15000; //Scan every 15 secs
    private final long WIFI_SCAN_TIMEOUT = 60000; //One minute timeout for getting called back, otherwise, initiate a new scan.

   @Override
    public void run() {
        while(running){
            //Start a new scan;
            wifiSearchComplete = false;
            _wifiMan.startScan();
            while(!wifiSearchComplete){
                synchronized(_lock){
                    try{
                        _lock.wait(WIFI_SCAN_TIMEOUT);
                    } catch (InterruptedException ie){
                         Log.d(TAG, TAG+".run() caught " + ie.getMessage() +" when trying to sleep for " + (WIFI_SCAN_TIMEOUT/1000) +"secs.");
                         Thread.currentThread().interrupt();
                    }
                }
                if(!wifiSearchComplete){
                    synchronized(_lock){
                        //Try scanning again since we didn't get called back at all;
                        _lock.notify();
                    }
                }
            }
        }
    }

    public boolean isRunning(){
        return running;
    }

    public void stop(){
        synchronized(_lock){
            running = false;
            //unregister receivers and cleanup
            _lock.notify();
        }
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        synchronized(_lock){
               wifiSearchComplete = true;
               //iterate through our SSID's
                try{
                    _lock.wait(SLEEP_TIME);
                } catch (InterruptedException ie){
                     Log.d(TAG, TAG+".onReceive() caught " + ie.getMessage() +" when trying to sleep for " + (SLEEP_TIME/1000) +"secs.");
                     Thread.currentThread().interrupt();
                }
                _lock.notify();
            }
    }

但是,即使它在再次扫描之前每15秒等待一次,当尝试退出我的测试活动(调用onDestroy)时,它会在解除服务绑定之前阻塞主线程的休眠时间。换句话说,这是尝试在没有阻止的情况下完成我想要做的事情的适当方式,或者我是否必须在BroadcastReceiver结束时创建Thread.sleep并致电onReceive在开始新扫描之前?

1 个答案:

答案 0 :(得分:2)

您应该实现IntentService。在你的实现中覆盖onHandleIntent()来进行WiFi扫描。

接下来,使用AlarmManager计划以某个间隔向IntentService发送Intent。组成你自己的动作名称:“diago.intent.scan_wifi”或类似的东西。如果您使用其中一个“不精确的重复间隔”(例如15分钟),那么Android操作系统将同时安排所有其他服务,以最大限度地减少手机必须从睡眠模式唤醒的次数。

最后,实现BroadcastReceiver以响应ACTION_BOOT_COMPLETED并调用您的代码来安排AlarmManager。这将在启动时启动您的服务。

这样,当AlarmManager发送意图时,您的服务将被加载,执行扫描然后退出。