ActivityCompat.requestPermissions not showing dialog box - java

if (ContextCompat.checkSelfPermission(RegisterActivity.this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_DENIED){
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_PHONE_STATE}, REQUEST_READ_PHONE_STATE_PERMISSION);
i'm trying to use this function on nexus 5 api 23 and its just not showing me the dialog box like its supposed to do, it's just not doing anything.
what could cause the problem? (this code is in the java activity)
i tried changing my minimum api to 23 and use the requestPermissions() without the ActivityCompat but still not working.
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.example.idanayzen.photomap"
minSdkVersion 23
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.google.android.gms:play-services:8.4.0'
compile 'com.android.support:design:23.1.1'
}
and the Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.idanayzen.photomap">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_SMS" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="#string/google_maps_key" />
<activity
android:name=".MapsActivity"
android:label="#string/title_activity_maps" />
<activity android:name=".RegisterActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".WrongPhoneNum"></activity>
</application>
</manifest>

Here's an example of using requestPermissions():
First, define the permission (as you did in your post) in the manifest, otherwise, your request will automatically be denied:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Next, define a value to handle the permission callback, in onRequestPermissionsResult():
private final int REQUEST_PERMISSION_PHONE_STATE=1;
Here's the code to call requestPermissions():
private void showPhoneStatePermission() {
int permissionCheck = ContextCompat.checkSelfPermission(
this, Manifest.permission.READ_PHONE_STATE);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_PHONE_STATE)) {
showExplanation("Permission Needed", "Rationale", Manifest.permission.READ_PHONE_STATE, REQUEST_PERMISSION_PHONE_STATE);
} else {
requestPermission(Manifest.permission.READ_PHONE_STATE, REQUEST_PERMISSION_PHONE_STATE);
}
} else {
Toast.makeText(MainActivity.this, "Permission (already) Granted!", Toast.LENGTH_SHORT).show();
}
}
First, you check if you already have permission (remember, even after being granted permission, the user can later revoke the permission in the App Settings.)
And finally, this is how you check if you received permission or not:
#Override
public void onRequestPermissionsResult(
int requestCode,
String permissions[],
int[] grantResults) {
switch (requestCode) {
case REQUEST_PERMISSION_PHONE_STATE:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(MainActivity.this, "Permission Granted!", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "Permission Denied!", Toast.LENGTH_SHORT).show();
}
}
}
private void showExplanation(String title,
String message,
final String permission,
final int permissionRequestCode) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(title)
.setMessage(message)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
requestPermission(permission, permissionRequestCode);
}
});
builder.create().show();
}
private void requestPermission(String permissionName, int permissionRequestCode) {
ActivityCompat.requestPermissions(this,
new String[]{permissionName}, permissionRequestCode);
}

I had the same issue and it turned out to be due to the manifest merger tool pulling in an android:maxSdkVersion attribute from a dependency.
To view the actual permissions you're requesting in your APK you can use the aapt tool, like this:
/path/to/android-sdk/build-tools/version/aapt d permissions /path/to/your-apk.apk
in my case, it printed:
uses-permission: name='android.permission.WRITE_EXTERNAL_STORAGE' maxSdkVersion='18'
even though I hadn't specified a maxSdkVersion in my manifest. I fixed this issue by changing <uses-permission> in my manifest to:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion"/>
(where the tools namespace is http://schemas.android.com/tools)

I had a need to request permission for WRITE_EXTERNAL_STORAGE but was not getting a pop-up despite trying all of the different suggestions mentioned.
The culprit in the end was HockeyApp. It uses manifest merging to include its own permission for WRITE_EXTERNAL_STORAGE except it applies a max sdk version onto it.
The way to get around this problem is to include it in your Manifest file but with a replace against it, to override the HockeyApp's version and success!
4.7.2 Other dependencies requesting the external storage permission (SDK version 5.0.0 and later) To be ready for Android O,
HockeySDK-Android 5.0.0 and later limit the WRITE_EXTERNAL_STORAGE
permission with the maxSdkVersion filter. In some use cases, e.g.
where an app contains a dependency that requires this permission,
maxSdkVersion makes it impossible for those dependencies to grant or
request the permission. The solution for those cases is as follows:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="replace"/>
It will cause that other attributes from low
priority manifests will be replaced instead of being merged.
https://support.hockeyapp.net/kb/client-integration-android/hockeyapp-for-android-sdk#permissions-advanced

Replace:
ActivityCompat.requestPermissions(this, new String[]{"Manifest.permission.READ_PHONE_STATE"}, 225);
with:
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, 225);
The actual string for that permission is not "Manifest.permission.READ_PHONE_STATE". Use the symbol Manifest.permission.READ_PHONE_STATE.

