Android:在屏幕关闭时进入覆盖范围区域后重新连接到Wi-Fi
作者:互联网
只要设备在接入点范围内而不打开屏幕,我就一直在自动打开Wi-Fi.测试和找出解决方案非常令人沮丧,尤其是因为不同的设备具有完全不同的结果.
基础测试
在此测试期间,请保持屏幕关闭.该应用程序应持有WifiLock.
>走出WiFi覆盖范围并在那里呆一分钟.
>返回到覆盖范围.
结果:Wifi没有立即重新连接,因此应用程序没有重新连接到服务器.根据设备和设置的不同,有时直到打开屏幕后它才完全重新连接.
强制Wi-Fi重新连接
好的,这一次,如果Wifi断开连接,我的应用程序将间隔调用WifiManager.Reconnect().
重复测试.
结果:为S3工作,其他设备失败.
尝试添加其他电话
尝试了WifiManager.Scan(),WifiManager.Reassociate()等的不同组合.最终,它适用于除S4之外的大多数设备(HTC,S3).
似乎适用于所有设备的代码
NetworkInfo wifiInfo = _androidConnectivityMgr.GetNetworkInfo(ConnectivityType.Wifi);
if (!_wifiManager.IsWifiEnabled || _wifiManager.WifiState == WifiState.Disabled || _wifiManager.WifiState == WifiState.Disabling)
{
// Make sure the Wi-Fi is enabled, required for some devices when enable WiFi does not occur immediately
_wifiManager.SetWifiEnabled(true);
}
if (!wifiInfo.IsConnectedOrConnecting)
{
// Do not wait for the OS to initiate a reconnect to a Wi-Fi router
_wifiManager.PingSupplicant();
if (_wifiManager.WifiState == WifiState.Enabled)
{
try
{
// Brute force methods required for some devices
_wifiManager.SetWifiEnabled(false);
_wifiManager.SetWifiEnabled(true);
}
catch (Java.Lang.SecurityException)
{
// 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();
}
我什至不确定所有这些代码是否必要,因为我无法在线找到很多信息. WifiFixer确实帮助了一些人.但这似乎确实适用于我测试过的设备.
问题
>还有更好的方法吗?
>制造商是否真的在修改基本的Android,使我看到很大的不同?
>这是完全错误的方法吗?
感谢您阅读所有这些内容:)
补充笔记
>代码在从AlarmManager启动的10秒间隔内运行. WakeLock仅在此通话期间保持.
>在此最终看起来恐怖的解决方案/破解之前,“ Wifi睡眠策略”影响了结果.这让我感到困惑,因为我一直都拿着WifiLock,我认为这相当于“从不”.
>以编程方式更改“ Wifi睡眠策略”不适用于S4,其他人可以确认吗?
>是的,我们特别需要这样做,并且了解电池的影响.
解决方法:
我的情况略有不同-我不持有wifi锁开始(而且我使用的是常规android系统,因此我必须翻译您的方法).
屏幕关闭,CPU关闭,无线电消失.警报唤醒我的(唤醒)服务-我持有(部分)唤醒锁.
我想要的是-如果启用了wifi可以将其连接到在无线电失效之前已连接的接入点-我将获得一个wifi锁,然后调用您的函数-wakeWifiUp().无线电失效后(!wifiInfo.IsConnectedOrConnecting为true),当我尝试连接时,网络无法访问.我解决它,如:
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!
}
}
}
}
}
顺便说一句,并不是需要用akeWifiUp()中的所有技巧(在我的情况下),也可以省略所有!_wifiManager.isWifiEnabled()-因为只有在用户启用的情况下,我才使用网络.我将其保留完整.
回顾一下:在我的场景中,您的方法还不够(如果我正确地翻译成java并且没有犯一些愚蠢的错误,这种错误总是适用的-另请参见我的connection()).我需要等待建立连接-但是一切都很好.不确定您使用它的方式是否正确-如果像我一样,那可能是您一直持有wifi锁
HTC Nexus 1、2.3.7,Cyanogen mod(不要射击,我已经给它进行了测试).
会及时向大家发布
标签:xamarin-android,android-wifi,wifimanager,android 来源: https://codeday.me/bug/20191122/2061709.html