As the question implies, I am wondering how I could write a thread that would call a system service and then wait a certain amount of time before calling said system service's function that calls back to onReceive
from a registered BroadcastReceiver
.
In other words, I am trying to call the Wifi scanning service (registering a BroadcastReceiver
with IntentFilters
) within my custom service so I can get the current SSID's available. I know what I will end up doing with the received data, which is not relevant to this question. However, I will need to wait a certain amount of time before calling startScan
again within onReceive
, and that is where I am trying to determine the best course of action.
I managed to try calling the wifi scanner in this fashion within my thread:
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开发者_如何学C){
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();
}
}
However, even though it waits every 15 seconds before it scans again, when trying to exit my test activity (calling onDestroy
) it blocks the main thread for the sleep time, before it unbinds the service. In other words, is this the appropriate way of trying to accomplish what I want to do without blocking, or do I have to simply create a BroadcastReceiver
and call Thread.sleep
at the end of onReceive
before calling starting a new scan?
You should implement an IntentService. In your implementation override onHandleIntent() to do you WiFi scan.
Next, use the AlarmManager to schedule sending an Intent to your IntentService at some interval. Make up your own action name: "diago.intent.scan_wifi" or something like that. If you use one of the "inexact repeating intervals" (such as 15min) then the Android OS will schedule all the other services at the same time to minimize the number of times the phone must wake from sleep mode.
Finally, Implement a BroadcastReceiver to respond to ACTION_BOOT_COMPLETED and call your code to schedule the AlarmManager. This will start your service on boot.
This way when the AlarmManager sends the intent, your service will be loaded, execute the scan and then exit.
精彩评论