I am currently working on an app which connects to an communication pod through wifi (no internet) but my app also needs cellular connection for internet access.
I tried achieving it by adding transport network capabilities TRANSPORT_CELLULAR, but it worked only for devices with wifi assistant(switches between wifi and cellular data as the network strength),
isn't there anyway to achieve it simultaneously which works for every device?
Example will be good.
mConnectivityManager = (ConnectivityManager)mLoginActivity.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder request = new NetworkRequest.Builder();
request.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
request.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
mConnectivityManager.registerNetworkCallback (request.build(), new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
mConnectivityManager.bindProcessToNetwork(network);
}
});
Related
I'm currently developping my first app in java.
This app requires a direct connection with my BL652, which doesn' t accept any kind of pairing option. That being said, I'm stuck with the code below, which still tries to pair with my bluetooth device instead of just connecting. Therefore, I wanted to know what am i supposed to do in order to make a connection that doesnt require pairing.
Thanks in advance for any response.
String mac_address = "DA:72:21:29:0F:F0";
private static final UUID MY_UUID = UUID.fromString("E54B0002-67F5-479E-8711-B3B99198CE6C");
lvNewDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
BluetoothDevice device = (BluetoothDevice) mBluetoothAdapter.getRemoteDevice(mac_address);
try {
socket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
socket.connect();
} catch (IOException e) {
e.printStackTrace();
}
I'm not sure about connection to external hardware but it's definetly possible to connect 2 phones without pairing. I made it using Android Nearby Connections . And yeah it's basically working with BLE. As far as I know it's possible to connect to RaspberryPi using that API.
Bluetooth devices can be made to communicate with each other using master-slave configuration. I first tried with two BLE-HC05s, made one as master and the other as slave, and as expected the master is able to send data, slave is able to receive data, that can be seen using the Serial Monitor in Arduino IDE. I have developed a similar app, which connects to a BLE-HC05 device, sends and receives data. But since you are trying to get data or send data to the App on your phone, Android will not support such unpaired anonymous communications. If you are having trouble with connection or pairing Bluetooth device and your app, I may help you with that. But as far as Bluetooth communication without pairing is concerned, you may not be able to find a way.
Edit: The code to connect any bluetooth device, like BLE-HC06 as you have mentioned, is 1234 (Only if you have not changed it)
I have a deployed app that is failing on Android 9. Part of its function is to configure a module over an Access Point network to allow that that module to connect to the users home network.
I have code that detects and connects to the correct WIFI network, but when I attempt to open a socket to the device, it fails - only on Android 9 and only if mobile data is enabled. If I manually disable mobile data on the device everything runs fine.
Socket open() {
Socket sock = new Socket(Proxy.NO_PROXY);
try {
sock.bind(new InetSocketAddress(localIpAddress(), 50000));
} catch (IOException e) {
activity.logContent("Warning: Failed to bind socket : " + e.toString());
}
try {
sock.connect(new InetSocketAddress("192.168.17.1", 5555), (int)5000);
} catch (IOException e) {
// This catch fires when Mobile Data is on.
activity.logContent("Connected to " + activity.mWifiManager.getConnectionInfo().getSSID());
activity.logContent("Couldn't open socket : " + e.toString());
}
return sock;
}
I have tried this with and without the Proxy.NO_PROXY and with and without the bind() call. If the bind call is missing the error implies that the socket is attempting to connect over the cell network. (Note: activity.logContent() is an on-screen log so it is easier to see what is happening when not connected to a debugger).
Any ideas what is going wrong?
After a few days of imprecations I believe I have come to the identification of the problem and therefore to the solution:
The problem occurs due to some changes in the version of android (I presume to be 9.0 even if other changes had occurred on API 21), in particular on the creation of the socket, if the system detects that there is a "better" network (access to internet, high signal, etc, etc) socket creation refers to that network and no longer to the wifi network you would like.
I looked for ways to force the creation of the socket on the wifi network (which is the network I want) and the only way I found is this:
Simply put instead of:
Socket sock = new Socket ();
Do:
ConnectivityManager connectivity = (ConnectivityManager) MyApp.getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null)
{
for (Network network : connectivity.getAllNetworks())
{
NetworkInfo networkInfo = connectivity.getNetworkInfo(network);
if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI)
{
if (networkInfo.isConnected())
{
Socket sock = network.getSocketFactory().createSocket();
}
}
}
}
Practically browse the networks present in the device and when you find your active wifi you do nothing but take advantage of this function to get the right socket for sure:
getSocketFactory().createSocket()
Now you have the working socket!
In my case it now works perfectly, if someone finds better solutions, it is welcome, but for now it is the only way I have found to make everything work as in the previous version of android.
In Android 9 there a security config about network: Android security config
Adding your domain in network_security_config might solve your problem. I had this in my network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">119.xxx.xxx.xxx</domain>
</domain-config>
</network-security-config>
I am not sure about the exact reason of why this is happening. However, when you are turning on your mobile data and you are only connected to the internet using your mobile data (considering your wifi is turned off), it gets the IP address from the cellular network which is no more connected in your home network. Hence, this is trivial to expect such timeout scenarios, because, it cannot reach the private IP addresses of your home network starting with 192.168.....
Now my confusion is that even if the mobile data is turned on, and both wifi and mobile data is turned on at the same time, the device should connect to the wifi as a default behavior.
Hence I would like to suggest you check the following.
Android 9 (Pie) introduces special Wifi preference, which prevents connecting to public networks automatically. You might consider checking the settings.
Please check the IP address of your device and check if it has some IP address starting with 192.168..... If not, then definitely, you are getting your IP address from your cellular network and hence it cannot reach your private IP addresses of the home network.
I am recently working on a project that requires sending a command from my android mobile app to the android things on my raspberry pi 3. How can I achieve this through a WiFi connection?
I only need to send a String to the device.
If one of your devices isn't connected to internet, you could :
Option 1 :
use Google Nearby Connections API , the API choose the best way to communicate (eg: Bluetooth, Wifi...).
See https://github.com/googlesamples/android-nearby/tree/master/connections
Option 2 :
Use Socket to communicate but your devices need to be on the same network. If they aren't connected to the same network, you can connect them using WIFI P2P.
Using Android Things, you can use the Nearby Messages API, which gives you the ability to communicate to and transfer messages between two Android devices within their apps. Here's a code snippet:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
mMessageListener = new MessageListener() {
#Override
public void onFound(Message message) {
Log.d(TAG, "Found message: " + new String(message.getContent()));
}
#Override
public void onLost(Message message) {
Log.d(TAG, "Lost sight of message: " + new String(message.getContent()));
}
}
mMessage = new Message("Hello World".getBytes());
}
#Override
public void onStart() {
super.onStart();
...
Nearby.getMessagesClient(this).publish(mMessage);
Nearby.getMessagesClient(this).subscribe(mMessageListener);
}
#Override
public void onStop() {
Nearby.getMessagesClient(this).unpublish(mMessage);
Nearby.getMessagesClient(this).unsubscribe(mMessageListener);
...
super.onStop();
}
If you use system like Raspbian you can transform your Raspberry into a server.Then, You will have different ways to send your command:
Option 1: Set up an Http server on your raspberry (PHP, NodeJS, JEE, ...) and send command via HTTP Request.
Option 2: Set up a Socket Server on your raspberry (Socket.io, raw socket, ...) and send command via socket client
Option 3 Set up MQTT Server on your raspberry and send command via MQTT client (this last option is the way to go when talking about Internet of Things). Note that the program which receive command should implement MQTT Client as MQTT is based on pub/sub pattern.
You can use nanoHttpd on Android things and other library such as retrofit or volley on the Android device.
Check out this example for controlling a car via an Http API: https://github.com/plattysoft/IotCar
I'm trying to connect to a WiFi (open network) which couldn't have Internet access and I having some problems with this.
When the Wifi has internet, my code work 100% for all devices. But, when the Wifi has no internet, some devices doesn't respond my code (below) correctly.
List<WifiConfiguration> wifiConfigurations = wifiManager.getConfiguredNetworks();
int i = -1;
for (WifiConfiguration iWifiConfig : wifiConfigurations) {
String wifiConfigSSID = iWifiConfig.SSID.replace("\"", "");
if (SSID_REGISTERED.equals(wifiConfigSSID)) {
i = iWifiConfig.networkId;
}
}
wifiManager.disconnect();
//I already tried call "Thread.sleep(5000);" here.
wifiManager.enableNetwork(i, true);
//I already tried call "Thread.sleep(5000);" here.
wifiManager.reconnect();
//I already tried call "Thread.sleep(5000);" here.
I noticed I'm having problems in devices that show a confirmation dialog for Wifi without internet (Dialog Wifi without Internet Confirmation). In those devices, the reconnect doesn't return error, and the phone show that is connected at the Wifi, but I can't reach my server in the lan network.
For all other devices, that doesn't have this dialog confirmation, my code work 100%.
We have an app we are making that needs to switch to cellular for some requests even when WiFi is connected.
According to the ConnectionManager documentation these following methods are now deprecated, but is not so clear on what to use instead.
public void useMobileNetworkMode(Context context) {
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.setNetworkPreference(ConnectivityManager.TYPE_MOBILE);
}
public void useDefaultNetworkMode(Context context) {
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.setNetworkPreference(ConnectivityManager.DEFAULT_NETWORK_PREFERENCE);
}
Do these methods still work in android 5/6? and if anyone has info or something to replace these methods with I would be very grateful!
Ok little bit more on the problem :)
I have managed to investigate ConnectivityManager and can see the networks using :
Network networkToUse = null;
Network[] networks;
networks = cm.getAllNetworks();
for (Network network : networks) {
NetworkInfo ni = cm.getNetworkInfo(network);
Log.e("NETWORKINFO", ni.getType() + " " + ni.getExtraInfo());
if (ni.getType()== ConnectivityManager.TYPE_WIFI) {
Log.e("NETWORKINFO", "isWifi");
if (ni.isConnected()) {
Log.e("NETWORKINFO", "and is connected");
if (networkToUse == null) {
networkToUse = network;
}
}
}
if (ni.getType()== ConnectivityManager.TYPE_MOBILE) {
Log.e("NETWORKINFO", "HasMobile");
if (ni.isConnected()) {
Log.e("NETWORKINFO", "and is connected");
networkToUse = network;
}
}
}
It is here I kind of get stuck because I can't logically see a way of telling the app to use one of these networks when performing a HttpsURLConnection from URL.openLink();.
UPDATE:
I have just noticed that the mobile one disappears shortly after WiFi connects. There is a moment where I get both but not for long.
I have also tried this:
final ConnectivityManager connection_manager =
(ConnectivityManager)httpsClient.getCheckoutController().getCheckout().getCurrentActivity().getApplication().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder request = new NetworkRequest.Builder();
request.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
connection_manager.registerNetworkCallback(request.build(), new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
Log.e("NETWORKINFO", "FOUND A CELLULAR NETWORK " + connection_manager.getNetworkInfo(network));
}
});
request = new NetworkRequest.Builder();
request.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
connection_manager.registerNetworkCallback(request.build(), new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
Log.e("NETWORKINFO", "FOUND A WIFI NETWORK "+connection_manager.getNetworkInfo(network));
}
});
but as with the "list" of networks" in previous try I only ever 1 callback, even if mobile data is on as well.
UPDATE;
Ok I seem to see mobile sometimes using above method. but it seems to create API level spaghetti hell. It sometimes also takes a very long time for the mobile callback to fire. I wonder if this is because it has to wake up the cellular modem and wait for it's handshake or something?
UPDATE;
I had another possible suggestion using Sockets (something I have little experience with..)
Does anyone know if it is possible to build a CELLULAR SSL connection socket to do https requests using HttpsURLConnection.getSocketFactory() and SSLSocket ?
Any info would be very welcome in this week long quest :D
UPDATE:
Found a good and categorical answer from someone at google:
How to stay connected through mobile network after WIFI is connected on Android?
However after implementation, i get a network callback for the mobile but when i open URL connection and perform a request it seems to get stuck for ages (about 4 minutes) before i get the response.
I have a Huawei 5.0.1 phone, which is the highest i have available. Obviously this is not good. However it is not tested on 5.1 galaxy S6 and works.. so could be the phone.
According to the Android documentation it is no longer working in Android version 5 and above.
This method was deprecated in API level 21.
Functionality has been removed as it no longer makes sense, with many more >than two networks - we'd need an array to express preference. Instead we >use dynamic network properties of the networks to describe their >precedence.
Found a good and categorical answer from someone at google: How to stay connected through mobile network after WIFI is connected on Android?
(Link is in edited info above)
However after implementation, i get a network callback for the mobile but when i open URL connection and perform a request it seems to get stuck for ages (about 4 minutes) before i get the response.
I have a Huawei 5.0.1 phone, which is the highest i have available. Obviously this is not good. However it is not tested on 5.1 galaxy S6 and works.. so could be the phone.