The main reason that tethering (of any kind) is not correctly supported by WebRTC on Android is that the internal network interfaces used for tethering are not included in the ICE candidate enumerations. As a result, for all those interfaces, only relay or reflexive connections are used.
A workaround can be found at the following link:
https://stackoverflow.com/questions/7509924/detect-usb-tethering-on-android/
Additionally, you can use Direct Wi-Fi code to produce something like the following inside sdk/android/api/org/webrtc/NetworkMonitorAutoDetect.java:
static class TetheringDelegate extends BroadcastReceiver {
private static final String EXTRA_ACTIVE_TETHER =
android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? "tetherArray" : "activeArray";
private static final String EXTRA_ERRORED_TETHER = "erroredArray";
private static final String EXTRA_AVAILABLE_TETHER = "availableArray";
private static final String ACTION_TETHER_STATE_CHANGED = "android.net.conn.TETHER_STATE_CHANGED";
private static final int TETHERING_NETWORK_HANDLE = 0;
private final Context context;
private final NetworkChangeDetector.Observer observer;
private List<NetworkInformation> tetheringNetworkInfo;
private static class NetworkInformationDiff {
public List<String> added = new ArrayList<>();
public List<NetworkInformation> unChanged = new ArrayList<>();
public List<NetworkInformation> removed = new ArrayList<>();
public boolean isNoChange() {
return added.isEmpty() && removed.isEmpty();
}
private List<String> getIntfNames(List<NetworkInformation> netInfos) {
List<String> intfNames = new ArrayList<>();
for (NetworkInformation netInfo : netInfos) {
intfNames.add(netInfo.name);
}
return intfNames;
}
}
TetheringDelegate(NetworkChangeDetector.Observer observer, Context context) {
this.context = context;
this.observer = observer;
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_TETHER_STATE_CHANGED);
context.registerReceiver(this, intentFilter);
}
@Override
@SuppressLint("InlinedApi")
public void onReceive(Context context, Intent intent) {
if (ACTION_TETHER_STATE_CHANGED.equals(intent.getAction())) {
List<String> tetherIfNames = intent.getStringArrayListExtra(EXTRA_ACTIVE_TETHER);
List<String> erroredIfNames = intent.getStringArrayListExtra(EXTRA_ERRORED_TETHER);
List<String> availableIfNames = intent.getStringArrayListExtra(EXTRA_AVAILABLE_TETHER);
onTetheringStateChange(tetherIfNames, erroredIfNames, availableIfNames);
}
}
public void release() {
context.unregisterReceiver(this);
}
public List<NetworkInformation> getActiveNetworkList() {
return tetheringNetworkInfo != null ? tetheringNetworkInfo : Collections.emptyList();
}
private NetworkInformationDiff computeNetworkInfoDiff(List<String> newNetIntfs) {
Map<String, NetworkInformation> oldMap = new HashMap<>();
NetworkInformationDiff diff = new NetworkInformationDiff();
Set<String> newNetInfsSet = new HashSet<>(newNetIntfs);
if (tetheringNetworkInfo != null) {
for (NetworkInformation oldNetInfo : tetheringNetworkInfo) {
oldMap.put(oldNetInfo.name, oldNetInfo);
}
}
for (String oldNetInfoName : oldMap.keySet()) {
newNetInfsSet.remove(oldNetInfoName);
}
for (String newNetInfoName : newNetInfsSet) {
NetworkInformation unChanged = oldMap.remove(newNetInfoName);
if (unChanged != null) {
diff.unChanged.add(unChanged);
}
}
diff.added.addAll(newNetInfsSet);
diff.removed.addAll(oldMap.values());
return diff;
}
private void onTetheringStateChange(List<String> tetherIfNames,
List<String> erroredIfNames,
List<String> availableIfNames) {
NetworkInformationDiff diff = computeNetworkInfoDiff(tetherIfNames);
if (diff.isNoChange()) {
return;
}
List<NetworkInformation> netInfos = new ArrayList<>(diff.unChanged);
List<NetworkInformation> newNetInfos = new ArrayList<>();
for (String ifName : diff.added) {
NetworkInterface intf = NetworkInterface.getByName(ifName);
if (intf == null) {
continue;
}
List<InetAddress> interfaceAddresses = Collections.list(intf.getInetAddresses());
IPAddress[] ipAddresses = new IPAddress[interfaceAddresses.size()];
for (int i = 0; i < interfaceAddresses.size(); ++i) {
InetAddress inetAddress = interfaceAddresses.get(i);
ipAddresses[i] = new IPAddress(inetAddress.getAddress());
}
NetworkInformation netInfo = new NetworkInformation(ifName,
NetworkChangeDetector.ConnectionType.CONNECTION_ETHERNET,
NetworkChangeDetector.ConnectionType.CONNECTION_NONE, TETHERING_NETWORK_HANDLE,
ipAddresses);
newNetInfos.add(netInfo);
}
netInfos.addAll(newNetInfos);
tetheringNetworkInfo = netInfos;
for (NetworkInformation connNetInfo : newNetInfos) {
observer.onNetworkConnect(connNetInfo);
}
for (NetworkInformation discNetInfo : diff.removed) {
observer.onNetworkDisconnect(discNetInfo.handle);