I'm testing Bluetooth with a Huawei Honor 8 device (Android 9).
The permissions in manifest.xml are registered:
<uses-permission android: name = "android.permission.BLUETOOTH" />
<uses-permission android: name = "android.permission.BLUETOOTH_ADMIN" />
1) Why, in Android 9, when bluetoothAdapter.enable() is called, a request pops up for permission to turn on Bluetooth (and also to turn off)? Although this permission has already been given to the application. In the list of permissions (Settings-Applications-My application-Rights) there are:
Permission to "request a connection, accept a connection, transfer
data" (I assume this is BLUETOOTH)
Permission to "start scanning devices and changing Bluetooth settings"
(I assume this is BLUETOOTH_ADMIN)
On a device with Android 4.4, no additional requests arise.
In order for the system to remember the issued permission, do I need to display its request using ActivityCompat.requestPermissions() ?
2) Why are these 2 permissions not in the main list of permissions, but as additional permissions (you must specifically click on the Advanced button to see them)?
UPDATE:
If I understand correctly, all the normal permissions (which are BLUETOOTH and BLUETOOTH_ADMIN) are often found as Additional.
Related
## How I solved it:
### For Permissions: Make sure to request Background location too:
```Java
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
For Verifying Permissions:
Copy the whole snippet from:
https://altbeacon.github.io/android-beacon-library/requesting_permission.html
to your on create method
BE PATIENT!!!!
Apparently, it takes about 1 minute for the first detection (both monitoring and ranging) to occur despite me setting the ranging time to 5 seconds (5000 ms). After that, the response time for out of range beacon should be less than half a second.
Please Advice if you can help with the long waiting time between starting the monitoring to receiving a list of beacons detected despite a change in beacon detection state already within 1 second of starting monitoring.
Original Question
Extra Detail:
The detection goes smoothly even if the 'Change Bluetooth Permission' mentioned above is set to 'notify' whenever I switch to another app despite the app not being a service. Why is that?
Original Question:
I am trying to scan for beacons around me using the android beacons library and it never works unless I manually go into settings -> manage apps and change the 'Change Bluetooth Connectivity (turn Bluetooth on or off)' permission from 'notify' -> to 'Accept'
However, I already requested bluetooth and bluetooth admin permissions
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
as well as other permissions like fine location/coarse location
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
The previous app that I created worked fine on my device but in that app, the beacon functions are built as a 'service' and I have heard that requesting Location permission when running beacon functions not as a service can spell disaster. However, removing the location permissions did not make a difference upon my experimentation. It is only manually changing the bluetooth permission in settings that made it work.
So the question is, how to I force the general bluetooth permission on a Xiaomi phone to ACCEPT through a prompt like requesting dangerous permissions for coarse location requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1234);
and is this the right way to solve the issue? Many thanks
Device:
Xiaomi Mi8 (MIUI11 Android 10 API29)```
I use the Code A to set the enabled status of WiFi, it works well when I use Android Emulator with both API 26 and API 23 in Android Studio 3.1.3 , and none of prompt window display!
But I get a prompt window "An App is requesting permission to use WLAN. Allow?" in real mobile phone with Android 5.1 when I run the code A.
How can I make the prompt window not to display in real mobile phone? Thanks!
BTW,the real mobile phone is Samsung SM-J5008 with Android 5.1
Prompt Window
I have set the permissions
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
Code A
fun setWiFi(aWiFiDef: WiFiDef): Unit{
val wifiManager =mContext.applicationContext.getSystemService(WIFI_SERVICE) as WifiManager
wifiManager.isWifiEnabled=aWiFiDef.status
}
Android 5.1 does not have such runtime permission, so I assume, that this is a wrongly implemented permission request rational, which is shown even though the app does not need to. You wrote, that you tested with API level 26 and 23, which is Android 6.0 and higher, so these versions already have runtime permissions. Maybe you haven't seen this issue, because you haven't tested on devices below Android 6.0...
Please check if you somewhere call AppCompat.shouldShowRequestPermissionRationale() and if it is surrounded by SDK level checks or at least with a checkSelfPermission as described here: https://developer.android.com/training/permissions/requesting. Test your code in an emulator with Android 5.1 and Android 6.0. Then you should be able to reproduce that issue also on real phones.
You also need to add this to your manifest:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
According to the website below: *App on Marshmallow needs ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission and Location services should be enabled to get wifi scan results. Google probably sees scanning for wifi as a security concern, and wanted to add the location permissions as well.
I would recommend following the blog post below if you are having trouble after adding the ACCESS_COARSE_LOCATION permission to your manifest.
https://www.intentfilter.com/2016/08/programatically-connecting-to-wifi.html
EDIT
For the people down voting, please include a comment explaining why. Was my answer flat out wrong? Did I overlook somthing?
Some more information on google's geolocation service:
Google maintains a huge database for its geolocation service ("Access coarse location" permission). It consists of:
Wifi access point mappings: Wifi MAC address resolve to a geolocation
Cell tower mapping: Cell tower ID's resolve to a geolocation
So it is very possible that this user didn't include this permission and is getting this dialog box.
Code:
I use the following code taken from here with a target API level 23 (and minimum API level 18).
private final BroadcastReceiver mReceiver = new BroadcastReceiver()
{
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action))
{
bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
deviceNameTextView.setText(bluetoothDevice.getName());
}
}
};
On a button pressed event I call:
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
mBluetoothAdapter.startDiscovery(); // was initialized successsfully
My AndroidManifest.xml contains:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
Devices:
Samsung Galaxy S III (API level 18)
Sony Xperia Z3 (API level 23)
Facts:
both devices are running the exact same code
device 1 can discover device 2 (and any other Bluetooth device)
device 2 cannot discover device 1 (or any other Bluetooth device)
both devices are discoverable
tested discoverability with the standard system dialog for pairing for both devices successfully
both devices were unpaired at all times (I don't want to pair)
No exceptions are thrown.
What is wrong?
Update 1:
Since API level 23 permissions may have to be requested at run time. Yvette pointed me to that, thank you! Unfortunately it didn't solve my problem.
What speaks against her theory is the following:
mBluetoothAdapter.startDiscovery() returns true, which means success (see here).
// Assume thisActivity is the current activity
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity , Manifest.permission.BLUETOOTH_ADMIN);
if(permissionCheck == PackageManager.PERMISSION_GRANTED)
Log.i("info", "Permission granted!");
else
Log.i("info", "Permission not granted!");
Running this code with BLUETOOTH_ADMIN and BLUETOOTH returns both times:
Permission granted!
When doing some research, I found the following article from the official documentation regarding changes in Android 6.0 (API level 23).
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:
- WifiManager.getScanResults()
- BluetoothDevice.ACTION_FOUND
- BluetoothLeScanner.startScan()
So, I was missing the permissions ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION all along. But just adding them in the AndroidManifest.xml file is not enough. You have to request those privileges at run time like Yvette suggested.
You can find here how you can do that or just use this piece of code I wrote to get the permissions needed for Bluetooth discovery.
final int CODE = 5; // app defined constant used for onRequestPermissionsResult
String[] permissionsToRequest =
{
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.BLUETOOTH,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
};
boolean allPermissionsGranted = true;
for(String permission : permissionsToRequest)
{
allPermissionsGranted = allPermissionsGranted && (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED);
}
if(!allPermissionsGranted)
{
ActivityCompat.requestPermissions(this, permissionsToRequest, CODE);
}
mBluetoothAdapter.startDiscovery();
This code is assuming that the user grants the permissions (for simplicity). If you want your app to behave differently when the permissions are not granted see "Handle the permissions request response" in this article.
Sounds like you're not managing runtime permissions for sdk 23 and higher. The phone with the sdk of 23 will either silently ignore any requests that require runtime permissions or crash.
Also see in the docs System Permissions.
If your app lists normal permissions in its manifest (that is, permissions that don't pose much risk to the user's privacy or the device's operation), the system automatically grants those permissions. If your app lists dangerous permissions in its manifest (that is, permissions that could potentially affect the user's privacy or the device's normal operation), the system asks the user to explicitly grant those permissions. The way Android makes the requests depends on the system version, and the system version targeted by your app:
If the device is running Android 6.0 (API level 23) or higher, and the app's targetSdkVersion is 23 or higher, the app requests permissions from the user at run-time. The user can revoke the permissions at any time, so the app needs to check whether it has the permissions every time it runs. For more information about requesting permissions in your app, see the Working with System Permissions training guide.
If the device is running Android 5.1 (API level 22) or lower, or the app's targetSdkVersion is 22 or lower, the system asks the user to grant the permissions when the user installs the app. If you add a new permission to an updated version of the app, the system asks the user to grant that permission when the user updates the app. Once the user installs the app, the only way they can revoke the permission is by uninstalling the app.
Often times a permission failure will result in a SecurityException being thrown back to the application. However, this is not guaranteed to occur everywhere. For example, the sendBroadcast(Intent) method checks permissions as data is being delivered to each receiver, after the method call has returned, so you will not receive an exception if there are permission failures. In almost all cases, however, a permission failure will be printed to the system log.
The permissions provided by the Android system can be found at Manifest.permission. Any application may also define and enforce its own permissions, so this is not a comprehensive list of all possible permissions.
A particular permission may be enforced at a number of places during
your program's operation:
At the time of a call into the system, to prevent an application from
executing certain functions.
When starting an activity, to prevent
applications from launching activities of other applications.
Both
sending and receiving broadcasts, to control who can receive your
broadcast or who can send a broadcast to you.
When accessing and
operating on a content provider.
Binding to or starting a service.
As for the app crashing:
Everything every Android Developer must know about new Android's Runtime Permission
Next question in your head right now. So will my application crash?
Such a kindness sent from god delivered through the Android team. When we call a function that requires a permission user revoked on application with targetSdkVersion less than 23, no any Exception will be thrown. Instead it will just simply do nothing. For the function that return value, it will return either null or 0 depends on the case.
But don't be too happy. Although application would not be crashed from calling a function. It may still can crash from what that application does next with those returned value.
Some more details in these answers Require dangerous permissions during installation When asking for runtime permission for location
I have a (FOSS) app out there which can, among other features, enable and disable Wifi.
AndroidManifest.xml contains android.permission.CHANGE_WIFI_STATE, unit tests on the emulator pass and the feature works on a real device, a HTC Desire running 2.2.2.
The SDK versions are android:minSdkVersion="7" and android:targetSdkVersion="10", so I can't say about newer releases of Android.
I have received one single crash report:
java.lang.SecurityException: Permission Denial: writing com.android.providers.settings.SettingsProvider
uri content://settings/secure from pid=6191,
uid=10114 requires android.permission.WRITE_SETTINGS
Is android.permission.WRITE_SETTINGS possibly required on recent versions of Android? The reference says the permission exists since API 1, so I'd be surprised why it wasn't on older releases.
The user message is weird, it just says "lies", so I am unsure if I should just follow this report and add android.permission.WRITE_SETTINGS.
Any thoughts?
Cheers,
Torsten
That's weird, cause I needed to check exactly the same issue, so i just wrote a few lines of code doing exactly just that : enable/disable wifi and bluetooth.
My conclusion: you dont need the WRITE_SETTINGS permission to toggle the wifi, nor the bluetooth for that matter.
wifi = access_wifi_state + change_wifi_state
BT = bluetooth + bluetooth_admin
(with 4.2.2)
Check whether you were trying something else too, which may trigger the exception ?
For allowing or preventing manually installation of apk file from sdcard we ticks/unticks the checkbox which says "Allow installation of app from unknown source".
Can we do this Programmatically by avoiding any User Interface?
Thanks,
Nirav
No, not unless you're a carrier, or not unless you're on an enterprise phone that your company has admin access over.
This is part of the security model of Android, so that a user can not lose the control of his phone to a malicious application.
Here are the actual permissions you would need to do something like that:
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
You can try using those permissions, but by design they won't work unless you have root access to the device.
Within the device settings, users are able to view permissions for
applications they have previously installed. Users can also turn off
some functionality globally when they choose, such as disabling GPS,
radio, or wi-fi.
In the event that an application attempts to use a protected feature
which has not been declared in the application's manifest, the
permission failure will typically result in a security exception being
thrown back to the application. Protected API permission checks are
enforced at the lowest possible level to prevent circumvention.