Android 10 requestNetwork() takes too long displaying specified network - java

I'm trying to connect my Android 10 device to a WiFi network. I'm using the WiFiNetworkSpecifier API to describe the network properties I want to connect to. The connection goes well, but I see often that the prompt shown to the user is taking too long (from 2 to 28 seconds) to display the network I described with WifiNetworkSpecifier object.
Here is my code (it is the same as the Google example linked here -> https://developer.android.com/guide/topics/connectivity/wifi-bootstrap)
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest networkRequest = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setNetworkSpecifier(
new WifiNetworkSpecifier.Builder()
.setSsid(SSID)
.setWpa2Passphrase(psw)
.build()
)
.build();
networkCallback = new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(#NonNull Network network) {
if (WiFiCoordinator.this.listner != null){
WiFiCoordinator.this.listner.onConnected();
}
cm.bindProcessToNetwork(network);
}
#Override
public void onUnavailable() {
super.onUnavailable();
listner.onTestNetworkNotAvailable();
}
};
cm.requestNetwork(networkRequest, networkCallback);
The connection has no problem, but the time spent by the OS looking for the requested network is not ok for me. Is there any problem in my code?
Thanks a lot

Through comparative experiments, it is found that Android 11 can work as well as Android 9
I guess it's the Android 10 bug. Comparing the code of Android 11 and Android 10, we find that there is a difference in the request network process.

Related

Android Serial Drivers are not detected

I have an industrial computer running Android v7 with multiple serial outputs, I am trying to send packets using RS232 to my COM3 port (/dev/ttyS2) nevertheless I am unable to open a connection since my serial drivers are not detected.
The cable is well connected and I don't have any issues communicating when running a NodeJS script.
Here is the code used in the Android App
import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
/*[...]*/
public static UsbSerialPort usb2SerialEnum(Context context)
{
UsbSerialPort device = null;
// Find all available drivers from attached devices.
UsbManager manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(manager);
if (availableDrivers.isEmpty())
{
return null; // -> availableDrivers is always empty
}
/*[...]*/
}
protected void onCreate(Bundle savedInstanceState)
{
UsbSerialPort port = usb2SerialEnum(this);
if (port != null)
{
/*[...]*/
}
}
I always receive an empty list of available drivers, would you have any idea about what am I doing wrong or what I should try ?
I have been stuck on this issue for quite some time, any help is appreciated, thanks a lot !

How to connect paired bluetooth device on app startup in Android Studio?

