diff --git a/F-Droid/src/org/fdroid/fdroid/net/WifiStateChangeService.java b/F-Droid/src/org/fdroid/fdroid/net/WifiStateChangeService.java index 95a81b7d4..eca334673 100644 --- a/F-Droid/src/org/fdroid/fdroid/net/WifiStateChangeService.java +++ b/F-Droid/src/org/fdroid/fdroid/net/WifiStateChangeService.java @@ -3,6 +3,7 @@ package org.fdroid.fdroid.net; import android.app.Service; import android.content.Context; import android.content.Intent; +import android.net.NetworkInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.AsyncTask; @@ -17,7 +18,12 @@ import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.localrepo.LocalRepoKeyStore; import org.fdroid.fdroid.localrepo.LocalRepoManager; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; import java.security.cert.Certificate; +import java.util.Enumeration; import java.util.Locale; public class WifiStateChangeService extends Service { @@ -27,77 +33,67 @@ public class WifiStateChangeService extends Service { private WifiManager wifiManager; private static WaitForWifiAsyncTask asyncTask; + private int wifiState; @Override public int onStartCommand(Intent intent, int flags, int startId) { + FDroidApp.initWifiSettings(); NetworkInfo ni = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); - if (ni == null) { - // this app just started up, NetworkInfo is only passed via WifiStateChangeReceiver - int wifiState = wifiManager.getWifiState(); - if (wifiState == WifiManager.WIFI_STATE_ENABLED) { - startAsyncTask(); + wifiState = wifiManager.getWifiState(); + if (ni == null || ni.isConnected()) { + /* started on app start or from WifiStateChangeReceiver, + NetworkInfo is only passed via WifiStateChangeReceiver */ + Log.i(TAG, "ni == " + ni + " wifiState == " + printWifiState(wifiState)); + if (wifiState == WifiManager.WIFI_STATE_ENABLED + || wifiState == WifiManager.WIFI_STATE_UNKNOWN) { // might be hotspot + if (asyncTask != null) { + asyncTask.cancel(true); + } + asyncTask = new WaitForWifiAsyncTask(); + asyncTask.execute(); } - } else if (ni.isConnected()) { - Log.i(TAG, "ni.isConnected()"); - startAsyncTask(); - } else { - Log.i("WifiStateChangeReceiver", "ni != null && !ni.isConnected()"); - FDroidApp.initWifiSettings(); } return START_NOT_STICKY; } - private void startAsyncTask() { - Log.i(TAG, "startAsyncTask"); - if (asyncTask != null) { - Log.i(TAG, "asyncTask.cancel"); - asyncTask.cancel(true); - } - asyncTask = new WaitForWifiAsyncTask(); - asyncTask.execute(); - } - public class WaitForWifiAsyncTask extends AsyncTask { private static final String TAG = "WaitForWifiAsyncTask"; @Override protected Void doInBackground(Void... params) { try { - while (!wifiManager.isWifiEnabled()) { - FDroidApp.initWifiSettings(); - if (isCancelled()) + WifiInfo wifiInfo = null; + + wifiState = wifiManager.getWifiState(); + + while (FDroidApp.ipAddressString == null) { + if (isCancelled()) // can be canceled by a change via WifiStateChangeReceiver return null; - if (BuildConfig.DEBUG) { - Log.d(TAG, "waiting for the wifi to be enabled..."); - } + if (wifiState == WifiManager.WIFI_STATE_ENABLED) { + wifiInfo = wifiManager.getConnectionInfo(); + FDroidApp.ipAddressString = formatIpAddress(wifiInfo.getIpAddress()); + } else + FDroidApp.ipAddressString = getIpAddressFromNetworkInterface(); + // TODO turning off a hotspot leaves wifiState as UNKNOWN with no IP, and this goes until next wifi change Thread.sleep(1000); - } - int ipAddress = wifiManager.getConnectionInfo().getIpAddress(); - while (ipAddress == 0) { - if (isCancelled()) - return null; if (BuildConfig.DEBUG) { Log.d(TAG, "waiting for an IP address..."); } - Thread.sleep(1000); - ipAddress = wifiManager.getConnectionInfo().getIpAddress(); } - if (isCancelled()) + if (isCancelled()) // can be canceled by a change via WifiStateChangeReceiver return null; - WifiInfo wifiInfo = wifiManager.getConnectionInfo(); - ipAddress = wifiInfo.getIpAddress(); - FDroidApp.ipAddressString = String.format(Locale.ENGLISH, "%d.%d.%d.%d", - (ipAddress & 0xff), - (ipAddress >> 8 & 0xff), - (ipAddress >> 16 & 0xff), - (ipAddress >> 24 & 0xff)); - final String ssid = wifiInfo.getSSID(); - if (ssid != null) { - FDroidApp.ssid = ssid.replaceAll("^\"(.*)\"$", "$1"); + if (wifiInfo != null) { + String ssid = wifiInfo.getSSID(); + if (ssid != null) { + FDroidApp.ssid = ssid.replaceAll("^\"(.*)\"$", "$1"); + } + String bssid = wifiInfo.getBSSID(); + if (bssid != null) { + FDroidApp.bssid = bssid; + } } - FDroidApp.bssid = wifiInfo.getBSSID(); String scheme; if (Preferences.get().isLocalRepoHttpsEnabled()) @@ -108,14 +104,14 @@ public class WifiStateChangeService extends Service { FDroidApp.repo.address = String.format(Locale.ENGLISH, "%s://%s:%d/fdroid/repo", scheme, FDroidApp.ipAddressString, FDroidApp.port); - if (isCancelled()) + if (isCancelled()) // can be canceled by a change via WifiStateChangeReceiver return null; Context context = WifiStateChangeService.this.getApplicationContext(); LocalRepoManager lrm = LocalRepoManager.get(context); lrm.writeIndexPage(Utils.getSharingUri(FDroidApp.repo).toString()); - if (isCancelled()) + if (isCancelled()) // can be canceled by a change via WifiStateChangeReceiver return null; // the fingerprint for the local repo's signing key @@ -156,4 +152,54 @@ public class WifiStateChangeService extends Service { return null; } + public String getIpAddressFromNetworkInterface() { + try { + for (Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); networkInterfaces.hasMoreElements(); ) { + NetworkInterface netIf = networkInterfaces.nextElement(); + + for (Enumeration inetAddresses = netIf.getInetAddresses(); inetAddresses.hasMoreElements(); ) { + InetAddress inetAddress = inetAddresses.nextElement(); + if (inetAddress.isLoopbackAddress() || inetAddress instanceof Inet6Address) { + continue; + } else if (netIf.getDisplayName().contains("wlan0") + || netIf.getDisplayName().contains("eth0") + || netIf.getDisplayName().contains("ap0")) { + return inetAddress.getHostAddress(); + } + } + } + } catch (SocketException ex) { + ex.printStackTrace(); + } + + return null; + } + + private String formatIpAddress(int ipAddress) { + if (ipAddress == 0) { + return null; + } else { + return String.format(Locale.ENGLISH, "%d.%d.%d.%d", + (ipAddress & 0xff), + (ipAddress >> 8 & 0xff), + (ipAddress >> 16 & 0xff), + (ipAddress >> 24 & 0xff)); + } + } + + private String printWifiState(int wifiState) { + switch (wifiState) { + case WifiManager.WIFI_STATE_DISABLED: + return "WIFI_STATE_DISABLED"; + case WifiManager.WIFI_STATE_DISABLING: + return "WIFI_STATE_DISABLING"; + case WifiManager.WIFI_STATE_ENABLING: + return "WIFI_STATE_ENABLING"; + case WifiManager.WIFI_STATE_ENABLED: + return "WIFI_STATE_ENABLED"; + case WifiManager.WIFI_STATE_UNKNOWN: + return "WIFI_STATE_UNKNOWN"; + } + return null; + } }