With the release of API level 26, my app's core functionality broke, this being, changing the users' hotspot setting within the application.
To get and set this configuration I am using the following functions from the WifiManager hidden api: getWifiApConfiguration and setWifiApConfiguration.
Method getWifiApConfiguration = wifiManager.getClass().getMethod("getWifiApConfiguration");
getWifiApConfiguration.invoke(wifiManager);
This is working with devices prior to Android O, but in this version I get the following error:
App not allowed to read or update stored WiFi Ap config (uid = 10168)
The permissions I have declared in the manifest are:
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.NETWORK_STACK"/>
<uses-permission android:name="android.permission.TETHER_PRIVILEGED" />
How can I do this with the latest APIs?
As of Android Oreo (26), a new permission check was added to the service implementation of the getWifiApConfiguration() method:
Snippet from WifiServiceImpl.java
/**
* see {#link WifiManager#getWifiApConfiguration()}
* #return soft access point configuration
* #throws SecurityException if the caller does not have permission to retrieve the softap
* config
*/
#Override
public WifiConfiguration getWifiApConfiguration() {
enforceAccessPermission();
int uid = Binder.getCallingUid();
// only allow Settings UI to get the saved SoftApConfig
if (!mWifiPermissionsUtil.checkConfigOverridePermission(uid)) {
// random apps should not be allowed to read the user specified config
throw new SecurityException("App not allowed to read or update stored WiFi Ap config "
+ "(uid = " + uid + ")");
}
mLog.trace("getWifiApConfiguration uid=%").c(uid).flush();
return mWifiStateMachine.syncGetWifiApConfiguration();
}
Digging into the code you will quickly find out that to successfully invoke this method your application must hold the android.permission.OVERRIDE_WIFI_CONFIG permission that is a system level protected permission:
Snippet from framework AndroidManifest.xml
<!-- #SystemApi #hide Allows an application to modify any wifi configuration, even if created
by another application. Once reconfigured the original creator cannot make any further
modifications.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.OVERRIDE_WIFI_CONFIG"
android:protectionLevel="signature|privileged" />
This means that your application needs to be signed by the platform key or be privileged to use this API.
Related
Good afternoon. For a very long time I have been trying to get a list of wi-fi networks using WifiManager. When I try to get through a virtual device, I get only one fictional network with an SSID: Android Wifi. However, I do not receive networks from my real environment. When using a real device, it is not possible to get any network.
What is the mistake?
Rights in AndroidManifest:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<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_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
The code I use to work with Wifi:
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiManager.startScan();
List<ScanResult> availNetworks = wifiManager.getScanResults();
Log.d("STRING",Integer.toString(availNetworks.size()));
if (availNetworks.size() > 0) {
for (int i=0; i< availNetworks.size();i++) {
String buf = availNetworks.get(i).toString();
String[] buflist = buf.split(",");
Log.d("STRING","In");
String elementWssid = buflist[0];
String elementWsec = buflist[2];
String elementWlevel = buflist[3];
String SSID = elementWssid.split(": ")[1];
String Sec = elementWsec.split(": ")[1];
String level = elementWlevel.split(": ")[1];
Log.d("STRING",SSID);
Log.d("STRING",Sec);
Log.d("STRING",level);
}
}
Permits have already been issued.
Solved a problem. In the application settings there is such a section as "other permissions". It contains permissions to work with wi-fi, which by default are in the "ask" status, after changing the status to "allow" the problem was solved. For some reason, android doesn't feel the need to ask for permissions like location.
P.s.
Xiaomi has a separate slider to access the location of ALL apps, it needs to be turned on to give permissions.
AndroidWifi on a virtual device is a test network for checking the performance of applications, since it does not know how to work with real networks.
I have been trying various ways to call on my location data ranging from IP location API's to Flutter plugin's but have not been able to get accurate location data for any of them. Through all I have settled onto Geolocator. But I kept getting
I/flutter ( 5206): null
I/flutter ( 5206): GeolocationStatus.unknown
When calling it in my Init state as follows:
void initState() {
super.initState();
fetchData();
}
fetchData() async {
setState(() {
isLoading = true; //Data is loading
});
GeolocationStatus geolocationStatus =
await Geolocator().checkGeolocationPermissionStatus();
position = await Geolocator()
.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
if (position != null) {
lastPosition = await Geolocator()
.getLastKnownPosition(desiredAccuracy: LocationAccuracy.high);
}
...
if (position != null)
print(position);
else
print(lastPosition);
print(geolocationStatus);
setState(() {
isLoading = false; //Data has loaded
});
}
After some research I decided to settle on permission_handler to try to check permissions. I declared PermissionStatus _status added the following lines to my fetchData() function:
PermissionHandler()
.checkPermissionStatus(PermissionGroup.location);
To which I get No permissions found in manifest for: 3
My manifest has the permissions to the best of my understanding. Manifest file: https://gist.github.com/Purukitto/640d1637c05bdb1b69cc4309947c45d5
From what I understand adding the permissions to the Manifest should add the permission option at least to the app, but after building and installing the app there are "No permissions" for my app(Screenshot attached).
What could be the problem. I have tried to mention all relevant things. Any insight will be really helpful.
This question is linked in the Flutter package permission_handler's ReadMe as an example of setting up the AndroidManifest.xml for asking permissions.
If you're having issues with the device asking the user for permissions, this may be your culprit.
To elaborate on rollcake's answer:
1. If you don't know what permissions you need yet, go to the Android Developer page to see the list and the syntax(es).
2. In your project, open: android/app/src/main/AndroidManifest.xml
3. Insert your permissions as shown in this example here:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.your.package">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:name="io.flutter.app.FlutterApplication"
...<and so on>...
Just a side note: There are different AndroidManifest.xml files in your project (...src/debug, ...src/profile, and ...src/main). Adding the permissions to the main version described above should work but if you're noticing inconsistent behavior make sure you're putting all of your permissions in the same AndroidManifest file.
Check for targetSdkVersion is 23 if so then check for runtime permission you can use checkSelfPermission() and requestPermissions() for android 6 and above
open android project in flutterProject
click manifests file
insert permission
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
1. Add them in AndroidMenifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="30"></uses-permission>
<uses-permission android:name="com.google.android.gms.permission.AD_ID"></uses-permission>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"></uses-permission>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"></uses-permission>
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"></uses-permission>
2. Update permissions handler package :
Package link : https://pub.dev/packages/permission_handler
I'm developing a little sdk that has to be included in projects via .aar file. In this sdk I have a method defined like below:
/**
* Sends an "open lock" request for the bike, with the ble name provided as param. Requires ACCESS_FINE_LOCATION and
* BLUETOOTH permission
*
* #param bikeBleName The BLE name of the searched bike, normally starts with 'BS' prefix
* #param listener Listener for the operation state, returns success or an error string with the detailed error
*/
#RequiresPermission(allOf = [Manifest.permission.BLUETOOTH, Manifest.permission.ACCESS_FINE_LOCATION])
override fun startRent(bikeBleName: String, bikeMode: BikeMode, listener: StartRentListener) {
GlobalScope.launch {
startRentManager.startRent(bikeBleName, bikeMode, listener)
}
}
As you can see, the method is annotated with #RequiresPermission(allOf = [Manifest.permission.BLUETOOTH, Manifest.permission.ACCESS_FINE_LOCATION]), however, if I call the method from my project MainActivity, Android Studio tells me that the method requires a permission check, but it doesn't tell me which permissions are required.
What I would like to obtain is Android Studio telling me "this method requires ACCESS_FINE_LOCATION and BLUETOOTH permissions", something similar to the screenshot below. How can I achieve that? Thanks
The manifest file of the library module is:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="it.zehus.bikeaccesssdk">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
</manifest>
Problem was that I placed
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="it.zehus.bikeaccesssdk">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
</manifest>
in the library module. I removed the permissions from the library manifest and now Android Studio is providing the correct hint.
I am using this code to get MAC ADDRESS and display it in my app. The code works fine for all devices except most latest devices and ANDROID BOX.
it shows null for ANDROID BOX and other latest device.
Here is code:
public static String getWifiMacAddress() {
try {
String interfaceName = "wlan0";
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface intf : interfaces) {
if (!intf.getName().equalsIgnoreCase(interfaceName)){
continue;
}
byte[] mac = intf.getHardwareAddress();
if (mac==null){
return "";
}
StringBuilder buf = new StringBuilder();
for (byte aMac : mac) {
buf.append(String.format("%02X:", aMac));
}
if (buf.length()>0) {
buf.deleteCharAt(buf.length() - 1);
}
return buf.toString();
}
} catch (Exception ex) { } // for now eat exceptions
return "";
}
I have written these permissions in manifest file
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Firstly u will check the permission is granted or not?
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo wInfo = wifiManager.getConnectionInfo();
String macAddress = wInfo.getMacAddress();
Also, add below permission in your manifest file
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
Please refer this link for 6.0 marshmalow
First you will need to add Internet user permission in AndroidManifest.xml.
<uses-permission android:name="android.permission.INTERNET" />
and then Refer this to get mac address: http://robinhenniges.com/en/android6-get-mac-address-programmatically
And if it doesn't works then refer this Android 6.0 changes
from this i have concluded that,
To provide users with greater data protection, starting in this
release, Android removes programmatic access to the device’s local
hardware identifier for apps using the Wi-Fi and Bluetooth APIs. The
WifiInfo.getMacAddress() and the BluetoothAdapter.getAddress() methods
now return a constant value of 02:00:00:00:00:00.
To access the hardware identifiers of nearby external devices via
Bluetooth and Wi-Fi scans, your app must now have the
ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permissions.
Note That : you can't get your own MACs even having those permissions. Read carefully, It is said that you can get other devices MACs having those permissions, but not your own.
As in 6.0 and above adding permission in Manifest alone wont work. You should have runtime permission and grant it if not granted.
Check this link:
https://stackoverflow.com/a/30549756/3910281
I'm using this library and trying to retrieve current location coordinates like this:
settings =
new TrackerSettings()
.setUseGPS(false)
.setUseNetwork(true)
.setUsePassive(true)
.setTimeBetweenUpdates(30 * 60 * 1000);
tracker = new LocationTracker(getBaseContext(), settings) {
#Override
public void onLocationFound(Location location) {
// Do some stuff
currentLatDouble = location.getLatitude();
currentLngDouble = location.getLongitude();
}
#Override
public void onTimeout() {
}
};
tracker.startListening();
but, I'm getting this error:
W/LocationTracker: Provider (network)
fr.quentinklein.slt.ProviderError: Provider is not enabled | ProviderError{provider='network'}
Isn't WiFi a network provider or do I need to write some code related to LocationManager too?
Please let me know what is wrong here.
Added the following permission in manifest file
<uses-permission android:name="android.permission.INTERNET" />
Allows applications to open network sockets.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
Allows an app to access approximate location.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Allows an app to access precise location.
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Allows applications to access information about networks.
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
Allows applications to access information about Wi-Fi networks.
Additionally
<uses-feature
android:name="android.hardware.location.network"
android:required="false" />
<uses-feature
android:name="android.hardware.location.gps"
android:required="false" />