6

EDITS BELOW =)

There are many many many questions on this topic on SO already, I know. However, none of the answers I have found so far resolves the issue for me.

The problem: That the ActivityCompat.requestPermissions does not trigger a popup, asking the user to give permission for notifications.

Setup:

  • Testing on physical device (Android 13, Pixel 6)
  • Targeting SDK version 33 (targetSdkVersion=33)
  • minSdkVersion = 29
  • AndroidManifest has permission: <uses-permission android:name="android.permission.POST_NOTIFICATION" />
  • in onCreate in an otherwise working Activity, I do:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_DENIED)
{
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.POST_NOTIFICATIONS}, 1);
}

and the callback is like so:

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case 1:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(MainScreenActivity.this, "Woho, you have enabled notifications!", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(MainScreenActivity.this, "Ouch, this is gonna hurt without notifications", Toast.LENGTH_SHORT).show();
            }
            return;
    }
}

Here are the build.gradle files:

TheApp\build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
        maven { url 'https://raw.github.com/xujiaao/mvn-repository/master/releases' }
        maven {
            url 'https://jitpack.io'
        }
        maven { url 'http://dl.bintray.com/ahmedrizwan/maven'
            allowInsecureProtocol = true
        }
        google()

    }
    dependencies {
        classpath 'com.google.gms:google-services:4.3.10'  // Google Services plugin
        classpath 'com.google.firebase:firebase-crashlytics-gradle:2.5.2'
        classpath 'com.android.tools.build:gradle:7.3.1'
        classpath "io.realm:realm-gradle-plugin:10.0.0"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local'
            allowInsecureProtocol = true
        }
        google()
        jcenter()
        flatDir {
            dirs 'src/main/libs'
        }
    }
}

TheApp\app\build.gradle


apply plugin: 'com.android.application'
apply plugin: 'realm-android'
apply plugin: 'com.google.firebase.crashlytics'

android {
    compileSdkVersion 33
    lintOptions {
        abortOnError false
    }

    buildFeatures{
        dataBinding = true
    }

    defaultConfig {
        applicationId "test.myapp"
        minSdkVersion 29
        targetSdkVersion 33
        versionCode 60
        versionName "1.60"

    }
    buildTypes {

        debug {
            signingConfig signingConfigs.debug_keystore
            aaptOptions.setProperty("cruncherEnabled", false)
        }

        release {
            signingConfig signingConfigs.release_keystore
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            aaptOptions.setProperty("cruncherEnabled", false)
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    namespace 'test.myapp'
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.cardview:cardview:1.0.0'

    implementation 'com.google.firebase:firebase-core:17.5.1'
    implementation 'com.google.firebase:firebase-messaging:20.3.0'

    implementation 'com.google.code.gson:gson:2.8.6'
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    implementation 'com.google.android.gms:play-services-gcm:17.0.0'
    implementation 'com.google.android.gms:play-services-location:17.1.0'
    implementation 'com.google.android.gms:play-services-maps:17.0.0'

    implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
    implementation "androidx.preference:preference-ktx:1.1.1"
    implementation 'com.google.firebase:firebase-crashlytics:17.2.2'
    implementation 'com.google.firebase:firebase-analytics:17.6.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
    implementation 'com.google.android.play:app-update:2.0.1'

    def fragment_version = "1.5.4"

    // Java language implementation
    implementation "androidx.fragment:fragment:$fragment_version"
    // Kotlin
    implementation "androidx.fragment:fragment-ktx:$fragment_version"
    // Testing Fragments in Isolation
    debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
}
apply plugin: 'com.google.gms.google-services'  // Google Play services Gradle plugin


I have stepped through the code via the debugger, and can confirm that the requestPermissions is executed, but that the onRequestPermissionsResult is triggered immediately with no popup on device.

I also read this, but I figured that it was down to developers not implementing the opt-in model as described here, but maybe, this is an issue after all? Cause I cannot make sense of this...

UPDATE

I ask for other permissions in other parts of the app, and this line works well - I get the popup to grant permission:

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, BaseActivity.PHONE_STATE_PERMISSION_CODE);

UPDATE 2

In another part of the code base, I have the same requestPermission call, but for another permission, and this works like a charm:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);

    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, BaseActivity.PHONE_STATE_PERMISSION_CODE);
}

When this is executed, I get this: enter image description here

But, if I change the requestPermissions call so it looks like this, nothing happens and I get to the callback immediately, with a "rejected":

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);

    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.POST_NOTIFICATIONS}, BaseActivity.PHONE_STATE_PERMISSION_CODE);
}

Picture: enter image description here

UPDATE 3

I have also tried using the new ActivityResultLauncher, but the behaviour is the same - it goes directly to the callback without showing any popup.

