Callback for ConnectivityManager not working in BlueStacks 5 emulator - android

In order to get notified when the device connects/disconnects from internet, I took the following approach:
ConnectivityManager connectivityManager = activity.getSystemService(ConnectivityManager.class);
ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(#NonNull Network network) {
super.onAvailable(network);
try {
activity.runOnUiThread(() -> {
tvNoInternet.animate().alpha(0f).setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
MiscellaneousUtils.hideView(tvNoInternet, View.GONE);
}
});
behaviour.onConnected();
// behaviour is an interface named NetworkConnectionBehaviour (check the following snippet for its implementation)
});
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
#Override
public void onLost(#NonNull Network network) {
super.onLost(network);
try {
activity.runOnUiThread(() -> {
if (isInternetConnected(activity)) {
// check internet connection status because onLost() is called
// after onAvailable() when the device automatically switches
// internet connection from cellular to wifi
return;
}
tvNoInternet.animate().alpha(1f).setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
MiscellaneousUtils.showView(tvNoInternet);
}
});
behaviour.onDisconnected();
});
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
};
try {
NetworkRequest networkRequest = getNetworkRequest();
// implementation of getNetworkRequest() is added in next snippet
connectivityManager.registerNetworkCallback(networkRequest, networkCallback);
} catch (Exception e) {
Toast.makeText(activity, "Unexpected interruption! please try again later", Toast.LENGTH_SHORT).show();
}
Interface NetowrkConnectionBehaviour:
public interface NetworkConnectionBehaviour {
void onConnected();
void onDisconnected();
}
Implementation of getNetworkRequest():
public static NetworkRequest getNetworkRequest() {
return new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.build();
}
This approach is working in all physical devices and emulator of android studio.
However, if someone runs the app on Bluestacks 5 emulator, the callbacks of ConnectivityManager aren't called at all. And it does not produce any exception either.
Am I missing something here? Is there a different way to use ConnectivityManager for BlueStacks?
NOTE: It shows same behaviour for gameloop emulator too.

The solution is to remove transport types: TRANSPORT_WIFI and TRANSPORT_CELLULAR since the BlueStacks 5 Emulator does not recognize its connection to be one of those transport types.
The capability NET_CAPABILITY_INTERNET will ensure that the connection is working and has access to the internet as per docs:
Indicates that this network should be able to reach the internet.
The code for the NetworkRequest now should be as follows:
public static NetworkRequest getNetworkRequest() {
return new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
}

Related

Testing network connectivity in Android 11 - not available DNS