It could be not a problem with a single line of your code.
On some devices (I don't recall if it is in stock Android) the Permission dialog includes a check box labeled "Never ask again". If you click Deny with the box checked then you won't be prompted again for that permission, it will automatically be denied to the app. To revert this, you have to go into Settings -> App -> Permissions and re--enable that perm for the app. Then turn it off to deny it again. You may have to open the app before turning it off again, not sure.
I don't know if your Nexus has it. Maybe worth a try.

Here is another experience I'd like to share with you guys. The problem showed up after I implemented the following code to check for BLE access permission:
final String requiredPermission = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && targetSdkVersion >= Build.VERSION_CODES.Q) ?
android.Manifest.permission.ACCESS_FINE_LOCATION :
android.Manifest.permission.ACCESS_COARSE_LOCATION;
I meant to distinguish between FINE and COARSE location permission requests, both had been defined in the manifest. When checking for ACCESS_COARSE_LOCATION permission, the "Request permission" dialog never poped up but onRequestPermissionsResult was always called with PERMISSION_DENIED (in case permission was not enabled in app settings). So I removed the check for BUILD.SDK and checked only for ACCESS_FINE_LOCATION and voilla the missing dialog showed up.
final String requiredPermission = android.Manifest.permission.ACCESS_FINE_LOCATION;
did the trick.
The Manifest source contains:
<uses-permission android:name="android.permission.COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
but the apk contained android.permission.ACCESS_FINE_LOCATION only. Sometime during build, the COARSE_LOCATION had been removed.
I hope this might help somebody having the same issue.

I updated my target SDK version from 22 to 23 and it worked perfectly.

Don't forget to write the permissions without extra spaces in the manifest. In my case, I had:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE " />
But look, at the end, there's an extra space. Just write it the right way:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
And it's working now.

No matter what you do, Check if you declare Permission you need in the Manifest file.
<!--Declaring the required permissions-->
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.CAMERA" />
Then go to next steps..

I followed the top answer, but still didn't work. This simple issue wasted me many days. For my case, I'm trying to get access for MANAGE_EXTERNAL_STORAGE. At the end, I found for this particular permission, we can't use ActivityCompat.requestPermissions(), instead I have to use Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION. And to check if the permission is there, we also need to use a different API: Environment.isExternalStorageManager() instead of ContextCompat.checkSelfPermission(), not sure why they design in such an inconsistent way cause so much confusions.
I get my issue resolved following: How to obtain MANAGE_EXTERNAL_STORAGE permission
And also this is mentioned in SDK document of: manage-all-files.

For me the issue was requesting a group mistakenly instead of the actual permissions.

The above information is good, but setting targetSdkVersion to 23 (or higher) is critical for Android to interpret the <uses-permission> tag in the manifest as "I will ask in code" instead of "I demand upon installation." Lots of sources will tell you that you need the <uses-permission> tag, but no one says why and if you don't have that value set, you're going to be as confused as I was for hours on end.

I came across this problem in Samsung S8 and N8 (havent found in any other)
so the problem is in the manifest file uses-permission
<uses-permission android:name="android.permission.CAMERA"
android:requiredFeature="true" />
For some reason, the attribute android:requiredFeature is the culprit. and I haven't found the explanation on why.
to solve simply remove it,
<uses-permission android:name="android.permission.CAMERA" />

In my case, target sdk 33 to 32 solves it

For me, this was related to them getting more granular with permissions in 33, related to requesting read_external_storage.
This is the kotlin code I'm using to check and request access in Jan 2023.
private fun checkPermissions():Boolean{
// version 33 gets more granular
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (checkSelfPermission(Manifest.permission.READ_MEDIA_IMAGES)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this, arrayOf(
Manifest.permission.READ_MEDIA_IMAGES,
Manifest.permission.READ_MEDIA_VIDEO // why isn't this plural too
),
1
)
return false
}
}else{
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this, arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE
),
1
)
return false
}
}
return true
}
I also had to add all 3 of these to my manifest, to support apis 31-33.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

I had this same issue.I updated to buildToolsVersion "23.0.3" It all of a sudden worked. Hope this helps anyone having this issue.

I was having the same problem, and solved it by replacing Manifest.permission.READ_PHONE_STATE with android.Manifest.permission.READ_PHONE_STATE.