Ted
  • 19,727
  • 35
  • 96
  • 154
  • current support/compat/androidx libs? – snachmsm Dec 05 '22 at 21:42
  • Updated question with build.gradles – Ted Dec 05 '22 at 21:47
  • Yes for POST_NOTIFICATIONS there is no permission dialog. Its just granted. Like many others. Try READ_MEDIA_IMAGES instead for a pop up. – blackapps Dec 05 '22 at 21:49
  • @blackapps that is not what the docs say... – Ted Dec 05 '22 at 21:54
  • @blackapps - now you need some coffee or break.. :) [`POST_NOTIFICATIONS`](https://developer.android.com/develop/ui/views/notifications/notification-permission#user-choice) do show dialog and [`READ_MEDIA_IMAGES`](https://developer.android.com/about/versions/13/behavior-changes-13#granular-media-permissions) is just a newer `READ_EXTERNAL_STORAGE` only for images, there is no word for accessing filesystem by OP... – snachmsm Dec 05 '22 at 22:10
  • 1
    I'm about to call it a day ;-) – blackapps Dec 05 '22 at 22:31
  • Instead of ***onRequestPermissionsResult*** which is now deprecated, I believe we should use ***ActivityResultLauncher***. https://developer.android.com/training/permissions/requesting#request-permission https://stackoverflow.com/questions/66551781/android-onrequestpermissionsresult-is-deprecated-are-there-any-alternatives – ecle Dec 06 '22 at 05:41
  • I looked at that one, but it was optional as far as I understood it? And the other version see med much easier to implement (found no examples of the other version,rhe PermissionRequest i think it was called)... – Ted Dec 06 '22 at 06:23
  • I tried using the code on the SO link you posted, but there is no change, the same behaviour as when using the code in my question above. Interesting thing: after `onActivityResult` is called (the callback in `ActivityResultLauncher`), then also the `onRequestPermissionsResult` is called. – Ted Dec 06 '22 at 07:59
  • What an odd problem with the Android 13 SDK. Let's say we change **minSdkVersion** to 33 to see what happens. Alternatively, if it does go into the **onRequestPermissionsResult** method/callback, try logging the output of ***result.get(Manifest.permission.POST NOTIFICATIONS)***. – ecle Dec 06 '22 at 08:51
  • On the other hand, `grantResults[0]` in your code only checks the first entry... If you pass a lot of permissions, this could be a problem. However, because it is only passing one permission, this is not an issue. – ecle Dec 06 '22 at 08:57
  • Hey @ecle, thankks for input. 1) I will try to change minSdkVersion. 2) Logg hte output of... What do you mean? 3) grantResults aint the problem, it is -1 in there, the problem is that I never get a popup for this one... – Ted Dec 06 '22 at 08:59
  • Java: `ActivityResultLauncher permissionRequest = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), result ->{ Log.i("PERMISSIONS", String.format("POST_NOTIFICATIONS=%s", result.get(Manifest.permission.POST_NOTIFICATIONS)));}); permissionRequest.launch(new String[]{Manifest.permission.POST_NOTIFICATIONS});` – ecle Dec 06 '22 at 09:06
  • To test, refer https://developer.android.com/develop/ui/views/notifications/notification-permission#test – ecle Dec 06 '22 at 09:18
  • I added some updates above, which makes this even more mysterious. – Ted Dec 06 '22 at 13:20
  • Examine this demo, which does not use the ***ActivityCompat.requestPermissions*** call as it needs the deprecated ***AppCompatActivity.onRequestPermissionsResult*** call but rather the most recent **ActivityResultLauncher** approach. https://www.droidcon.com/2022/03/21/notification-runtime-permission-android13/ – ecle Dec 06 '22 at 15:34
  • It is because you have already rejected the permission a few times already or you have deliberately disabled it in the app settings. Try to clear app data or uninstall and re-install the app. – Sovathna Hong Dec 06 '22 at 16:49
  • Thanks, but: @ecle I have also tried using the ActivityResultLauncher, exact same results - goes directly to the result callback, no popup is ever seen. – Ted Dec 07 '22 at 05:31
  • @SovathnaHong I have uninstalled and reinstalled the app like 100 times by now. Every time I reinstall and start, I get the "make and manage phone calls" permission popup, so I know for sure that the app is considered "new" and that permission is not set, thus the popup is displayed. However, the POST_NOTIFICATIONS does not show. – Ted Dec 07 '22 at 05:33
  • @Ted have you tested it according to the guide? https://developer.android.com/develop/ui/views/notifications/notification-permission#test – ecle Dec 08 '22 at 00:29
  • @ecle No, but the issue is resolved, see below. A typo! =) – Ted Dec 08 '22 at 07:41

2 Answers2

4

Stupid me. In the Q above, I did post what the AndroidManifest contained, and I wrote:

<uses-permission android:name="android.permission.POST_NOTIFICATION" />

This is not correct. I am missing an s, it shoul be:

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

Oops! :-)

Ted
  • 19,727
  • 35
  • 96
  • 154
  • 1
    Glad in your case you found that you missed S, letter. In my case I have S included, i.e., My app is built over ReactNative, I add the permission in AndroidManifest, requesting the permission which is not showing me the popup. Am using Android 13 Emulator with google playstore. – rjkolli7 Jan 16 '23 at 08:24
  • Which approach do use req permission?= – Ted Jan 18 '23 at 11:50
  • I made even stupider mistake: forgot to declare this permission in the manifest entirely. 30 min of wasted time. This would be a perfect place for Android to throw an exception to spare us all this trouble. – Vasiliy May 15 '23 at 09:32
0

update your AndroidX dependency, as only newest ones will have code handling freshly introduced permission.

replace

implementation 'androidx.appcompat:appcompat:1.2.0'

with

implementation 'androidx.appcompat:appcompat:1.5.1'

generally try to update (and consolidate) AndroidX libs version

snachmsm
  • 17,866
  • 3
  • 32
  • 74
  • Thanks, I updated it, synced gradle, built and deploed in debug to device - same thing unfortunately =( – Ted Dec 05 '22 at 21:57
  • 1
    just based on [my question](https://stackoverflow.com/questions/73736926/post-notifications-permission-dialog-not-showing), currently I don't see any differences in our snippets, have no other ideas... – snachmsm Dec 05 '22 at 22:05
  • There was one difference we all missed: a missing "S" in the AndroidManifest =) – Ted Dec 07 '22 at 08:27
  • 1
    glad you've found that after few hours/days pulling out your hair :) good luck! – snachmsm Dec 07 '22 at 08:32