My question is similar to Android 10 request permission for ACTIVITY_RECOGNITION in a way that I also do not have a permission dialog showing on a device, but conditions are different.
My app is targeting API 29.
In manifest I have
<uses-permission android:name="android.permission.BODY_SENSORS"/> <- for test purposes
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
Requesting permission Manifest.permission.ACTIVITY_RECOGNITION as usual:
fragment.requestPermissions(permissions, GOOGLE_FIT_ANDROID_PERMISSIONS_REQUEST_CODE)
On a device with Android 9 (API28) I do not receive a permission dialog for ACTIVITY_RECOGNITION and when I check a permission status, it is always denied.
I know that permission logic is working, as when I've added BODY_SENSORS permission, I do get a permission dialog for BODY_SENSORS, but not for ACTIVITY_RECOGNITION. As a result, a permission for BODY_SENSORS is granted, but for ACTIVITY_RECOGNITION - not:
permissions array:
android.permission.BODY_SENSORS;android.permission.ACTIVITY_RECOGNITION
grantResults array:
0;-1
Answering my own question. Please don't treat it as a source of truth, it is based on my own tests. Maybe someone from GoogleFit team can comment on this.
Preconditions: your app is targeting API29 or above.
Regardless of Android version, installed on a device, you should add permissions to Manifest file according to documentation. Side note: I was able to query GoogleFit HistoryApi even without those permissions on device with Android 9, but Android 10 will not work.
<uses-permission android:name="android.permission.BODY_SENSORS"/>
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
For devices with Android 10 or above: all is simple, you should request runtime permissions, same which you've added to Manifest.
For devices with Android version 9 or below: you don't have to request runtime permissions. This is the part which was not clear from the documentation.
You may, of course, request those permissions, but for android.permission. ACTIVITY_RECOGNITION you will not receive a permission dialog and as a result permission will not be granted.
Related
I am developing a COSU/KIOSK application and I need to manually update the time on the device.
I am using AlertManager.setTime(Calendar) to do so, but I can't grant my application the SET_TIME permission that it is required.
The application is the device owner, and this allowed me to use many other system permissions, for example
android:name="android.permission.REBOOT"
android:name="android.permission.SHUTDOWN"
android:name="android.permission.WRITE_SETTINGS"
android:name="android.permission.INSTALL_PACKAGES"
android:name="android.permission.DELETE_PACKAGES"
All of these permissions were granted to my application, just by listing them in the manifest.xml
But SET_TIME does not work.
I also tried using the device policy manager
mDevicePolicyManager.setPermissionGrantState(mAdminComponentName, getPreferredPackageName(),
Manifest.permission.SET_TIME, DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
This function returned false meaning it couldn't grant permission.
How can I solve this problem without prompting the user to grant this permission to my application.
If you are targeting devices api 28+ (android 9 and higher) you can set it with setTime(ComponentName admin, long millis) function.
For lower android versions I had to rely on a device manufacturer api to set device time.
Manifest.permission.SET_TIME is proteced/system permission, sadly deviceOwner cannot grant any protected permissions with setPermissionGrantState() function.
There is very important word in its documentation:
Sets the grant state of a !runtime! permission for a specific application.
The application I am developing uses Bluetooth and Storage permissions, therefore my AndroidManifest.xml contains the following.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission>
<uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE"></uses-permission>
However, when the app is installed, upon scanning for Bluetooth devices nothing is found until I manually switch on permission for Location in my device settings (Settings -> Apps -> [My App] -> Permissions). I have read somewhere that this permission is required for Android 6.0 (maybe 7.0) and above if you want to use the Bluetooth, but why is it not enabled upon installation with these permissions in the manifest file? Have I missed one out?
Location and Bluetooth are two different things.
You don't need to request permission to access Bluetooth as it is a normal permission, but you do need to request permission for Location as it is a dangerous permission.
You can find a list of all permissions that must be requested on runtime here.
From the official documentation.
System permissions are divided into two categories, normal and dangerous:
Normal permissions do not directly risk the user's privacy. If your app lists a normal permission in its manifest, the system grants the
permission automatically.
Dangerous permissions can give the app access to the user's confidential data. If your app lists a normal permission in its
manifest, the system grants the permission automatically. If you
list a dangerous permission, the user has to explicitly give
approval to your app.
And
If the device is running Android 5.1 or lower, or your app's target SDK is 22 or lower: If you list a dangerous permission in your
manifest, the user has to grant the permission when they install the
app; if they do not grant the permission, the system does not install
the app at all.
If the device is running Android 6.0 or higher, and your app's target SDK is 23 or higher: The app has to list the permissions in
the manifest, and it must request each dangerous permission it
needs while the app is running. The user can grant or deny each
permission, and the app can continue to run with limited
capabilities even if the user denies a permission request.
So, most likely you are testiong your app on device or emulator running API 23+ and have a request to location of the device.
Location permission is a dangerous one, so in Android 6.0 or higher user is forsed to allow location access manually. For this you have to add dangerous permissions programmatically. Take a look here for the good instruction for this.
P.S. To find out, which permissions are dangerous, and wich are normal, look here.
Certain permissions are classified as dangerous and they need to be asked for in runtime.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
Replace the READ_CONTACTS permission with location permission
I have an application that requires the internet permission but it doesn't seem to be working for me.
I added:
<uses-permission android:name="android.permission.INTERNET"/>
To the manifest (above the application tag) and when I install the app my phone says: "No permissions requested" and the permission dialog doesn't show up.
However when I replace INTERNET with CAMERA like so:
<uses-permission android:name="android.permission.CAMERA"/>
It works fine and shows up under the permissions tab in settings.
Any ideas?
Thanks
If the device is running Android 6.0 (API level 23) and the app's targetSdkVersion is 23 or higher if an app declares in its manifest that it needs a normal permission, the system automatically grants the app that permission at install time.
The system does not prompt the user to grant normal permissions, and users cannot revoke these permissions.
As you can check in the official doc the INTERNET permission is normal.
Instead the CAMERA permission is dangerous.
You're running your app in Android SDK>=23.
Internet permission is under Normal permission so it not show any permission prompt but Camera permission is under Dangerous Permission so it show permission prompt.
If an app declares that it needs a normal permission, the system automatically grants the permission to the app.
https://developer.android.com/guide/topics/permissions/requesting.html
Android only puts the dangerous permissions there. And since Camera is a dangerous permissions you see it in the list, and since Internet is not, you don't see it in the list.
Android differentiates between normal permissions (e.g. INTERNET) and dangerous permissions (e.g. CAMERA). The User is only asked in case of dangerous permissions. So the behavior you see is perfectly normal.
https://developer.android.com/guide/topics/permissions/normal-permissions.html
Only Selected permissions can be asked for user
check here which permissions can be asked by Permission manager
This usually does the trick for me:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
This code worked my phone.But it didnt worked from my friend phone. I have permission too . I get This error ;
Neither user 10109 nor current process has android.permission.READ_PHONE_STATE.
Permission ;
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
This is my Code ;
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
IMEI= telephonyManager.getDeviceId();
This is probably due to your friend running on Android 6.0 (API level 23). You need to add permissions at Runtime as well as the ones in the Manifest.
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. This approach streamlines the app install process, since the user does not need to grant permissions when they install or update the app. It also gives the user more control over the app's functionality; for example, a user could choose to give a camera app access to the camera but not to the device location. The user can revoke the permissions at any time, by going to the app's Settings screen.
Refer here for more information. Maybe take a look at this question to see how to implement runtime permissions, although it's explained in the first link as well.
As per new marshmallow os you need to configure runtime permission for "READ_SMS"
like this :
String permission = Manifest.permission.READ_SMS;
if (ContextCompat.checkSelfPermission(getContext(), permission) != PackageManager.PERMISSION_GRANTED){
permissionList.add(permission);
if (!ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), permission)){
requestPermissions(new String[]{permission}), SMS_PERMISSION);
}
}
I have an Android application which need the permissions: READ_PHONE_STATE & CALL_PHONE. I've declared these permissions in the Manifest and it works fine for SDK < 23.
Now in Android 6 (SDK 23) I'm asking the user to grant this permission in runtime.
In the documentation, they say the if the user has granted one of the above permission, he actually granted all the permissions that are found in the same group permissions, in this case all the permission that are related to the phone group permissions.
But I'm facing with a problem, when I'm using telephony manager to get the deviceid, I'm getting a security exceptions that says that I don't have any access, even though the user has granted the "call phone" permission, why is that?
Update:
I'm requesting multiple permissions
In Manifest.xml
<uses-permission android:name="android.permission.CALL_PHONE">
<uses-permission android:name="android.permission.READ_PHONE_STATE">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE">
In Activity:
ActivityCompat.requestPermissions(this,new String[]
{
Manifest.permission.CALL_PHONE,
Manifest.permission.READ_EXTERNAL_STORAGE
},
permissionRequestcode);