Ok, I have the following code and warning in AS:
When I agree to add such check, AS insert following code:
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return TODO;
}
And I'm just wondering, why AND operator is using?
If user reject only one of permissions above, such check wouldn't be working, as for me.
Or I miss something?
You can get location in different ways. Getting it from GPS using LocationManager.GPS_PROVIDER, from network using LocationManager.NETWORK_PROVIDER and from LocationManager.PASSIVE_PROVIDER (GPS).
permission.ACCESS_FINE_LOCATION is needed for GPS_PROVIDER and PASSIVE_PROVIDER.
permission.ACCESS_COARSE_LOCATION is needed for NETWORK_PROVIDER
According to doc:
Note: If you are using both NETWORK_PROVIDER and GPS_PROVIDER, then
you need to request only the ACCESS_FINE_LOCATION permission, because
it includes permission for both providers. (Permission for
ACCESS_COARSE_LOCATION includes permission only for NETWORK_PROVIDER.)
So probably Android Studio does not check if you are using both, so it plays safe and checks for both
You dont need to check both these permissions. Even if only fine location access is denied ,the other one is automatically denied and vice versa.
Bothe comes in the same group- LOCATION
http://developer.android.com/guide/topics/security/permissions.html#normal-dangerous
Related
I'd like to grant android.permission.READ_PRIVILEGED_PHONE_STATE permission to my app, but even though it's a system app (in system-priv folder on a rooted device for tests) it's not granted.
ADB shows request for this permission, but it's not granted.
In the Manifest I have
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" tools:ignore="ProtectedPermissions" />
When I try to check it in the runtime
if (ActivityCompat.checkSelfPermission(context.getApplicationContext(), Manifest.permission.READ_PRIVILEGED_PHONE_STATE) == PackageManager.PERMISSION_GRANTED)
the AS gives "Cannot resolve symbol 'READ_PRIVILEGED_PHONE_STATE'" and the app won't compile.
Why READ_PRIVILEGED_PHONE_STATE is visible in the Manifest, but not visible in the java code (also missing in Manifest.class) ?
How can I grant this permission?
I tested it on rooted Android Oreo.
Edit: This answers a part of my question: Permission is not a changeable permission type
The permission was granted on Lollipop, but not on Oreo.
But the question remains: Why READ_PRIVILEGED_PHONE_STATE is visible in the Manifest, but not visible in the java code (also missing in Manifest.class) ?
What I think might be happening is that Drobinsky did not call:
String[] permissions = {"android.permission.READ_PHONE_STATE"};
int requestCode = 5;
ActivityCompat.requestPermissions(this,permissions, requestCode);
prior to calling "ActivityCompat.checkSelfPermission(…"
In the activity you can also add a permissions notififcation handler which looks like this:
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 5: //REQUEST_READ_PHONE_STATE:
if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
// Do what you want to do with the granted permission
Even though you've got the permission added in the manifest, the user must also grant this permission at runtime. What happens is that a popup will occur asking the user to grant this permission, and if the user grants it, the "checkSelfPermission" method will then work correctly. The popup block is automatic; i.e. no code needs to be added to the app. I think you can add a text message that displays the reason the permission is required. Certain permission requests need to be handled in this manner, whereas some permission requests are granted without user intervention required. I think the Android model is that if a request is deemed "dangerous" it requires the user give their permission to grant the app access to these so called dangerous privileges.
I'd like to know why my permission are not asked when I'm launching my app, here's my manifest permissions :
<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"/>
And when I go through the param of my phone, I only have the "position" permission (and it's disabled).
If by permission not asked you mean that the user isn't being prompted to allow internet permission then that is normal. Internet is in the normal permissions list so it is auto granted. For more information about normal permissions take a look at: https://developer.android.com/guide/topics/permissions/normal-permissions.html
Also, adding permissions is a two step process; once you have declared the permission you need in your manifest, you will also have to do some setup in your java file. Take a look at https://developer.android.com/training/permissions/requesting
Additionally, if you are looking for easier ways to deal with permissions then there are libraries out there for that too such as RxPermissions: https://github.com/tbruyelle/RxPermissions
Hopefully this helps!
You should ask for a Runtime Permission
Please see the documentation:
Request App Permissions
If you are targeting SDK 26+, then you need to check for permissions in code like this:
if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
MY_PERMISSIONS_ACCESS_FINE_LOCATION)
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
} else {
// Permission has already been granted - or running on old Android
}
It is described in Request App Permissions
for marshmallow(API 23) and above you should get permission for location, phone states and other dangerous permissions not only in your manifest but in your code (Run Time Permission).for other permissions, manifest is enough.
see this video
also you can find your solution in this Q&A
Android Things only support limited number of API such Cast, Drive, and Location APIs. I'm trying to work with one API and I want to map between the API methods and its required permission. I'm not sure what is the best approach to do such a task. I'm working with Intel Edison board. Basically, I need to do something like this:
====== Method ============= Required Android Permission =============
=====getLocation()====>===== android.permission.ACCESS_FINE_LOCATION
=====getBeaconState()===>===== android.permission.ACCESS_FINE_LOCATION
Also, I need to see what happens if the permission required is missing? I'm just looking for thoughts on how to do these tasks.
I'm not sure what you are trying to achieve, if it is documentation or something in code, but fwiw AndroidThings act's differently for permissions, so you don't have to do anything in your codebase.
Requesting Permissions at Runtime is not supported because embedded devices aren't guaranteed to have a UI to accept the runtime dialog. Declare permissions that you need in your app's manifest file. All normal and dangerous permissions declared in your app's manifest are granted at install time.
This is from the Android Things docs https://developer.android.com/things/sdk/index.html
As you can see it says
All normal and dangerous permissions declared in your app's manifest are granted at install time.
Therefore if you use maps that requires ACCESS_FINE_LOCATION you will be granted the permission at install time and will not need to code anything for "runtime permissions" as they do not exist.
Try this for location runtime permission
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) ==
PackageManager.PERMISSION_GRANTED) {
//Do your work if permission already granted
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
}
and override onRequestPermissionResult
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == 1) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Do your Work
}
}
}
Declare this in AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
Install the apk on device, and then reboot the device, it fixed my issue.
Use ActivityCompat.checkSelfPermission for check permission.
Use ActivityCompat.requestPermissions for request permission.
Use interface ActivityCompat.OnRequestPermissionsResultCallback for callback.
I'm building a Cardboard app and testing it on a Nexus 6P.
The problem I have is that when I install the app, it doesn't ask for any permissions.
In my manifest I have this:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Then if I want to download some file from the internet in my app, it doesn't work. It doesn't even create the com. folder.
I have to go manually to the app info and check the storage permission.
It's weird because when building the app for GearVR and testing it on a Note 4, it asks for permission (in the Note 4 I use the sd card, in Nexus 6P the internal)
Why is this happening?
Thank you.
For Android 6+ you need to request permissions at runtime, not startup. This is especially the case if you are considering your app for Google Play featuring,
In short, you need to specify the permission in tour manifest, and also include the following in your application tag
<meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" />
Then, request the permission(s) at runtime via Android.
There is a great little plugin for this at https://www.assetstore.unity3d.com/#!/content/62735
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. Thats a reason why you didn't have request dialog.
If you need to request permission you need to show request rationale and handle user iteration result.
From docs :
Request permission :
if (ContextCompat.checkSelfPermission(thisActivity,Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
Handle User Choosed Option
In ActivityCompat :
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
Starting with Android 6.0 (Marshmallow) apps no longer get all permissions on install like they used to. You now have to request the permissions at runtime (which the user can decline) and have to be able to handle the permission getting revoked any time after it has been granted.
If you want to use the old behavior for now, I believe you should be able to set your target API level to 22.
Read more here: http://developer.android.com/training/permissions/requesting.html
for a quick fix, you can target android 5 (api level 22 instead of 23) and the permissions will keep using the old behavior.
note, if you publish an app targeting android 6 (level 23) api, you can't deprecate the target api level in an update.
https://developer.android.com/training/permissions/requesting.html
I am trying to use GPS in android but it gives me this error:
I put in manifest these 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"/>
can anyone help me please
As the hint suggests : The user may deny permission. In that case this call will throw error...
Right now, android asks for the user to accept all the permissions an app asks for in the manifest on installation. In the upcoming M release, android will switch over to the iOS style of permissions with an "on needed" basis.
Call this method to see if permission is granted or not. If not, you need to handle that situation.
context.checkCallingPermission(permission)
Declaring permission in manifest only means that you are requesting permission. In new releases it will not guarantee that user will give you that permission.
In older releases the user has to accept all or reject all permissions
This is not an error actually but a heads-up by the Lint and which may cause an issue!
Hope you are aware about the new permission model is introduced in Android 6.0 (Marshmallow), through which user may not permit to use GPS or Network or anything else and so it may cause an issue in your application!
Now, as per the lint analysis, so before implementing particular functionality, you should check whether permission for the same is available or not!
Since SDK 23, you should/need to check the permission using checkSelfPermission
http://developer.android.com/reference/android/support/v4/content/ContextCompat.html
for example
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
This condition checks user allowed to access the permission to read the location
if(checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)== PackageManager.PERMISSION_GRANTED||checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER,meter,mill,new locationlist(this));
}