I have this code in Android Service:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!isCurrentlyRunning()) {
currentlyRunning = true;
ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder builder = new NetworkRequest.Builder();
connectivityManager.registerNetworkCallback(
builder.build(),
new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
Log.d(TAG, "Start UpdateService after connectivity up");
try {
if (!UpdateService.isCurrentlyRunning()) {
if (Properties.DEBUG)
Log.d(TAG, "UpdateService is not running, try to start");
UpdateService.startService(getApplicationContext());
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
#Override
public void onLost(Network network) {
Log.d(TAG, "Stop UpdateService after connectivity lost");
try {
if (UpdateService.isCurrentlyRunning()) {
if (Properties.DEBUG)
Log.d(TAG, "UpdateService is running, sometimes need to redesigned stop service");
UpdateService.stopService(getApplicationContext());
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
);
}
return START_STICKY;
}
It would be all fine, but device is connected over DHCP and when onAvailable function is executed, its still not available DNS resolving.
How is the best way to wait (and check it during this waiting) for DNS resolver? I am thinking about for loop and sleep (and trying to connect for some web page during this loop), but during this sleeping is sleeping whole service and this solution I dont like it.
Thank you
D

How to turn on/off wifi hotspot programmatically in Android 8.0 (Oreo)

I know how to turn on/off wifi hot spot using reflection in android using below method.
private static boolean changeWifiHotspotState(Context context,boolean enable) {
try {
WifiManager manager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
Method method = manager.getClass().getDeclaredMethod("setWifiApEnabled", WifiConfiguration.class,
Boolean.TYPE);
method.setAccessible(true);
WifiConfiguration configuration = enable ? getWifiApConfiguration(manager) : null;
boolean isSuccess = (Boolean) method.invoke(manager, configuration, enable);
return isSuccess;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
But the above method is not working Android 8.0(Oreo).
When I execute above method in Android 8.0, I am getting below statement in logcat.
com.gck.dummy W/WifiManager: com.gck.dummy attempted call to setWifiApEnabled: enabled = true
Is there any other way to on/off hotspot on android 8.0
I thought the LocalOnlyHotspot route was the way to, but as #edsappfactory.com said in the comments - it only gives closed network, no internet access.
In Oreo hot-spotting/tethering moved to ConnectionManager, and its annotated #SystemApi, so (nominally) inaccessible.
As part of something else I was doing, I made an app and put it on github here. It uses reflection to get at the function and DexMaker to generate a subclass of ConnectionManager.OnStartTetheringCallback (which is also inaccessible).
Think it all works okay - bit rough around the edges, so please feel free to make better!
Relevant bits of code are in:
MyOreoWifiManager and;
CallbackMaker
I lost patience trying to get my DexMaker-generated callback to fire the MyOnStartTetheringCallback so all that code is in disarray and commented out.
Finally I got the solution.
Android 8.0, they provided public api to turn on/off hotspot. WifiManager
Below is the code to turn on hotspot
private WifiManager.LocalOnlyHotspotReservation mReservation;
#RequiresApi(api = Build.VERSION_CODES.O)
private void turnOnHotspot() {
WifiManager manager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
manager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {
#Override
public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
super.onStarted(reservation);
Log.d(TAG, "Wifi Hotspot is on now");
mReservation = reservation;
}
#Override
public void onStopped() {
super.onStopped();
Log.d(TAG, "onStopped: ");
}
#Override
public void onFailed(int reason) {
super.onFailed(reason);
Log.d(TAG, "onFailed: ");
}
}, new Handler());
}
private void turnOffHotspot() {
if (mReservation != null) {
mReservation.close();
}
}
onStarted(WifiManager.LocalOnlyHotspotReservation reservation) method will be called if hotspot is turned on.. Using WifiManager.LocalOnlyHotspotReservation reference you call close() method to turn off hotspot.
Note:
To turn on hotspot, the Location(GPS) should be enabled in the device. Otherwise, it will throw SecurityException
As per Jon suggestion, I got another way to enable WifiHotSpot in Android Oreo and above.
public boolean enableTetheringNew(MyTetheringCallback callback) {
File outputDir = mContext.getCodeCacheDir();
try {
proxy = ProxyBuilder.forClass(classOnStartTetheringCallback())
.dexCache(outputDir).handler(new InvocationHandler() {
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
switch (method.getName()) {
case "onTetheringStarted":
callback.onTetheringStarted();
break;
case "onTetheringFailed":
callback.onTetheringFailed();
break;
default:
ProxyBuilder.callSuper(proxy, method, args);
}
return null;
}
}).build();
} catch (IOException e) {
e.printStackTrace();
}
ConnectivityManager manager = (ConnectivityManager) mContext.getApplicationContext().getSystemService(ConnectivityManager.class);
Method method = null;
try {
method = manager.getClass().getDeclaredMethod("startTethering", int.class, boolean.class, classOnStartTetheringCallback(), Handler.class);
if (method == null) {
Log.e(TAG, "startTetheringMethod is null");
} else {
method.invoke(manager, TETHERING_WIFI, false, proxy, null);
}
return true;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return false;
}
private Class classOnStartTetheringCallback() {
try {
return Class.forName("android.net.ConnectivityManager$OnStartTetheringCallback");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}

android wifi-direct connect success callback calling repeatedly

i trying to connect to one wifi device using wifidirect but when i run following code it's always show connected device notification infinitely may i know where i made mistake
Here is my code snippet
if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
final Context ctx = context;
//showing this pop up message always can you help me to understand this issue please
Toast.makeText(ctx, "WIFI_P2P_PEERS_CHANGED_ACTION",Toast.LENGTH_LONG).show();
if (mManager != null) {
mManager.requestPeers(mChannel, new WifiP2pManager.PeerListListener() {
#Override
public void onPeersAvailable(WifiP2pDeviceList peers) {
for ( WifiP2pDevice peer : peers.getDeviceList()) {
WifiP2pDevice device=peer;
String serverName = "Android_f9c4";
if(device.deviceName.equals(serverName)){
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
mManager.connect(mChannel,config ,new ActionListener() {
//whats wrong here
#Override
public void onSuccess() {
// This fire always
Toast.makeText(ctx, "connected",Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(int reason) {
// TODO Auto-generated method stub
Toast.makeText(ctx, "Not connected",Toast.LENGTH_LONG).show();
}
});
}
}
}
});
}
}
}
use
ArrayList<WifiP2pDevice> list=peers.getDeviceList();
for( WifiP2pDevice peer : list)
in place of
for ( WifiP2pDevice peer : peers.getDeviceList()) {

Is this a bad hack? Is there a better way to do this?

I have some code that works, but just feels like a bad idea. I'm wondering if there's a better way to do this.
The Problem (You could honestly probably skip this and go to the code)
I have a bluetooth LE app that occasionally needs to write characteristics as fast as possible to multiple BLE devices (The app is a controller for a smart lamp). My current set up for BLE communication is to use a BluetoothContorller custom singleton which handles all communication, and Lamp objects which ask the controller to write to the lamps and hand off their BluetoothGatt and BluetoothGattCharacteristic to the controller.
The Solution
handler.post(new Runnable() {
#Override
public void run() {
if (control != null) {
synchronized (BluetoothController.this) {
Logger.d("BluetoothController", "Waiting......");
for(int i = 0; i < 100; i++){
if(isWaiting)
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
else
break;
}
isWaiting = true;
Logger.d("BluetoothController", "Done waiting.");
}
control.setValue(message);
mBluetoothGatt.writeCharacteristic(control);
}
}
});
And inside my gatt callback:
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
if(isWaiting){
isWaiting = false;
}
}
Now, this code works but all my experience as a programmer tells me that this code will cause me a lot of pain and surely there is a better.
EDIT: New Code using Handler.Callback and Messages
I've changed my code to do the waiting in the handle message callback, using Thread.wait() and notify(), but It seems like the messages are getting backed up in the queue, and the last one to execute still seems kind of random.
#Override
public void run() {
Looper.prepare();
handler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
synchronized (BluetoothController.this) {
if (shouldWait) {
isWaiting = true;
try {
BluetoothController.this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
isWaiting = false;
}
shouldWait = true;
}
return true;
}
});
Looper.loop();
}

Android internet connection checking [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Android - detect whether there is an Internet connection available
this is the code to check the internet availability on android device:
public boolean isInternetAvailable() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm.getActiveNetworkInfo() != null)
return cm.getActiveNetworkInfo().isConnected();
else
return false;
}
So this code is working correctly if no wifi or network available.
But if device is connected to wifi network but internet is not available then what should i do to check the internet is there or not?
any suggestion will be appreciated.
I do it like this:
I try to reach google.com and watch for response:
public static void isGoogleAvailable(final Handler handler)
{
new Thread()
{
private boolean hasGoogleResponded = false;
#Override
public void run()
{
new Thread()
{
#Override
public void run()
{
HttpGet requestForTest = new HttpGet("https://www.google.com/");
try
{
new DefaultHttpClient().execute(requestForTest);
hasGoogleResponded = true;
}
catch (Exception e)
{}
}
}.start();
try
{
int waited = 0;
while(!hasGoogleResponded && (waited < 60000))
{
sleep(100);
if(!hasGoogleResponded )
{
waited += 100;
}
}
}
catch(InterruptedException e)
{}
finally
{
if (hasGoogleResponded)
{
handler.sendEmptyMessage(1);
}
else
{
handler.sendEmptyMessage(0);
}
}
}
}.start();
}
Then I retrive messages in my handler:
Handler internetHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
if (msg.what == 1) //connected
{
}
else //not connected
{
}
}
};
I hope this helps.
You could try to ping a server like google (that should always exist)
see this topic
You can try
ConnectivityManager m;
m.getAllNetworkInfo();
First check internet connection,then others.
But sometimes its depends on app architecture.
If application needed wifi and you havent - you can not check internet because
it is not necessary

Categories

Resources