Is there any way to automatically connect a specific device via Bluetooth LE on app startup?
I've been scrolling through stack overflow for the past few hours and have seen a number of similar questions, although majority are quite outdated and deal with reflections or other complex methods that I can't quite comprehend (these methods I've tried to implement, but not successfully, as I didn't really understand what was going on).
So far, I've managed to find the device by its friendly name, although I have no clue what to execute in that if statement. This is within my MainActivity:
protected void onCreate(Bundle savedInstanceState) {
...
if (bluetoothAdapter == null) {
Toast.makeText(getApplicationContext(),"Bluetooth not supported",Toast.LENGTH_SHORT).show();
} else {
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
if(pairedDevices.size()>0){
for(BluetoothDevice device: pairedDevices){
if (deviceName.equals(device.getName())) {
//Device found!
//Now how do I pair it?
break;
}
...
Assuming you've successfully identified the BlueToothDevice, you now need to connect to the GATT(Generic Attribute Profile), which allows you to transfer data.
Use the BlueToothDevice.connectGatt method. Using the first overload, the method takes in a Context , a boolean (false = directly connect, true = connect when available), and a BlueToothGhattCallback. The callback receives info from the device.
BlueToothGatt blueToothGatt = device.connectGatt(this, false, blueToothGattCallback);
An example to implement the callback:
BluetoothGattCallback blueToothGattCallback =
new BluetoothGattCallback()
{
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if(newState == BlueToothProfile.STATE_CONNECTED){
/* do stuff */
}
}
}
More details on the callbacks here.
Ended up scrolling through the source code for this app, particularly the SerialSocket, SerialService and SerialListener files which completely solved my problem.

How to retrieve active network information in android

I have been working on an android application.For one of the feature, I need the active network information(i.e. whether it's connected with Wi-Fi or mobile data). I got this piece of code from the internet.
NetworkInfo activeNetworkInfo = context.getSystemService(ConnectivityManager.class).getActiveNetworkInfo();
But this API is deprecated and I don't want to use any deprecated API.
After some more googling, I found that we should use ConnectivityManager.NetworkCallback instead. But I am not able to get an example of it. How can I use this?. Please help me if anyone having an idea about using ConnectivityManager.NetworkCallback
Check out this function in Kotlin
fun networkConnection(): Boolean {
var networkAvailable = false
val connectivityManager: ConnectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val network: Network = connectivityManager.activeNetwork!!
val networkCapabilities: NetworkCapabilities = connectivityManager.getNetworkCapabilities(network)!!
if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
networkAvailable = true
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
networkAvailable = true
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
networkAvailable = true
}
return networkAvailable
}
try the following code:
private void registerNetworkCallback(Context context) {
final ConnectivityManager manager =
(ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
manager.registerNetworkCallback(
new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
.build(),
new NetworkCallback() {
#Override
public void onAvailable(Network network) {
/** here to get the available info
this ternary operation is not quite true, because non-metered
doesn't yet mean, that it's wifi
nevertheless, for simplicity let's assume that's true
*/
Log.i("vvv", "connected to " + (manager.isActiveNetworkMetered() ? "LTE" : "WIFI"));
}
#Override
public void onCapabilitiesChanged(Network network,
NetworkCapabilities networkCapabilities){
/**here to get the change network info
Value is TRANSPORT_CELLULAR, TRANSPORT_WIFI,
TRANSPORT_BLUETOOTH, TRANSPORT_ETHERNET, TRANSPORT_VPN
*/
if(networkCapabilities.hasTransport("type")){
}
}
});
}
connectivityManager = (ConnectivityManager)
context.getSystemService(ConnectivityManager.class);
#RequiresApi(api = Build.VERSION_CODES.M)
private void getActiveNet() {
Network currentNetwork = connectivityManager.getActiveNetwork();
}
Note that "active network" is synonymous in android with "default network".
ConnectivityManager#getActiveNetworkInfo()
Returns details about the currently active default data network...
ConnectivityManager#registerDefaultNetworkCallback(NetworkCallback)
Registers to receive notifications about changes in the application's
default network...
Therefore using ConnectivityManager#registerDefaultNetworkCallback(NetworkCallback) you can listen for default (aka "active") network changes. Unfortunately, this only returns the Network object which does not have information regarding transport (Wi-Fi vs Cellular) in which case you'll need to make an additional call to ConnectivityManager#getNetworkCapabilities(Network) to get that info.
Here is an example:
final ConnectivityManager connectivityManager = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkCallback networkCallback = new NetworkCallback() {
#Override
void onAvailable(Network network) {
// Triggers when a default network is available.
NetworkCapabilities nc = connectivityManager.getNetworkCapabilities(network);
boolean isWifi = nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
boolean isCellular = nc.hasTransport(NetworkCapabilities. TRANSPORT_CELLULAR);
}
};
connectivityManager.registerDefaultNetworkCallback(networkCallback);

How do i check internet connectivity in remote android device?

This question might be a duplicate question, but i cant find proper solution.
I have chat app in which i set function for when remote android device on background mode it will get notification by FCM when new message will come(new node added in chatroom).
So
if remote device is in the foreground mode than it will get notification by app and its has definitely internet connectivity for this i can set message delivery successfully.
if remote device is in the background mode than it will get notification by FCM and its has definitely internet connectivity. for this i can also set message delivery successfully.
So how do i check that remote device is totally offline(no internet connection) or how to check FCM is not success to send notification ?
for example:
if(messegeReceiver(remote device) has no internet connectivity )
{
//here i want to change data in firebase//
}
else
{
//here i want to change data in firebase//
}
I have "Users" node in which every users set device_token while login the app.
You can device checking offline/online mode via set one param in your chat table. When user exit or minimize application then set states to 0 and maximum set to 1.Best way if possible you use firebase real-time database for online offline.
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
NetworkChangeReceiver receiver = new NetworkChangeReceiver();
regisenter code hereterReceiver(receiver, filter);
public static class NetworkChangeReceiver extends BroadcastReceiver {
public static boolean isOnline(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
//should check null because in air plan mode it will be null
return (netInfo != null && netInfo.isConnected());
}
public static boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivity = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
if (!isConnected) {
relativelayout_connection.setVisibility(View.GONE);
isConnected = true;
return true;
}
} else {
relativelayout_connection.setVisibility(View.VISIBLE);
}
}
}
} else {
relativelayout_connection.setVisibility(View.GONE);
isConnected = false;
return false;
}
return isConnected;
}
#Override
public void onReceive(final Context context, final Intent intent) {
// isNetworkAvailable(context);
if (isOnline(context)) {
} else {
relativelayout_connection.setVisibility(View.VISIBLE);
}
}
}
FCM does not guarantee that the push notification gets delivered. It completely depends upon various factors like internet connection (as you mentioned), OEM behavior, Doze mode etc.
In your case, you are trying to send messages via FCM from one device to another and shown messages in the form notifications just like any other chat application.
The only problem here is that the FCM does not provide you with delivery parameters in response (image attached) that you are looking for. It only gives count for number of notifications that has been accepted by the gateway i.e. FCM (success) and the count for number of notifications that has been rejected by the gateway (failure). It also gives the reason for rejection (error) message like NotRegistered, MissingRegistrationToken, etc and you can refer this for the same.
My suggestion here would be to have a handshake message in place that acknowledges the delivery of the push notification from the other device. As soon as you receive the push notification send a handshake message via FCM and that gets received by the first device which understands that the push notification has been delivered. In case if the device does not receive the handshake you assume that the message is yet to be delivered.
I hope this really helps you and please up vote the answer or accept the answer if you feel like doing so.

Google Analyrics track user if connected to the Internet

I just started learning Google Analytics for Android (v4). I am trying to measure how many users use my application with WiFi turned on when an activity is created. I am not sure if I am doing this correctly but I added a custom dimension for "Users are Connected" and used this code:
builder.setCustomDimension(1, isNetworkConnected() ? "True" : "False");
tracker.send(builder.setNewSession().build());
I look at the Google Analytics webpage and cannot see any information about this custom dimension on the "Realtime" navigation. I can see that the user count increased but no information about whether users are connected or not.
Thanks in advance.
Android has to check with isNetworkConnected. If the condition provided, you can run your request in this. This will assume internet is available and connected.
Implement this way:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
if(isNetworkConnected(this)){
// start a service related to internet or
// put your tracker to send data
tracker.send(builder.setNewSession().build()); // or any other methot you use to track app
}
}
public static boolean isNetworkConnected(Context context) {
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
return (cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isAvailable() && cm.getActiveNetworkInfo().isConnected());
}
}

Categories

Resources