I am learning about request permission on runtime. My phone OS is kitkat. This is my code :
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ActivityCompat.requestPermissions(this, arrayOf("com.android.launcher.permission.INSTALL_SHORTCUT"), 1000)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == 1000) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//do something
}
}
}
But permission dialog not shown. Is there any mistakes in my code?
You can not ask runtime permission below Android 6.0
Below Android 6.0 all permisson are granted while user install the app
FYI
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app
Read about runtime permission
Kitkat(version 20)
or below versions of Android don't need runtime permission requests,you can just define the permission in AndroidManifest.xml file and that will be enough for the permissions.
example : <uses-permission android:name="android.permission.CAMERA"/>
BUT
For Lollipop(version 21) or higher version you need to add method to request permissions for your Application.
Android developer site quote,
In Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app.
Run time permissions are added in Android Marshmallow. Android versions prior to marshmallow will ask for permission during the app installation.
Check this to learn more about android runtime permissions
According to the google developer page:
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app.
Which means that your phone are required to ask for runtime permissions from API level-23, i.e, Marshmallow whereas KitKat is API level-19. So, no runtime permission will be asked by the Operating system.
Related
I've the permission rule configured as below in my MainActivityTest class
#Rule
public GrantPermissionRule permissionRule =
GrantPermissionRule.grant(RECORD_AUDIO, WRITE_EXTERNAL_STORAGE);
When I run below command to execute the tests on emulator with api 27
./gradlew connectedCheck
It fails with the below error
com.example.myapplication.MainActivityTest > testLaunch_main_activity[Pixel_XL_API_27(AVD) - 8.1.0] FAILED
androidx.test.espresso.NoActivityResumedException: No activities in stage RESUMED. Did you forget to launch the activity. (test.getActivity() or similar)?
at dalvik.system.VMStack.getThreadStackTrace(Native Method)
Surprisingly the permissions are showing as granted in the app info settings, but still its asking for permissions when the test is run on emulator with api version 27 (or lower)
Can someone please confirm if it is a bug in some android plugin or if I am missing anything here.
Source Code - https://github.com/vivekweb2013/test-android-project
You are using ContextCompat's checkSelfPermission to check whether the app has permission or not. This is backward compatible with the support libraries but not sure with androidx. Alternative to this can be to use PermissionChecker's checkSelfPermission api like,
For API level 22 and below,
int permission = PermissionChecker.checkSelfPermission(context, permission);
if (permission == PermissionChecker.PERMISSION_GRANTED) {
// permission is granted
} else {
// permission not granted
}
But given that these permissions RECORD_AUDIO and WRITE_EXTERNAL_STORAGE are dangerous permission which requires acknowledgement from the user before our app can start consuming it. Below API level 23, these permissions are granted automatically when it is declared in AndroidManifest so the other way to get rid of this issue can be to verify it only for API level 23+ since it makes sense to validate.
I'd suggest you use a RuleChain with an outer rule for permissions around the ActivityScenarioRule
The problem seems to come from a race between launching the activity through the scenario rule and the permission rule, with a RuleChain in place the order of execution becomes explicit and the behavior should be as expected.
Here's the updated code from your example:
public class MainActivityTest {
public GrantPermissionRule permissionRule =
GrantPermissionRule.grant(RECORD_AUDIO, WRITE_EXTERNAL_STORAGE);
public ActivityScenarioRule<MainActivity> rule = new ActivityScenarioRule<>(MainActivity.class);
#Rule
public RuleChain chain = RuleChain.outerRule(permissionRule).around(rule);
#Test
public void testLaunch_main_activity() {
onView(withId(R.id.txt_view)).check(matches(isDisplayed()));
}
}
i have xamarin forms app that have tracking and fore ground service for background tracking working fine when set android target api level 28 but after upgrade it target api level 29 to upload app to play store no background location permission set to app so cannot get location when app in background.
and this manifest Permissions:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
and this run time request in main activity:
private static string[] _initialPerms ={
Manifest.Permission.AccessFineLocation,
Manifest.Permission.AccessCoarseLocation
};
if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.AccessFineLocation) == Permission.Denied || ContextCompat.CheckSelfPermission(this, Manifest.Permission.Camera) == Permission.Denied)
{
RequestPermissions(_initialPerms, 1337);
}
thanks.
From Android 10, background location came as an independent resource. Apps have to request explicitly this permission besides the foreground one.
#TargetApi(29)
private fun Context.checkLocationPermissionAPI29(locationRequestCode : Int) {
if (checkSinglePermission(Manifest.permission.ACCESS_FINE_LOCATION) &&
checkSinglePermission(Manifest.permission.ACCESS_COARSE_LOCATION) &&
checkSinglePermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) return
val permList = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION)
requestPermissions(permList, locationRequestCode)
}
private fun Context.checkSinglePermission(permission: String) : Boolean {
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
}
The permission ACCESS_BACKGROUND_LOCATION is new after Android 10.0 . Even if you have set the target version to Api 29 , but the version of support SDK in Xamarin.Android is still v28.x.x.x (Android 9.0) .So this enumeration is still unavailable in Xamarin.Android now . What you need is just to wait the update of the support SDK .
In your case , ACCESS_BACKGROUND_LOCATION will compatible with old version .
If the application apply for ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION, the system will automatically add a permission ACCESS_BACKGROUND_LOCATION during building.
===========================Update===============================
On Android 10 (API level 29) and higher, you must declare the ACCESS_BACKGROUND_LOCATION permission in your app's manifest in order to request background location access at runtime. On earlier versions of Android, when your app receives foreground location access, it automatically receives background location access as well.
<manifest ... >
<!-- Required only when requesting background location access on
Android 10 (API level 29) and higher. -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</manifest>
More info refer to android document here.
I'm trying to comply with the Google requirements to request the permission ACTIVITY_RECOGNITION, for Android 10, but I don't seem to understand why there's no permission popup showing , like with the other permissions (ie, Location, storage,...)
The code I have is:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACTIVITY_RECOGNITION) != PackageManager.PERMISSION_GRANTED) {
Log.d("TAG", "PERMISSION 'ACTIVITY_RECOGNITION' NOT GRANTED");
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACTIVITY_RECOGNITION},
MY_PERMISSIONS_ACTIVITY_RECOGNITION);
} else
{
Log.d("TAG", "PERMISSION 'ACTIVITY_RECOGNITION' GRANTED");
}
And I'm always ending up on the 'NOT GRANTED' flow, but the ActivityCompat.requestPermissions is not showing no popup!
Is there anything else I'm Missing ?
The manifest contains the
and the app.gradle
minSdkVersion 29
targetSdkVersion 30
Running out of ideas, any help would be welcome.
Just to add, I'm running this on my Pixel 2, with the latest firmware available 10.0.0 (QP1A.191105.004, Nov 2019)
check : Privacy changes in Android 10
From API 29(Android Q, Android 10)
Android App need permission in AndroidManifest.xml
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
Before API 29 AndroidManifest.xml
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
check : Google Fit APIs
And
If the system-auto grants the android.permission.ACTIVITY_RECOGNITION permission, your app retains the permission after you update your app to target Android 10. However, the user can revoke this permission at any time in system settings.
Thanks.
I'm not sure i fully understand this. So, for the <= 21 API version we can just use AndroidManifest.xml to request permissions, but Lollipop and higher APIs we have Requesting permission on runtime feature. So i'm using it with this simpe code:
if (Build.VERSION.SDK_INT >= 23) {
mPermissionsToBeAsked.clear();
for (String permission : AudioRecordingThread.PERMISSIONS_NEEDED) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
mPermissionsToBeAsked.add(permission);
}
} ....
Then, if that list is not empty i'm requesting them :
if (mPermissionsToBeAsked.size() > 0) {
requestPermissions(mPermissionsToBeAsked.toArray(new String[0]), AUDIO_PERMISSIONS_REQUEST_CODE);
}
But, for some reason, on devices, for example, like Samsung Galaxy S7 with Android 6.0.1, all the permissions grandted by default when app is installed. So i want to know why, BUT, it's there is an even bigger concerne, when i go to my application in Application Manager and manually removing Microphone permision, in the app checkSelfPermission(permission) is still returning GRANTED. So the questions:
Why on devices with API level Lollipop and higher all permissions are still granted by default and above code won't add anything into mPersmissionToBeAsked?
Why if i manually removing permission with title MICROPHONE in Application manager checkSelfPermission(android.permission.RECORD_AUDIO) still returns GRANTED?
Just Cross verify in your app gradle file the targetsdk version is greater than 22.
defaultConfig {
// -----
targetSdkVersion 23
//----
}
If it is less than 23 than permission will automatically been granted to your app.
First of all it's Android M and above that handles permission granting. And that means you should have
targetSdkVersion 23
or above. Otherwise the system considers that the developper did not target this version, meaning that the developper does not check for permissions.
I am developing a file manager under Intellij IDEA 14.1.6 and I have to support USB OTG flash drives. My file manager works fine with USB OTG on devices with API < 23 (Marshmallow). I have seen multiple references with the statement (1, 2, 3):
...it doesn’t require full support until you choose to target version 23 in your application. If you are targeting version 22 or below, your application will request all permissions at install time just as it would on any device running an OS below Marshmallow.
My project has target:
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="22"/>
but Nexus 5 (upgraded to Android 6.0.1) can't see USB OTG flash drive, unlike to a few other devices with API 19, 21, 22 which can read and write to flash drive pretty easy.
The question is: Does anybody have checked this statement?
Does this statement apply to API 23 or to its preview version (M) only?
Does this statement apply to Android Studio only?
EDIT: The only way to get Nexus 5 with Marshmallow works with USB OTG as a previous API level devices is to use a command:
adb shell sm set-force-adoptable true
from terminal.
In Android 6.0+, the user needs to grant Storage access to the app else the application can't access Internal or External Storage.
You can do this in your app's MainActivity's onCreate(Bundle savedInstanceState) Method :
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
checkForPermissionsGrantStatus();
Than :
private void checkForPermissionsGrantStatus() {
int storagePermissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if(storagePermissionCheck == PackageManager.PERMISSION_DENIED)
requestForPermissionAccess(Manifest.permission.WRITE_EXTERNAL_STORAGE, 1);
}
private void requestForPermissionAccess(String permission, int requestCode) {
ActivityCompat.requestPermissions(this, new String[]{permission}, requestCode);
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults[0]== PackageManager.PERMISSION_GRANTED){
Toast.makeText(this, "Storage Permission Granted", Toast.LENGTH_SHORT).show();
}
}
On every run your application will check if the device runs Android 6.0+. If it does than it will check if it has Storage Permission. If yes than it will stop there else show a popup asking user to grant storage access.
Screenshot :