For me the issue was I had an invalid request code. I choose 0xDEADBEEF as a request code and it was silently failing (maybe it's cast to something smaller than 32-bit somewhere internally?) If I choose 255 everything worked fine as NightSkyDev described above.

This just happened to me. It turned out I was requesting ALL permissions, when I needed to filter to just DANGEROUS permissions, and it suddenly started working.
fun requestPermissions() {
val missingDangerPermissions = PERMISSIONS
.filter { ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED }
.filter { this.getPackageManager().getPermissionInfo(it, PackageManager.GET_META_DATA).protectionLevel == PermissionInfo.PROTECTION_DANGEROUS } // THIS FILTER HERE!
if (missingDangerPermissions.isNotEmpty()) {
Log.i(TAG, "Requesting dangerous permission to $missingDangerPermissions.")
ActivityCompat.requestPermissions(this,
missingDangerPermissions.toTypedArray(),
REQUEST_CODE_REQUIRED_PERMISSIONS);
return
} else {
Log.i(TAG, "We had all the permissions we needed (yay!)")
}
}

For me the error was in the manifest: the permission was in uppercase. Android Studio suggest me the permissions in uppercase. I don't care about that and it took me two hours to fixe this problem.
The right syntaxe for permission is
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

For me the problem was that right after making the request, my main activity launched another activity. That superseded the dialog so it was never seen.

TL;DR:
Add the following to your Manifest file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:remove="android:maxSdkVersion" />
Check this article, it fixed it for me:
https://nphau.medium.com/android-request-permissions-not-showing-a-dialog-box-b7f2067d7b09

it happen to me i was running it on API 23 and i had to use the code to request permission like this code below put it on on create method. note that MY_PERMISSIONS_REQUEST_READ_LOCATION is an integer that is equal to 1 example int MY_PERMISSIONS_REQUEST_READ_LOCATION = 1:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{ Manifest.permission.ACCESS_COARSE_LOCATION},MY_PERMISSIONS_REQUEST_READ_LOCATION);
}

Maybe this solution could help anyone
rather than:
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
use :
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
so we add android. to Manifest.permission.WRITE_EXTERNAL_STORAGE

Related

Android Studio: How to write a ringtone / notification / alarm audio file to storage and see it in the settings

So this functionality was working previously, but I guess somewhere when I upgraded versions, it does not anymore.
I want to create dynamically an audio file (this is working), and copy it to the storage (this is working, it is currently copied to my local app storage :
Android/data/com.mypackagename/files/xxx.mp3
Then I create a new ContentValues with the data & metadata and insert it into MediaStore.Audio.Media.EXTERNAL_CONTENT_URI.
After that I set ringtone and launch ringtone picker to check:
RingtoneManager.setActualDefaultRingtoneUri(_instance, RingtoneManager.TYPE_RINGTONE, newUri);
Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, newUri);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, newUri);
startActivityForResult(intent, 1);
But the ringtone set is only the ID of the media, not the name, and I can't find it in the list..
I though the Media wasn't scanned, so i tried this beforehand:
Intent scanFileIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, newUri);
sendBroadcast(scanFileIntent);
I'm not really sure what this does, but it didn't helped.
Any clues what's going on with the current status of creating ringtone with Android Studio ?
So here was my error. I needed to correct some things in my Manifest to get the rights permissions:
//Without this folders will be inaccessible in Android-11 and above devices
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
//Without this entry storage-permission entry will not be visible under app-info permissions list Android-10 and below
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29"
tools:ignore="ScopedStorage"/>
//Without this entry the folders will remain in-accessible in Android-10, even if WRITE_EXTERNAL_STORAGE as above is present.
<application
android:requestLegacyExternalStorage="true"/>
The Ringtones external root folder is not accessible from basic WRITE_EXTERNAL_STORAGE permissions anymore. We have access to app specific external folder, & others (link).
Even the Media store does not give you access to this folder, so from Android 11 & forward, you need the MANAGE_EXTERNAL_STORAGE permission, that gives you this warning:
Most apps are not allowed to use MANAGE_EXTERNAL_STORAGE. Because you need to ask for this permission to the user, and he might refuse..
But if you want to do what I wanted to do, you'll need it..
Be sure that your app ask for the permission through:
// permission: Manifest.permission.WRITE_EXTERNAL_STORAGE
// permission_id: 1
public Boolean checkPermission(String permission, Integer permission_id) {
if (ContextCompat.checkSelfPermission(_instance, permission) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(_instance, new String[]{permission}, permission_id);
return false;
} else {
return true;
}
}

READ_SETTINGS permission needed to launch gmaps with intent on WEAR OS

