Unity : Detect if mobile is on Tether connection - android

Short question: I want to check if the Personal Hotspot functionality is turned on
I am currently building a client/server application. I would like to know if my mobile (Android for instance) has tether connection activated (personal hotspot), since my server could connect to it.
I found how to detect wifi connection thanks to this answer Unity check internet connection availability but this does not detect if I am using tether connection.
Do you know how ?
Thanks you all !
ps : I don't need to know if I have an internet connection, just tether wifi working on

So you want to check if the Personal Hotspot functionality is turned on? That would only allow you to determine if other devices can use your device to connect to the internet. To do that from within an Android app on the device, you would use the WiFiManager class as shown here.
Do you want to tell if something is actually connected to the hotspot? If so, you can look at this source (specifically in the getClientList method) to check for connected clients.
You mention a server. Are you trying to run a server on a desktop / laptop computer and then connect it to the personal hotspot on the device, then have the mobile app connect to some server on the desktop? If so, there are other things you'll need to consider.

Thanks to wottle links and help, I manage to find the solution
public bool isWifiApEnabled()
{
using (AndroidJavaObject activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity"))
{
try
{
using (var wifiManager = activity.Call<AndroidJavaObject>("getSystemService", "wifi"))
{
return wifiManager.Call<bool>("isWifiApEnabled");
}
}
catch (System.Exception e)
{
}
}
return false;
}

Related

is it possible to recognize wifi network inside app with xamarin

I'm just wondering if it's possible for an app to recognize what network you are connected to. I'm making and app where you have to be connected to a specific network before the app lets you use it's functions, but I'm wondering if that is even possible, I am using xamarin but I can program with androidand a little bit ofswift, so I also want to know if it's possible forxamarinto do this, if it's possible with android studio andxcode. I am usingxamarin.forms` by the way.
This used to be disabled for security reasons but after iOS 4.0 Apple enabled it.
Although this question is for Xcode, the answer can be applied in Xamarin.
This is a sample application built with the feature in question, although it is for Xamarin.Mac
Use function CNCopyCurrentNetworkInfo.
This is possible but you will have to do native implementations to access the specific platform apis. For Android you will need to use WifiManager (https://developer.android.com/reference/android/net/wifi/WifiManager) and for iOS you could possibly use NEHotspotConfiguration (https://developer.apple.com/documentation/networkextension/nehotspotconfiguration).
I have used WifiManager for Android to connect to a specific Wifi network programmatically.
You can use "CrossConnectivity" plugin in Xamarin by adding the package "xam.plugin.connectivity". Below is the code to check connectivity. From the connectionType property you can detect to which network the device is connected and perform operations accordingly. `
CrossConnectivity.Current.ConnectivityTypeChanged += (sender, e) =>
{
var wifi = Plugin.Connectivity.Abstractions.ConnectionType.WiFi;
var cellular = Plugin.Connectivity.Abstractions.ConnectionType.Cellular;
var connectionTypes = CrossConnectivity.Current.ConnectionTypes;
if (connectionTypes.Contains(cellular))
{
//Do operations with cellular
}
else if (connectionTypes.Contains(wifi))
{
//Do operations with wifi
}
};`

On Android, 'Sign in to network' uses strange IP routing?

I am trying to have an IoT device (ESP32) use Wifi AP mode, so that I can connect my cellphone to it and visit a webpage hosted on the device in order to see some data.
By doing some DNS shenanigans, I do get the "Sign in to network" pop-up to appear.
When I tap on the 'sign in' popup, a page from my IoT device appears correctly.
If I use any regular browser to visit the devices IP, my phone refuses to connect.
If I disable mobile data, I can connect to my device using browsers.
It seems that Android refuses to route traffic to a wifi network that doesn't appear to offer internet connectivity.
I looked at the routing tables (ip route show table 0) and the default route does seem to be to my device, but all the browsers seem to ignore it.
I am assuming that this is some anti-spoofing protection against rogue wifi hotspots - but how does the webview in the 'sign in' popup circumvent this?
Would i have to hack together some custom webview wrapper in order to be able to connect to the IoT device (over a LAN IP over Wifi) and the internet (3G/4G) simultaneously?
I tried telling the IoT device to hand out 0.0.0.0 as the default gw, but this only had the effect of disabling the sign-in pop-up.
Look into using ConnetivityManager.requestNetwork(). This allows you to bind a process to a particular network interface. Something like,
NetworkRequest.Builder request = new NetworkRequest.Builder();
request.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
request.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
connectivityManager.requestNetwork(request.build(), ...);
Look at the docs, but the second argument is a callback for when the network is available. Something like,
#Override
public void onAvailable(Network network) {
if (connectivityManager.bindProcessToNetwork(network)) {
// success
} else {
// fail
}
}
Undo the binding with ConnectivityManager.unregisterNetworkCallback() and .bindProcessToNetwork(null). E.g.,
protected void releaseTransport() {
if (requestTransportCallback != null) {
connectivityManager.unregisterNetworkCallback(requestTransportCallback);
requestTransportCallback = null;
connectivityManager.bindProcessToNetwork(null);
}
}
Good luck.

TXT Record from a Wifi Direct Printer

I'm trying to get TXT Records from Wifi Direct Printers nearby. So far, I can discover peers and establish a connection. But no luck with TXT Records.
I tried Wifi Direct Service Discovery, and I believe I did everything properly since I compared lots of codes from different resources including sample projects from Google and some open source Wifi Direct Wrappers in GitHub. But I couldn't make it work.
I've also seen some weird issues while trying to achieve that. e.g in some devices, when I start the peer discovery, Wifi Connection started to be turned off and on constantly.
Can someone explain how this actually works ? are DnsSdServiceResponseListener and DnsSdTxtRecordListener made for Android devices rather than Printers ?
I've also tried to listen the MultiCast DNS IP Address (224.0.0.251) with a MulticastSocket after establishing the connection between Android and Wifi Direct Printer, but I couldn't receive any data as well.
Thanks.
I used "DnsSdServiceResponseListener" and "DnsSdTxtRecordListener" successfully in my current project. Both listeners are associated to discovering local services nearby.
To use them properly, you have to do the following:
Implement your listeners
WifiP2pManager.DnsSdServiceResponseListener dnsListener = new WifiP2pManager.DnsSdServiceResponseListener() {
#Override
public void onDnsSdServiceAvailable(String instanceName, String registrationType, WifiP2pDevice device) {
// instanceName is service name and device is the print information
}};
WifiP2pManager.DnsSdTxtRecordListener txtListener = new WifiP2pManager.DnsSdTxtRecordListener() {
#Override
public void onDnsSdTxtRecordAvailable(String fullDomain, Map record, WifiP2pDevice device) {
// here we get the service published information in the record map object
}};
Add the listeners to your WiFiManager object
wifiP2PManagerObj.setDnsSdResponseListeners(mChannel, dnsListener, txtListener);
Add service request
WifiP2pDnsSdServiceRequest serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();
wifiP2PManagerObj.addServiceRequest(mChannel,serviceRequest, actionListener);
Finally, discover services
wifiP2PManagerObj.discoverServices(mChannel,actionListener);
After discover services is executed successfully, the listeners should receive the nearby services information.
Hope this helps.
Goodluck.
Update
Wifi direct supported printers don't have any published services by default. To use them you have to connect to them via wifi direct and print normally as its a printer connected to your network. Note that those listeners are meant to capture published services (i.e will not capture anything for any device unless its publishing a service).
I think you will need to run Bonjour discovery once the connection is established. You can see NSD and look for "_ipp._tcp" as the service type. By the way,
for "I've also seen some weird issues while trying to achieve that. e.g in some devices, when I start the peer discovery, Wifi Connection started to be turned off and on constantly." if you're testing on a 7.1 device you might be seeing this issue, for which a patch should be coming soon.

Use multiple network interfaces in an app

I wrote an app that is triggering a Sony qx smartphone attachable camera over wifi. However I need to transfer the images off the phone over another local network in real time. Since the wifi card is being used for qx connection I need to be able to use ethernet over usb for transferring images off the phone. Http requests will be used to trigger the camera and send the images off the phone.
Is it possible in one android app on a phone with two network interfaces setup to specify for certain http requests to use one network interface and for others to use another network interface ? Does this need to be done through routing tables, not java?
The phone I'm using is a rooted nexus 6p.
Update:
Currently, I was able to get an Ethernet adapter working with the device (Nexus 6P). The device is connected to a local network over Ethernet. When the Wi-Fi interface is off, I can ping all devices on the local network the device is connected to over Ethernet. However, I am unable to access the web servers (Not using DNS) of any of the devices on that network (which I know they are running), i.e. Http via a browser app. The nexus 6p is connected to the network over Ethernet via a Ubiquiti Station. This seems to be a routing issue.
I can tether(usb interface) and use Wi-Fi in one app, so that leads me to believe it is possible to use Ethernet and Wi-Fi.
Update2:
After more testing, it seems to be that it is a permissions issue. Since when I ping the network the device is connected to over Ethernet without first running su in the terminal the network doesn't exist. However, when I run su then ping, I can ping the network. Thus it seems my app needs to get superuser permission before accessing Ethernet. I've granted it superuser access, but nothing has changed. I read that simply running su isn't enough from one of the comments in this post. This is because su just spawns a root shell that dies. This also explains why I couldn't access any of the web servers on this network via a browser app. Is it possible to grant my app access to the Ethernet interface when making HTTP calls like give HttpURLConnection root access, if that makes any sense (running su doesn't work)? There seems to definitely be a solution since HttpURLConnection can make calls over the USB tethering interface (Nexus 6P calls it rndis0) fine.
Update 3:
I found online here , that I can make my app a System app (thought this might grant the app eth0 access). I just moved my app to /system/app and then rebooted. However, this didn't seem to give the app anymore privileges (thus not solving the problem) , or there is something else required to make the app system than just copying it to /system/app.
Update 4:
So I was able to get Ethernet working on every app without root permissions! It seemed to be that it only works over DHCP and does not like static connections, which I was using. It works with Wi-Fi enabled, however, I cannot contact any of the devices on the Wi-Fi network when Ethernet is enabled. Is there a way around this? Does it have to do with setting two default gateways?
Since you were programming in Nexus 6P, you can try to use the new API added in ConnectivityManager to select the ethernet as your preferred network connection for your process.
Since I can't build the similar environment like yours, I am not sure if it works. It's just a suggested solution, totally not tested and verified.
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
Network etherNetwork = null;
for (Network network : connectivityManager.getAllNetworks()) {
NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network);
if (networkInfo.getType() == ConnectivityManager.TYPE_ETHERNET) {
etherNetwork = network;
}
}
Network boundNetwork = connectivityManager.getBoundNetworkForProcess();
if (boundNetwork != null) {
NetworkInfo boundNetworkInfo = connectivityManager.getNetworkInfo(boundNetwork);
if (boundNetworkInfo.getType() != ConnectivityManager.TYPE_ETHERNET) {
if (etherNetwork != null) {
connectivityManager.bindProcessToNetwork(etherNetwork);
}
}
}
Just to give a little more explanation on how this finally got solved.
Utilizing #alijandro's answer I was able to switch back and forth between Ethernet and Wi-Fi in one app. For some reason for the Ethernet to work it required the network gateway to supply DHCP address, not static. Then since the bindProcessToNetwork, used in #alijandro's answer is per-process, I decided to split communications with the QX camera into a Service that runs in a separate Process. The main Application (another process) would post images over Ethernet to a local network. I was successfully able to contact the devices on the local network via HTTP over Ethernet while simultaneously triggering the QX over Wi-Fi. Currently, I used Messenger to communicate using IPC to tell the QX triggering Service what methods to call.
Most of android tv boxes can use wifi and ethernet together. In my device, i can enable ethernet from this path ---
Settings -> More ... > Ethernet ---
But your device wont have a menu like that as i understand. So you should make an app to do that. This application needs to access some system specific resources so your device needs to be rooted or application needs to signed with system signature.
Also this topic can help you link
There is an easy way to do this that will answer the OP's original question about how to do this with a single application (not two separate app processes) using ConnectivityManager.requestNetwork().
The docs for ConnectivityManager.requestNetwork() allude to this:
... For example, an application could use this method to obtain a
connected cellular network even if the device currently has a data
connection over Ethernet. This may cause the cellular radio to consume
additional power. Or, an application could inform the system that it
wants a network supporting sending MMSes and have the system let it
know about the currently best MMS-supporting network through the
provided NetworkCallback. ...
For OP's scenario of using Wi-Fi for some traffic and ethernet for other traffic one only needs to call ConnectivityManager.requestNetwork() twice with two separate requests. One for TRANSPORT_WIFI and one for TRANSPORT_ETHERNET. The operative item here is we need a way to uniquely identify these networks. For OP's scenario, we can use transport type.
final NetworkRequest requestForWifi =
new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build();
final NetworkRequest requestForEthernet =
new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
.build();
final ConnectivityManager connectivityManager = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkCallback networkCallbackWifi = new NetworkCallback() {
#Override
void onAvailable(Network network) {
// Triggers when this network is available so you can bind to it.
}
#Override
void onLost(Network network) {
// Triggers when this network is lost.
}
};
final NetworkCallback networkCallbackEthernet = new NetworkCallback() {
#Override
void onAvailable(Network network) {
// Triggers when this network is available so you can bind to it.
}
#Override
void onLost(Network network) {
// Triggers when this network is lost.
}
};
connectivityManager.requestNetwork(requestForWifi, networkCallbackWifi);
connectivityManager.requestNetwork(requestForEthernet, networkCallbackEthernet);
Then, once the callbacks trigger, you can then in the pertinent code (e.g. OP's code for transferring images), listen for onAvailable(Network network) and use the provided Network with Network.OpenConnection() to connect to an HTTP server using that network.
This would allow you to connect to two separate Networks from the same application.

How to get list of devices connected to my Wi-Fi in android?

I need to get the list of devices (and possible details of them as well) that are connected to the Wi-Fi which is I have connected to. I don't need to connect and chat with any of them. I'm going through this link http://developer.android.com/training/connect-devices-wirelessly/wifi-direct.html#fetch.
Is wifi p2p connection works for my requirement? How do I get the list of connected devices on the device with no Wifi-Direct feature? Do my app needs to be installed on other devices in order to use wifi p2p connection? I have tried this https://github.com/rorist/android-network-discovery but it is force closing on launch of app. I've seen same kind of apps on playstore like Fing. How did they do this?
Please help me. Thanks in advance.
manager=(WifiP2pManager)getSystemService(WIFI_P2P_SERVICE);
channel=manager.initialize(this, Looper.getMainLooper(),null);
When PEERS CHANGE.. call..
manager.requestPeers(channel, new WifiP2pManager.PeerListListener() {
#Override
public void onPeersAvailable(WifiP2pDeviceList wifiP2pDeviceList) {
Log.e("peer num", "" + wifiP2pDeviceList.getDeviceList().size());
devices.clear();
devices.addAll(wifiP2pDeviceList.getDeviceList());
for(WifiP2pDevice device:wifiP2pDeviceList.getDeviceList()){
//Log.e("device ",device.toString());
dnames.clear();
daddresses.clear();
dnames.add(device.deviceName);
daddresses.add(device.deviceAddress);
}
}
});

Categories

Resources