rework WifiStateChangeService to support hotspots (aka WiFi AP on device)
When a device is setup as a WiFi Access Point aka "hotspot", the standard API for getting the WiFi settings returns nothing. We have to use a separate API to get the IP address of the WiFi AP. As far as I could tell, there is no public API for getting the SSID/BSSID of the WiFi AP, so for now that is left blank. That means the wifi screen in swap is confusing because it will say it is not attached when the device is a hotspot @mvdan's https://github.com/mvdan/libaccesspoint should help there #193 https://gitlab.com/fdroid/fdroidclient/issues/193
This commit is contained in:
parent
edb3564e29
commit
96b7c35a2a
@ -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,36 +33,29 @@ 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();
|
||||
}
|
||||
} 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");
|
||||
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) {
|
||||
Log.i(TAG, "asyncTask.cancel");
|
||||
asyncTask.cancel(true);
|
||||
}
|
||||
asyncTask = new WaitForWifiAsyncTask();
|
||||
asyncTask.execute();
|
||||
}
|
||||
}
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
public class WaitForWifiAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||
private static final String TAG = "WaitForWifiAsyncTask";
|
||||
@ -64,40 +63,37 @@ public class WifiStateChangeService extends Service {
|
||||
@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 (wifiInfo != null) {
|
||||
String ssid = wifiInfo.getSSID();
|
||||
if (ssid != null) {
|
||||
FDroidApp.ssid = ssid.replaceAll("^\"(.*)\"$", "$1");
|
||||
}
|
||||
FDroidApp.bssid = wifiInfo.getBSSID();
|
||||
String bssid = wifiInfo.getBSSID();
|
||||
if (bssid != null) {
|
||||
FDroidApp.bssid = bssid;
|
||||
}
|
||||
}
|
||||
|
||||
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<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces(); networkInterfaces.hasMoreElements(); ) {
|
||||
NetworkInterface netIf = networkInterfaces.nextElement();
|
||||
|
||||
for (Enumeration<InetAddress> 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;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user