I am developing a simple app that show your current position ( latitude and longitude). I am using the functions:
- navigator.geolocation.getCurrentPosition
- navigator.geolocation.watchPosition
But I have noticed that the permission is granted without asking for permission at the user.
Is this agaist the google's rules?
If yes, how can I show a dialog that ask for the permission?
For android, You can use PermissionAndroid by importing from 'react-native'.
import { PermissionsAndroid } from 'react-native'; //
Checkout this link for more info.
For iOS, You have to fill the .plist file and it pops for permission. No need to handle it explicitly.
As per the android docs
Android apps must request permission to access sensitive user data (such as contacts and SMS), as well as certain system features (such as camera and internet)
If the device is running Android 6.0 (API level 23) or higher, and the app's targetSdkVersion is 23 or higher, the user isn't notified of any app permissions at install time. Your app must ask the user to grant the dangerous permissions at runtime.
If the device is running Android 5.1.1 (API level 22) or lower, or the app's targetSdkVersion is 22 or lower while running on any version of Android, the system automatically asks the user to grant all dangerous permissions for your app at install-time.
To grant the Permissions manually you must use PermissionsAndroid before each request which is well mentioned in this link
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.CAMERA,
{
'title': 'Cool Photo App Camera Permission',
'message': 'Cool Photo App needs access to your camera ' +
'so you can take awesome pictures.'
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log("You can use the camera")
} else {
console.log("Camera permission denied")
}
} catch (err) {
console.warn(err)
}
The list of dangerous permissions are mentioned here
I think you should be looking at doing this with the react-native-permissions
Permissions.request('location', { type: 'always' }).then(response => {
this.setState({ locationPermission: response })
})
Related
According to the React Native docs PermissionsAndroid.check is supposed to return a boolean that shows if the corresponding permission has been granted, but for me this is always true independently of me enabling/disabling any permission for the app I'm building.
I didn't find any issue on the React Native Github about this, so I assume that this is a more of my issue than React Native's. What am I doing wrong/missunderstanding here?
System:
React Native: 0.63
Android Emulator: Pixel 4 API 29
Example:
async function checkPermissions(): void {
const hasCameraPermission = await PermissionsAndroid.check(
PermissionsAndroid.PERMISSIONS.CAMERA
);
const hasStoragePermission = await PermissionsAndroid.check(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE
);
console.log(`checkPermissions camera=${JSON.stringify(hasCameraPermission, null, 2)}, storage=${JSON.stringify(hasStoragePermission, null, 2)}`);
}
The result is always checkPermissions camera=true, storage=true independently of the app having permissions enabled or disabled.
I think you are doing a wrong comparison , you should compare this
PermissionsAndroid.RESULTS.GRANTED === hasStoragePermission
PermissionsAndroid.RESULTS.GRANTED === hasStoragePermission
this will give you result that you have the permission or not
Cheers !!
I think these permissions has been filtered by google play
Note: In some cases, the permissions that you request through can affect how your application is filtered by Google Play.
If you request a hardware-related permission — CAMERA, for example — Google Play assumes that your application requires the underlying hardware feature and filters the application from devices that do not offer it.
To control filtering, always explicitly declare hardware features in elements, rather than relying on Google Play to "discover" the requirements in elements. Then, if you want to disable filtering for a particular feature, you can add a android:required="false" attribute to the declaration.
Or the permission is no longer needed
beginning with Android 4.4 (API level 19), it's no longer necessary for your app to request the WRITE_EXTERNAL_STORAGE permission
You can read the doc here
Facebook, Evernote, Pocket - all apps get this permission on Android 6.0 automatically, even though they are targeting 23 (targetSdkVersion=23).
There has been a lot of documentation regarding the new Marshmallow permission model. One of them is SYSTEM_ALERT_WINDOW been 'promoted' to 'above dangerous' permission class thus requiring a special user intervention in order for apps to be granted with those. If the app has targetSdkVersion 22 or lower, app gets this permission automatically (if requested in the manifest).
However, I've noticed some apps that get this permission, without needing to send the user to the setting special page of Draw over other apps permission. I saw Facebook, Evernote, Pocket - and perhaps there are more.
Anyone knows how an app can be granted this permission without the user go through Settings -> Apps -> Draw over other apps?
Thanks
It is a new behaviour introduced in Marshmallow 6.0.1.
Every app that requests the SYSTEM_ALERT_WINDOW permission and that is installed through the Play Store (version 6.0.5 or higher is required), will have granted the permission automatically.
If instead the app is sideloaded, the permission is not automatically granted. You can try to download and install the Evernote APK from apkmirror.com. As you can see you need to manually grant the permission in Settings -> Apps -> Draw over other apps.
These are the commits [1] [2] that allow the Play Store to give the automatic grant of the SYSTEM_ALERT_WINDOW permission.
Yeh After Marshmallow come Android make security level more stick, But For SYSTEM_ALERT_WINDOW you can show floating action and anything You can Force user to give permission for it By Following Codes in your onCreate() method.
Put this code after setContentView:
// Check if Android M or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Show alert dialog to the user saying a separate permission is needed
// Launch the settings activity if the user prefers
Intent myIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
startActivity(myIntent);
}
The action ACTION_MANAGE_OVERLAY_PERMISSION directly launches the 'Draw over other apps' permission screen.
Edit:
My Above Code works 100% Correct
But I just found that many guys are still searching that how can allow ACTION_MANAGE_OVERLAY_PERMISSION permanently like If user has allow Permission Once then don't ask it every time he open application so here is a solution for you:
Check if device has API 23+
if 23+ API then check if user has permit or not
if had permit once don't drive him to Settings.ACTION_MANAGE_OVERLAY_PERMISSION and if has not permit yet then ask for runtime permission check
Put below line in your onCreate() method. Put this after setContentView:
checkPermission();
Now put below code in onActivityResult:
#TargetApi(Build.VERSION_CODES.M)
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {
if (!Settings.canDrawOverlays(this)) {
// You don't have permission
checkPermission();
} else {
// Do as per your logic
}
}
}
Now finally the checkPermission method code:
public void checkPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
}
}
}
And don't forget to declare this public variable in your class:
public static int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE = 5469;
Now(2019) that Google offers an alternative API to SYSTEM_ALERT_WINDOW in the form of Bubbles in Android Q, Google has decided to eventually deprecate SYSTEM_ALERT_WINDOW in a future Android release.
And Android Go devices will no longer grant this permission
i.e Settings.canDrawOverlays() == false
For those who want to get this permission automatically when the app is downloaded from the Play Store, besides the SYSTEM_ALERT_WINDOW in the Manifest, you should go to this link and request this from Google.
You have to provide some additional information why you need this permission and Google will review and give you the automatically permission.
Bear in mind that before you ask for this, you have to:
Have the SYSTEM_ALERT_WINDOW permission in the Manifest
Prompt the user to grant the SYSTEM_ALERT_WINDOW permission within your app, when not already granted
If I miss something feel free to update the answer
If the app targets API 22 or lower, then Play Store will give the SYSTEM_ALERT_WINDOW permission and others when the user clicks to install (showing an alert) even if its device is Android 6.0
Otherwise, if the app targets API 23 or above, so that permission will be request to grant in run time.
Right now I am building an applications which uses multiple device features like location, camera, storage and contacts.
I want to know if there is any way that allows users to enter into my application if and only if all the permissions are granted.
I've tried using react-native-permissions and the code snippet is as follows
Permissions.request('photo').then(() => {
Permissions.request('location').then(() => {
Permissions.request('camera').then(() => {
Permissions.request('contacts').then(() => {
Permissions.request('notification').then(() => {
console.log('PERMISSIONS ASKED');
});
});
});
});
});
The above code works only at the first time and if the user clicks deny then it is not asking again. Can any one help me with this.
Thanks in advance
Yes, once a user denies a permission he won't be asked for the permission again(iOS). He have to go back to settings and manually update the permissions.
It is not a good practice to ask all the permissions at once, the right way to ask is to alert for the permission when user initiate the usage of services like (location, camera).
Any way if you would like to ask all the permissions at once then you can check if the permission is in denied state, if so you can show an alert to open settings and change the permission.
Permissions.check('location', { type: 'always' }).then(response => {
this.setState({ locationPermission: response })
})
Facebook, Evernote, Pocket - all apps get this permission on Android 6.0 automatically, even though they are targeting 23 (targetSdkVersion=23).
There has been a lot of documentation regarding the new Marshmallow permission model. One of them is SYSTEM_ALERT_WINDOW been 'promoted' to 'above dangerous' permission class thus requiring a special user intervention in order for apps to be granted with those. If the app has targetSdkVersion 22 or lower, app gets this permission automatically (if requested in the manifest).
However, I've noticed some apps that get this permission, without needing to send the user to the setting special page of Draw over other apps permission. I saw Facebook, Evernote, Pocket - and perhaps there are more.
Anyone knows how an app can be granted this permission without the user go through Settings -> Apps -> Draw over other apps?
Thanks
It is a new behaviour introduced in Marshmallow 6.0.1.
Every app that requests the SYSTEM_ALERT_WINDOW permission and that is installed through the Play Store (version 6.0.5 or higher is required), will have granted the permission automatically.
If instead the app is sideloaded, the permission is not automatically granted. You can try to download and install the Evernote APK from apkmirror.com. As you can see you need to manually grant the permission in Settings -> Apps -> Draw over other apps.
These are the commits [1] [2] that allow the Play Store to give the automatic grant of the SYSTEM_ALERT_WINDOW permission.
Yeh After Marshmallow come Android make security level more stick, But For SYSTEM_ALERT_WINDOW you can show floating action and anything You can Force user to give permission for it By Following Codes in your onCreate() method.
Put this code after setContentView:
// Check if Android M or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Show alert dialog to the user saying a separate permission is needed
// Launch the settings activity if the user prefers
Intent myIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
startActivity(myIntent);
}
The action ACTION_MANAGE_OVERLAY_PERMISSION directly launches the 'Draw over other apps' permission screen.
Edit:
My Above Code works 100% Correct
But I just found that many guys are still searching that how can allow ACTION_MANAGE_OVERLAY_PERMISSION permanently like If user has allow Permission Once then don't ask it every time he open application so here is a solution for you:
Check if device has API 23+
if 23+ API then check if user has permit or not
if had permit once don't drive him to Settings.ACTION_MANAGE_OVERLAY_PERMISSION and if has not permit yet then ask for runtime permission check
Put below line in your onCreate() method. Put this after setContentView:
checkPermission();
Now put below code in onActivityResult:
#TargetApi(Build.VERSION_CODES.M)
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {
if (!Settings.canDrawOverlays(this)) {
// You don't have permission
checkPermission();
} else {
// Do as per your logic
}
}
}
Now finally the checkPermission method code:
public void checkPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
}
}
}
And don't forget to declare this public variable in your class:
public static int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE = 5469;
Now(2019) that Google offers an alternative API to SYSTEM_ALERT_WINDOW in the form of Bubbles in Android Q, Google has decided to eventually deprecate SYSTEM_ALERT_WINDOW in a future Android release.
And Android Go devices will no longer grant this permission
i.e Settings.canDrawOverlays() == false
For those who want to get this permission automatically when the app is downloaded from the Play Store, besides the SYSTEM_ALERT_WINDOW in the Manifest, you should go to this link and request this from Google.
You have to provide some additional information why you need this permission and Google will review and give you the automatically permission.
Bear in mind that before you ask for this, you have to:
Have the SYSTEM_ALERT_WINDOW permission in the Manifest
Prompt the user to grant the SYSTEM_ALERT_WINDOW permission within your app, when not already granted
If I miss something feel free to update the answer
If the app targets API 22 or lower, then Play Store will give the SYSTEM_ALERT_WINDOW permission and others when the user clicks to install (showing an alert) even if its device is Android 6.0
Otherwise, if the app targets API 23 or above, so that permission will be request to grant in run time.
I'm using this to get permission:
if (ContextCompat.checkSelfPermission(context, Manifest.permission.GET_ACCOUNTS) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(context, Manifest.permission.GET_ACCOUNTS)) {
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(context, new String[]{Manifest.permission.GET_ACCOUNTS}, PERMISSIONS_REQUEST_GET_ACCOUNTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
But the pop up dialog for permission asks user for access Contacts!?!?
In pre 6.0 in Play Store with
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
request is named Identity and explains I need it to get device account.
That is because of Permission Groups. Basically, permissions are placed under different groups and all permissions from that group would be granted if one of them is granted.
Eg. Under "Contacts" , there is write/read contacts and get accounts, so when you ask for any of those, the popup asks for Contacts permissions.
Read through: Everything every Android Developer must know about new Android's Runtime Permission
EDIT 1
Just thought i'l add the related(not to get accounts but permissions and groups) Oreo update info:
source: https://developer.android.com/about/versions/oreo/android-8.0-changes.html#rmp
Prior to Android 8.0 (API level 26), if an app requested a permission
at runtime and the permission was granted, the system also incorrectly
granted the app the rest of the permissions that belonged to the same
permission group, and that were registered in the manifest.
For apps targeting Android 8.0, this behavior has been corrected. The
app is granted only the permissions it has explicitly requested.
However, once the user grants a permission to the app, all subsequent
requests for permissions in that permission group are automatically
granted.
GET_ACCOUNTS was moved into the CONTACTS permission group in Android 6.0. While the API has us provide permissions, the user (for Android 6.0 at least) is prompted for permission groups. Hence, the user will be given the same prompt for GET_ACCOUNTS as the user would get for READ_CONTACTS or WRITE_CONTACTS.
Fortunately this will change in Android N
http://developer.android.com/preview/behavior-changes.html#perm
The GET_ACCOUNTS permission is now deprecated. The system ignores this
permission for apps that target Android N.
In Marshmallow all dangerous permissions belong to permission groups.
The permission android.permission.GET_ACCOUNTS belongs to CONTACTS group
You can find more information about dangerous permission and their groups here:
https://developer.android.com/guide/topics/security/permissions.html#normal-dangerous
I got your question wrong first. On this page http://developer.android.com/guide/topics/security/permissions.html#perm-groups, your can see that GET_ACCOUNTS refers to the permission group contacts. Because of that your are prompted for contact permission.
If your using the GET_ACCOUNTS permission to ask the user to select a particular account type on the device(Google in my case), you can use the AccountPicker class which doesn't require any special permissions
Intent intent = AccountPicker.newChooseAccountIntent(null, null,
new String[]{GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE},
false, null, null, null, null);
try {
startActivityForResult(intent, REQUEST_ACCOUNT_PICKER);
} catch (ActivityNotFoundException e) {
// This device may not have Google Play Services installed.
}
You'll need Google Play services auth in your gradle dependencies
implementation com.google.android.gms:play-services-auth:16.0.1
This avoids the Contacts permission popup for me