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.app.Service;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.net.NetworkInfo;
|
||||||
import android.net.wifi.WifiInfo;
|
import android.net.wifi.WifiInfo;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
@ -17,7 +18,12 @@ import org.fdroid.fdroid.Utils;
|
|||||||
import org.fdroid.fdroid.localrepo.LocalRepoKeyStore;
|
import org.fdroid.fdroid.localrepo.LocalRepoKeyStore;
|
||||||
import org.fdroid.fdroid.localrepo.LocalRepoManager;
|
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.security.cert.Certificate;
|
||||||
|
import java.util.Enumeration;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
public class WifiStateChangeService extends Service {
|
public class WifiStateChangeService extends Service {
|
||||||
@ -27,77 +33,67 @@ public class WifiStateChangeService extends Service {
|
|||||||
|
|
||||||
private WifiManager wifiManager;
|
private WifiManager wifiManager;
|
||||||
private static WaitForWifiAsyncTask asyncTask;
|
private static WaitForWifiAsyncTask asyncTask;
|
||||||
|
private int wifiState;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
FDroidApp.initWifiSettings();
|
||||||
NetworkInfo ni = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
|
NetworkInfo ni = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
|
||||||
wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
|
wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
|
||||||
if (ni == null) {
|
wifiState = wifiManager.getWifiState();
|
||||||
// this app just started up, NetworkInfo is only passed via WifiStateChangeReceiver
|
if (ni == null || ni.isConnected()) {
|
||||||
int wifiState = wifiManager.getWifiState();
|
/* started on app start or from WifiStateChangeReceiver,
|
||||||
if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
|
NetworkInfo is only passed via WifiStateChangeReceiver */
|
||||||
startAsyncTask();
|
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;
|
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<Void, Void, Void> {
|
public class WaitForWifiAsyncTask extends AsyncTask<Void, Void, Void> {
|
||||||
private static final String TAG = "WaitForWifiAsyncTask";
|
private static final String TAG = "WaitForWifiAsyncTask";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
try {
|
try {
|
||||||
while (!wifiManager.isWifiEnabled()) {
|
WifiInfo wifiInfo = null;
|
||||||
FDroidApp.initWifiSettings();
|
|
||||||
if (isCancelled())
|
wifiState = wifiManager.getWifiState();
|
||||||
|
|
||||||
|
while (FDroidApp.ipAddressString == null) {
|
||||||
|
if (isCancelled()) // can be canceled by a change via WifiStateChangeReceiver
|
||||||
return null;
|
return null;
|
||||||
if (BuildConfig.DEBUG) {
|
if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
|
||||||
Log.d(TAG, "waiting for the wifi to be 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);
|
Thread.sleep(1000);
|
||||||
}
|
|
||||||
int ipAddress = wifiManager.getConnectionInfo().getIpAddress();
|
|
||||||
while (ipAddress == 0) {
|
|
||||||
if (isCancelled())
|
|
||||||
return null;
|
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
Log.d(TAG, "waiting for an IP address...");
|
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;
|
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) {
|
||||||
if (ssid != null) {
|
String ssid = wifiInfo.getSSID();
|
||||||
FDroidApp.ssid = ssid.replaceAll("^\"(.*)\"$", "$1");
|
if (ssid != null) {
|
||||||
|
FDroidApp.ssid = ssid.replaceAll("^\"(.*)\"$", "$1");
|
||||||
|
}
|
||||||
|
String bssid = wifiInfo.getBSSID();
|
||||||
|
if (bssid != null) {
|
||||||
|
FDroidApp.bssid = bssid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
FDroidApp.bssid = wifiInfo.getBSSID();
|
|
||||||
|
|
||||||
String scheme;
|
String scheme;
|
||||||
if (Preferences.get().isLocalRepoHttpsEnabled())
|
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",
|
FDroidApp.repo.address = String.format(Locale.ENGLISH, "%s://%s:%d/fdroid/repo",
|
||||||
scheme, FDroidApp.ipAddressString, FDroidApp.port);
|
scheme, FDroidApp.ipAddressString, FDroidApp.port);
|
||||||
|
|
||||||
if (isCancelled())
|
if (isCancelled()) // can be canceled by a change via WifiStateChangeReceiver
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Context context = WifiStateChangeService.this.getApplicationContext();
|
Context context = WifiStateChangeService.this.getApplicationContext();
|
||||||
LocalRepoManager lrm = LocalRepoManager.get(context);
|
LocalRepoManager lrm = LocalRepoManager.get(context);
|
||||||
lrm.writeIndexPage(Utils.getSharingUri(FDroidApp.repo).toString());
|
lrm.writeIndexPage(Utils.getSharingUri(FDroidApp.repo).toString());
|
||||||
|
|
||||||
if (isCancelled())
|
if (isCancelled()) // can be canceled by a change via WifiStateChangeReceiver
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// the fingerprint for the local repo's signing key
|
// the fingerprint for the local repo's signing key
|
||||||
@ -156,4 +152,54 @@ public class WifiStateChangeService extends Service {
|
|||||||
return null;
|
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