My Android app has to launch gmaps on Wear OS
Uri gmmIntentUri = Uri.parse("https://www.google.com/maps/search/?api=1&query=" +Uri.encode( string));
Intent mapIntent = new Intent(ACTION_VIEW, gmmIntentUri);
// mapIntent.setPackage("com.google.android.apps.maps");
if (mapIntent.resolveActivity(activity.getPackageManager()) != null) {
activity.startActivity(mapIntent);
}
but I get an error that says Permission denial... It wants
com.google.android.wearable.READ_SETTINGS
If I put this
<uses-permission android:name="com.google.android.wearable.READ_SETTINGS" />
in the manifest then I get the same kind of error.
I am not able to ask for permission programmatically with something similar to this
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_SETTINGS)
== PackageManager.PERMISSION_GRANTED) {
Log.d("permissions","granted");
} else {
// Show rationale and request permission.
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.READ_SETTINGS},
MY_LOCATION_REQUEST_CODE);
}
because that constant is not found. It is not useful to write the complete com.google.android.wearable.READ_SETTINGS string.
I do not understand why READ_SETTINGS is needed.
How to solve?
Google Maps on wearOS cannot handle Uri.parse("https://www.google.com/maps/search/?api=1&query=" +Uri.encode( string)) or in this format as suggested in documentation Uri gmmIntentUri = Uri.parse("geo:0,0?q=1600 Amphitheatre Parkway, Mountain+View, California"). While the same intent on phone launches Google Maps and shows you a list of suggestions.
My guess is that the Maps app on wearOS is meant to be lightweight , you can only search for something in a particular city or region like this:
// Searches for 'Main Street' near San Francisco
Uri gmmIntentUri = Uri.parse("geo:37.7749,-122.4194?q=101+main+street");
The below link shows examples of Google Maps intents to use on Android : https://developers.google.com/maps/documentation/urls/android-intents
For the error:
com.google.android.wearable.READ_SETTINGS
You don't need to add this in permissions, but check whether your wear app manifest has this :
<uses-feature android:name="android.hardware.type.watch" />

permission for music files

I want to declare a permission to access all the music files from external storage
Please tell me all the books steps to achieve this.
Try put this in your manifest.xml :
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Put the following permissions in manifest.xml file outside the application tag
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
You need to update your manifest file first:
<manifest ...>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
...
</manifest>
External storage might be unavailable and that may cause the app to crash. So you need to check programmatically whether you have external storage available and if that storage is readable. The following code snippet will help to achieve the goals:
/* Checks if external storage is available to at least read */
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}

Get current location with network provider on osmdroid

In my android app I am using the osmdroid framework. In the framework I am using the MyLocationNewOverlay() which contains a method to show the current location on the map.
My problem
The LocationListener in the framework seems not to use the network provider and only wants to locate me with GPS (which works fine, but only if I am outside).
Is there a standard way to use a LocationProvider that also works with the network provider if gps is not available?
AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Pretty standard to init my location overlay:
private void initMyLocationNewOverlay() {
myLocationNewOverlay = new MyLocationNewOverlay(new GpsMyLocationProvider(context), mapView);
myLocationNewOverlay.enableMyLocation();
mapView.getOverlays().add(myLocationNewOverlay);
}
Thanks in advance!
The problem is that the GpsMyLocationProvider only adds the GPS_Provider to its sources (you can see that in the constructor). To add the network provider use the addLocationSource as following.
private void initMyLocationNewOverlay() {
GpsMyLocationProvider provider = new GpsMyLocationProvider(context);
provider.addLocationSource(LocationManager.NETWORK_PROVIDER);
myLocationNewOverlay = new MyLocationNewOverlay(provider, mapView);
myLocationNewOverlay.enableMyLocation();
mapView.getOverlays().add(myLocationNewOverlay);
}

Google In App BIlling Returns Null Purchases when calling getPurchases

I had writing an IAB(In App Billing) application . the premium purchase will be submitted into google dashboard and also I can see the invoice of that item and user cannot buy this item twice. so this is ok.
But by using code below I cannot understand that the user is premium or not, because the premiumPurchase is always null. ( I am calling this method in on setup finished listener)
mHelper.queryInventoryAsync(new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
if (mHelper == null) return;
if (result.isFailure()) {
return;
}
Purchase premiumPurchase = inventory.getPurchase(SKU_PREMUIM);
if(premiumPurchase!=null) {
//Toast.makeText(getApplicationContext(),"permuim",Toast.LENGTH_SHORT).show();
lblIsPremuim.setText("You are Premium");
}
else{
lblIsPremuim.setText("You are Not Premium");
Toast.makeText(getApplicationContext(),"not permuim",Toast.LENGTH_SHORT).show();
}
}
});
I had restarted the device and clear the cache of Google Play and I am sure that I have signed in with correct account. the base-64 public key is surely correct and I had read all posts in Stack-Over-Flow which has been mentioned about this issue but not finding a solution. I am using same version name and version code and same key store with uploaded app.
Finally after some days I had solved the problem by manipulating the AndroidManifest.XML file:
1) I had removed permission below: ( because I had thought that is conflicting with billing permission) , but possibly you can leave this line .
<uses-permission android:name="android.permission.INTERNET" />
2) I notified that there is such line in my AndroidManifest.xml:
<uses-sdk
android:minSdkVersion="21"
android:maxSdkVersion="9" />
So by above statement, min is more than max version , it is not logical , so I have changed this to below:
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
After that I cleaned the project and make a rebuild and also restarting the device.then I can get my all purchases...
Very Important
update : you should sign in sign out from your google store app.

Categories