私のシナリオは少し異なります-最初はwifiロックを保持していません(そして、私は通常のAndroidを使用しているため、メソッドを翻訳する必要がありました)。
画面オフ、CPUオフ、ラジオ停止。アラームが (ウェイクフル) サービスを起動します - (部分的な) ウェイク ロックを保持しています。
私が欲しいのは、無線が切れる前に接続されていたアクセスポイントにwifiが接続できるようになっている場合-wifiロックを取得し、あなたの関数を呼び出します- wakeWifiUp()
. 無線が停止すると (!wifiInfo.IsConnectedOrConnecting
本当です) 、接続しようとするとネットワークに到達できなくなります。次のように回避します:
public final class NetworkService extends WakefulIntentService {
// this is an intent service - runs on its own thread - otherwise it would
// deadlock as I am using it. Moreover it holds a wakelock and woken up by
// an AlarmManager's Receiver - works reliably
private BroadcastReceiver mConnectionReceiver;
private volatile static CountDownLatch latch;
@Override
protected void doWakefulWork(Intent intent) {
WifiLock _wifiLock = null;
WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
boolean failedToConnect = true;
if (wm != null && wm.isWifiEnabled()) {// Don't want to enable it myself
_wifiLock = wm.createWifiLock(
/* WifiManager.WIFI_MODE_FULL_HIGH_PERF */0x3, this.getClass()
.getName() + ".WIFI_LOCK");
_wifiLock.acquire();
failedToConnect = !wakeWifiUp();
}
if (failedToConnect) {
if (_wifiLock != null) _wifiLock.release();
w("No connection !");
return;
}
HttpURLConnection connection = null;
try {
connection = connection();
} catch (IOException e) {/* won't throw - it doesn't do much*/}
OutputStream serverOutputStream = null;
try {
serverOutputStream = connection.getOutputStream(); // now
// this is really where the connection might seriously throw
// .... Work ....
} catch (IOException e) {
w("IOException sending data " + e.getMessage());
// I get here : Network unreachable when radio dies
} finally {
if (_wifiLock != null) _wifiLock.release();
if (connection != null) connection.disconnect();
}
}
private HttpURLConnection connection() throws MalformedURLException,
IOException {
HttpURLConnection connection = (HttpURLConnection) new URL("localhost")
.openConnection();
connection.setDoOutput(true); // triggers POST
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("User-Agent",
"Android Multipart HTTP Client 1.1");
return connection;
}
private boolean wakeWifiUp() {
ConnectivityManager _androidConnectivityMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo wifiInfo = _androidConnectivityMgr
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
WifiManager _wifiManager = (WifiManager)
getSystemService(Context.WIFI_SERVICE);
final int wifiState = _wifiManager.getWifiState();
if (!_wifiManager.isWifiEnabled()
|| wifiState == WifiManager.WIFI_STATE_DISABLED
|| wifiState == WifiManager.WIFI_STATE_DISABLING) {
// Make sure the Wi-Fi is enabled, required for some devices when
// enable WiFi does not occur immediately
d("!_wifiManager.isWifiEnabled()");
_wifiManager.setWifiEnabled(true);
// do not enable if not enabled ! FIXME
return false;
}
if (!wifiInfo.isConnectedOrConnecting()) {
d("Wifi is NOT Connected Or Connecting - "
+ "wake it up and wait till is up");
// Do not wait for the OS to initiate a reconnect to a Wi-Fi router
_wifiManager.pingSupplicant();
if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
try {
// Brute force methods required for some devices
_wifiManager.setWifiEnabled(false);
_wifiManager.setWifiEnabled(true);
} catch (SecurityException e) {
// Catching exception which should not occur on most
// devices. OS bug details at :
// https://code.google.com/p/android/issues/detail?id=22036
}
}
_wifiManager.disconnect();
_wifiManager.startScan();
_wifiManager.reassociate();
_wifiManager.reconnect();
// THIS IS WHAT I DO TO WAIT FOR A CONNECTION
try {
mConnectionReceiver = new WifiConnectionMonitor();
startMonitoringConnection();
latch = new CountDownLatch(1);
w("I wait");
latch.await();
w("Woke up");
return true; // made it
} catch (InterruptedException e) {
w("Interrupted while waiting for connection", e);
return false;
} finally {
stopMonitoringConnection();
}
}
return true;
}
static void downTheLatch() {
latch.countDown();
}
private synchronized void startMonitoringConnection() {
IntentFilter aFilter = new IntentFilter(
ConnectivityManager.CONNECTIVITY_ACTION);
aFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
registerReceiver(mConnectionReceiver, aFilter);
}
private synchronized void stopMonitoringConnection() {
unregisterReceiver(mConnectionReceiver);
}
private final class WifiConnectionMonitor extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent in) {
String action = in.getAction();
if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
NetworkInfo networkInfo = in
.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
d(networkInfo + "");
if (networkInfo.isConnected()) {
d("Wifi is connected!");
NetworkService.downTheLatch(); // HERE THE SERVICE IS WOKEN!
}
}
}
}
}
ところで、すべてのトリックwakeWifiUp()
が必要なわけではなく (私の場合) !_wifiManager.isWifiEnabled()
、ユーザーが有効にした場合にのみネットを使用するため、すべてを省略することができます。完全を期すために残します。
要約:私のシナリオでは、あなたの方法は十分ではありませんでした(Javaに正しく変換し、ばかげた間違いを犯さなかった場合、常に適用されます-私のも参照してくださいconnection()
)。接続が確立されるのを待つ必要がありましたが、その後はすべて問題ありませんでした。あなたがそれをどのように正確に使用していたのかまだわかりません-私がそうするなら、違いはあなたがずっとwifiロックを保持していたということかもしれません
HTC Nexus 1、2.3.7、Cyanogen mod (撮影しないでください。テスト用に提供されています)。
お知らせします