ConnectivityManager can't requestNetwork/bindProcessToNetwork in Oreo - java

After developing a working system in 6.0 (S6) I'm testing the same code in 8.0 (S9) and I've noticed that ConnectivityManager.requestNetwork() is no longer doing anything.
Here is the function I'm using:
public static void enableWifi() {
ConnectivityManager connectivityManager = (ConnectivityManager)
mContext.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder request = new NetworkRequest.Builder();
request.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
request.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
connectivityManager.requestNetwork(
request.build(),
new ConnectivityManager.NetworkCallback() {
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
public void onAvailable(Network network) {
connectivityManager.bindProcessToNetwork(network);
Log.i(TAG, "bindProcessToNetwork called");
}
},
30000
);
}
after calling this function, I check to see whether the connection has been switched to Wifi for 20 seconds:
wifiManager.setWifiEnabled(true);
enableWifi();
long start_time = System.currentTimeMillis();
while (!MainActivity.getNetworkClass(mContext).contains("WIFI")) {
if (System.currentTimeMillis() - start_time > 20000) {
Log.i(TAG, "connection timed out");
}
}
After the timeout I'm still on the 4G network, wifi is never truly enabled. All logs shown above are called, yet the network state never changes to Wifi.
The manifest:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
Edit:
After much frustration I was able to establish a connection once using this setup, but not again since. I am not sure where to even begin troubleshooting this and assume it's a bug in 8.0 until I find otherwise.

Related

Android wifi state permission

My app is communicating with another device by wifi.
I tried to ask all permissions at app's start, but is never asked about wifi.
By the way, every time I need to change wifi, user must give permission.
How can I ask for change wifi state permission once and never bother user again?
Sample of code that I used to change wifi is below
WifiConfiguration wifiConfig = new WifiConfiguration();
wifiConfig.SSID = String.format("\"%s\"", ssid);
if (!key.equals(""))
wifiConfig.preSharedKey = String.format("\"%s\"", key);
final int netId = wifiManager.addNetwork(wifiConfig);
Log.d("Network ID", Integer.toString(netId));
wifiManager.disconnect();
wifiManager.enableNetwork(netId, true);
wifiManager.reconnect();
The permission my phone is asked about below
It is Russian. Translation is "Would you give this app a permission to turn on/turn off WIFI?".
I tested it on another phone, and it keeps happening. Both phones is xiaomi and have their own android version MIUI.
Add this code snippet in AndroidManifest.xml:
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
And use this code:
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifi.setWifiEnabled(false); // activate/deactivate wifi
You only need to declare it in AndroidManifest.xml:
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
Android > 6.0 user prompted runtime permission is NOT required for CHANGE_WIFI_STATE, because it is one of the safe ones.
If something is still goes wrong, please provide code sample which you are using.
UPD:
Tested your code on Samsung J5 with Android 6.0 and everithing works fine.
Also you are using deprecated methods. You need to use something like this for >= Android.O
In manifest:
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />
And code:
WifiNetworkSpecifier.Builder builder = new WifiNetworkSpecifier.Builder();
builder.setSsid("SSID");
builder.setWpa2Passphrase("PASSWORD");
WifiNetworkSpecifier wifiNetworkSpecifier = builder.build();
NetworkRequest.Builder networkRequestBuilder1 = new NetworkRequest.Builder();
networkRequestBuilder1.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
networkRequestBuilder1.setNetworkSpecifier(wifiNetworkSpecifier);
NetworkRequest nr = networkRequestBuilder1.build();
final ConnectivityManager cm = (ConnectivityManager)
getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
ConnectivityManager.NetworkCallback networkCallback = new
ConnectivityManager.NetworkCallback() {
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
public void onAvailable(Network network) {
super.onAvailable(network);
Log.d("TEST", "onAvailable:" + network);
cm.bindProcessToNetwork(network);
}
};
cm.requestNetwork(nr, networkCallback);

How to check if I have enabled WIFI before downloading a file? [duplicate]

This question already has answers here:
How do I see if Wi-Fi is connected on Android?
(24 answers)
Closed 3 years ago.
I have a Button that downoad a File, and works fine. If I dont have Internet conection, the file doesnt download (obviously). The problem is that the app continues trying to download, instead of stop it.
I want to show a Toast saying "The device its not connected" or some stuff like that and NOT begin the download process then. I want a function that returns true or false if I have WIFI connection avaiable AT THE MOMENT or not
I try with the answers of these post: How to check currently internet connection is available or not in android , but the function retuns always true, even with Airplane mode.
I download the File with a DownloadManager and continues after download with a BroadcastReceiver.
Add this permission in Manifest file
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Following condition will help you
ConnectivityManager connManager = (ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo wifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (wifi.isConnected()){
// If Wi-Fi connected
}else{
Toast.makeText(getApplicationContext() /*Context field*/,"Please Connect to Wifi",Toast.LENGTH_SHORT).show();
}
Add this permission in Manifest file
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Use this condition to check if Wifi Connected or not
ConnectivityManager connManager = (ConnectivityManager);getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (mWifi.isConnected()) {
// Do whatever
}
Here's Network connectivity checking code
public class NetworUtil {
private static NetworkInfo activeNetwork;
public static boolean isInternetConnected(Context context) {
if (context == null)
return false;
else {
ConnectivityManager cm =(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
}
}
}
Below permission must be required in the AndroidManifest file.
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Wifi Hotspot creation fails in oreo

I'm working on a simple system app in Oreo AOSP to turn ON wifi Hotspot with predefined SSID and preshared key.
As my APP is built as a system app so i don't need reflection.
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
boolean result = false;
WifiManager mwifiManager;
mwifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
try {
Method method = mwifiManager.getClass().getMethod("getWifiApConfiguration");
WifiConfiguration netconfig = (WifiConfiguration) method.invoke(mwifiManager);
netconfig.SSID = "DummyApp";
netconfig.preSharedKey = "1234567890";
netconfig.allowedKeyManagement.set(4);
mwifiManager.setWifiEnabled(false);
method = mwifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
result = (boolean) method.invoke(mwifiManager, netconfig, true);
if (!result) {
Toast.makeText(this, "Hotspot creation failed", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Wifi Enabled", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
finish();
}
#Override
protected void onResume() {
super.onResume();
}
}
AndroidManifest.xml
android:protectionLevel="signature|privileged"
android:sharedUserId="android.uid.system">
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- for wifi -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.TETHER_PRIVILEGED" />
Wifi Should turn ON but getting following result:
Toast Message: Hotspot creation failed
Logcat: WifiManager: PACKAGE_NAME attempted call to setWifiApEnabled: enabled = true
update1: How to turn on/off wifi hotspot programmatically in Android 8.0 (Oreo)
I have tried above changes. It will turn on Hotspot locally but no custom SSID and password.
update2: After getting input from #Mr.AF.
Method setConfigMethod = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
......code snip.........
netconfig.allowedKeyManagement.set(4);
Method Method = mWifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
HOTSPOT Creation FAiled
To turn ON Portable HotSpot in Android Nougat and below following code works.
Method method = mwifiManager.getClass().getMethod("getWifiApConfiguration");
WifiConfiguration netconfig = (WifiConfiguration) method.invoke(mwifiManager);
method = mwifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
result = (boolean) method.invoke(mwifiManager, netconfig, true);
Above API is deprecated in Oreo.
Following is a #system hidden API in oreo, If the android application is built as a system app then only below API code can be accessed. In my case, I can use the below API.
ConnectivityManager oncm = (ConnectivityManager)ontext.getSystemService(Context.CONNECTIVITY_SERVICE);
oncm.startTethering(ConnectivityManager.TETHERING_WIFI, true, new ConnectivityManager.OnStartTetheringCallback() {
#Override
public void onTetheringStarted() {
super.onTetheringStarted();
Log.i(TAG, "Hotspot is successfully opened");
}
#Override
public void onTetheringFailed() {
super.onTetheringFailed();
Log.e(TAG, "Hotspot failed to open");
}
});
You don't need to use reflection for versions>=Oreo. After android's public exposed API startLocalOnlyHotspot. I've explained this answer in detail on this question on Stackoveflow.

Android BLE discovery issue

I'm developing and Android app with Bluetooth but sometimes I have problems with LE devices discovering: usually the discovery callback return me the the devices found but sometimes, stops working and does not return me the devices.
I tested the code (in debug mode) in different devices (Samsung, LG) and with different Android version (8.0, 6.0, 4.4) but the problem is the same, is not systematic and after some time, it return to works fine.
I have applied all the suggestions found in internet:
Android can't find any BLE devices
Bluetooth LE Scanning Sometimes Doesn't Find Devices
Android Bluetooth Low Energy code compatible with API>=21 AND API<21
but the problem persist.
Below a snips of manifest:
.
.
.
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-feature android:name="android.hardware.location.gps" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
.
.
.
and bluetooth code:
public BLEH_RES StartDiscovery()
{
.
.
.
CheckPermission();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
return(scanLeDevice21(true));
else
return(scanLeDevice18(true));
}
/**
* Scan BLE devices on Android API 20 to last version (Android 9.0)
*
* #param enable Enable scan
*/
#RequiresApi(21)
private BLEH_RES scanLeDevice21(boolean enable)
{
bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
if (bluetoothLeScanner == null)
return(BLEH_RES.BLE_NOT_SUPPORTED);
if (enable)
{
ScanSettings.Builder scanSettings = new ScanSettings.Builder();
scanSettings.setScanMode(SCAN_MODE_LOW_LATENCY);
bluetoothLeScanner.startScan(null, scanSettings.build(), BLEScanCallback);
}
else
bluetoothLeScanner.stopScan(BLEScanCallback);
return(BLEH_RES.OK);
}
/**
* Scan BLE devices on Android API 18 to 20
*
* #param enable Enable scan
*/
private BLEH_RES scanLeDevice18(boolean enable)
{
if(bluetoothAdapter == null)
return(BLEH_RES.BT_NOT_SUPPORTED);
if (enable)
{
bluetoothAdapter.startDiscovery();
bluetoothAdapter.startLeScan(mLeScanCallback);
}
else
{
bluetoothAdapter.cancelDiscovery();
bluetoothAdapter.stopLeScan(mLeScanCallback);
}
return(BLEH_RES.OK);
}
#RequiresApi(21)
private ScanCallback BLEScanCallback = new ScanCallback()
{
#Override
public void onScanResult(int callbackType, ScanResult result)
{
addDevice(result.getDevice(), result.getRssi(), result.getScanRecord().getBytes());
}
#Override
public void onScanFailed(int errorCode)
{
for(ErrorEvent ee:errorEventList)
ee.onError(BLEH_EVENT_ERROR.SCAN_FAILED);
}
};
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback()
{
#Override
public void onLeScan(final BluetoothDevice bluetoothDevice, int rssi,byte[] scanRecord)
{
addDevice(bluetoothDevice, rssi, scanRecord);
}
};
Can you suggest me anything to solve this problem?
Make sure that GPS is enabled all the time you searching devices. Also suggest you to watch this about BLE
https://youtu.be/jDykHjn-4Ng
I solved my problem by following the suggestions in this link: https://stackoverflow.com/a/42267678/7006955
I add to my code all the code suggested and it works fine also in Android 4

IOException Unable to resolve host,No address associated with hostname

I am working on Sony Remote camera which is connected using WiFi.I need to click a picture using a camera and then upload it to my FTP server which is in another activity.for than I need to disconnect my camera wifi and connect to the another wifi network or mobile data.when I connect to the another wifi/mobile data and going to upload the picture on FTP server I got this error.
IOException Unable to resolve host No address associated with hostname
When a close application and start again, And then directly upload pictures without connecting/disconnection camera than it works fine.
someone, please tell me how can I solve this, because I checked each and every solution on stack overflow and not one solution work for me.
I added bellow permissions
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
Connection to a network is not inmediate.
Also, if the desired network has no internet connection, in recent versions of Android it will not connect (if the connection is made by a user, a popup shows a confirmation to connnect).
I solved both problems using Android APIs (2 versions, one for API<21 and the other for API>=21).
Try this code (I'm using AndroidAnnotations for dependency injection, but is not required):
public class WifiHelper extends BroadcastReceiver {
#RootContext
Context context;
#SystemService
ConnectivityManager connectivityManager;
#SystemService
WifiManager wifiManager;
// For API>=21
private WifiHelperNetworkCallback wnc;
// For API<21
private boolean isBroadcastRegistered;
private String desiredSSID;
private Runnable callback;
public void enableNetwork(String ssid, int networkId, Runnable callback) {
desiredSSID = ssid;
wifiManager.enableNetwork(networkId, true);
configureNetworkRequest();
}
private void networkAvailable() {
// this method will be called when the network is available
callback.run();
}
private void configureNetworkRequest() {
if (android.os.Build.VERSION.SDK_INT >= 21) {
configureNetworkRequestAPI21();
} else {
configureNetworkRequestLegacy();
}
}
#TargetApi(21)
private void configureNetworkRequestAPI21() {
NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build();
if (wnc == null) wnc = new WifiHelperNetworkCallback(this, connectivityManager);
connectivityManager.requestNetwork(request, wnc);
}
private void configureNetworkRequestLegacy() {
unregisterReceiver();
connectivityManager.startUsingNetworkFeature(ConnectivityManager.TYPE_WIFI, null);
IntentFilter intent = new IntentFilter();
intent.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
intent.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
context.registerReceiver(this, intent);
isBroadcastRegistered = true;
}
#TargetApi(21)
private void disableNetworkRequest() {
if (android.os.Build.VERSION.SDK_INT >= 21) {
if (wnc != null) connectivityManager.unregisterNetworkCallback(wnc);
ConnectivityManager.setProcessDefaultNetwork(null);
} else {
unregisterReceiver();
}
}
private void unregisterReceiver() {
if (isBroadcastRegistered) {
context.unregisterReceiver(this);
isBroadcastRegistered = false;
}
}
// API<21
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
NetworkInfo networkInfo =
intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if(networkInfo.isConnected()) {
// Wifi is connected
if (desiredSSID.equals(getCurrentSSID())) {
// Callback and unregister
networkAvailable();
unregisterReceiver();
}
}
}
}
public String getCurrentSSID() {
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
if (wifiInfo != null && wifiInfo.getSupplicantState()== SupplicantState.COMPLETED) {
return ssidWithoutQuotes(wifiInfo.getSSID());
}
else return null;
}
protected static String ssidWithoutQuotes(String ssid) {
if (ssid == null) return null;
else if (ssid.startsWith("\"") && ssid.endsWith("\"")) {
return ssid.substring(1, ssid.length() - 1);
} else {
return ssid;
}
}
protected String getDesiredSSID() {
return desiredSSID;
}
#TargetApi(21)
public static class WifiHelperNetworkCallback extends ConnectivityManager.NetworkCallback {
public final String LOG_TAG = WifiHelper.class.getSimpleName();
private ConnectivityManager connectivityManager;
private WifiHelper wifiHelper;
public WifiHelperNetworkCallback(WifiHelper wifiHelper, ConnectivityManager connectivityManager) {
this.wifiHelper = wifiHelper;
this.connectivityManager = connectivityManager;
}
public void onAvailable(Network network) {
// Do something once the network is available
NetworkInfo info = connectivityManager.getNetworkInfo(network);;
Log.i(LOG_TAG, "networkcallback!! " + info.getExtraInfo());
String desiredSSID = wifiHelper.getDesiredSSID();
if (desiredSSID != null && desiredSSID.equals(ssidWithoutQuotes(info.getExtraInfo()))) {
ConnectivityManager.setProcessDefaultNetwork(network);
wifiHelper.networkAvailable();
}
}
}
}
You will need this permissions:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" android:maxSdkVersion="18"/>

Categories