Skip to content

Conversation

@roberi
Copy link
Collaborator

@roberi roberi commented Aug 12, 2025

Starting in Wear OS 4 (Android 13, API level 33), ongoing notifications are affected by the notification runtime permission. In the Wear app, there is currently no functionality to request this permission. If this permission is required and not granted, the ListenerService.showNotification() method exits.

// check if we have permission to post notification
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
    && checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS)
        != android.content.pm.PackageManager.PERMISSION_GRANTED) {
  return;
}

This PR introduces both a generic way to handle runtime permission in the Wearapp and specifically addresses the POST_NOTIFICATIONS permission requirement for Android 13 (API 33) and higher.

Key Changes include:

  • A new reusable component RequestPermissionActivity to manage requests for any Android runtime permission (for now only the POST_NOTIFICATIONS permission, but later also BODY_SENSORS for heart rate monitoring).
  • If needed, this activity displays a rationale to the user before the system permission dialog appears.
  • It reports the outcome of the permission request back to the calling component (if they are interested).
  • If the POST_NOTIFICATIONS permission is not already granted, the MainActivity (in the wear module) utilizes the new RequestPermissionActivity to prompt the user.
RunnerUp-Permission.mp4

roberi added 2 commits August 11, 2025 22:06
This commit adds RequestPermissionActivity to manage runtime permission requests on Wear OS. This activity is designed to be generic, capable of requesting any Android runtime permission. It displays a rationale to the user, if needed, before prompting for system permissions and reports the outcome of the request back to the calling component.
This commit introduces a check in MainActivity for the POST_NOTIFICATIONS permission on devices running Android 13 (API level 33) or higher. If the permission is not granted, MainActivity will now use RequestPermissionActivity to prompt the user.
@gerhardol
Copy link
Collaborator

If the permission is denied, the guidlines at least for phone states that you should not ask again.

The phone app is a little annoying here. I implemented that the app is not starting GPS unless all the time is ticked, to avoid error reports from users where the phone shut down GPS access after an hour or so. But that should maybe have been a snackbar or something in the GUI and maybe a default note.

Copy link
Owner

@jonasoreland jonasoreland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

awesome!
let's see if Gerhard want to chip in...or else I'll merge this.

@roberi
Copy link
Collaborator Author

roberi commented Aug 13, 2025

If the permission is denied, the guidlines at least for phone states that you should not ask again.

Ok, I see. I tried to follow the Workflow for requesting permissions on Android Developers, but I must have misunderstood something. Rereading them, I think the "error" is in my ActivityResultCallback. In their example, if the permission is not granted, they only "explain" to the user that the feature is unavailable because of the denial:

if (isGranted) {
  // Permission is granted. Continue the action or workflow in your
  // app.
} else {
  // Explain to the user that the feature is unavailable because the
  // feature requires a permission that the user has denied. At the
  // same time, respect the user's decision. Don't link to system
  // settings in an effort to convince the user to change their
  // decision.
}

In my code, I show the rational UI if not granted, which has the "explanation" and an OK button that requests the permission again:

if (isGranted) {
  sendPermissionResultAndFinish(true);
} else {
  if (shouldShowRequestPermissionRationale(permissionToRequest)) {
    rationaleUIRoot.setVisibility(View.VISIBLE);
  } else {
    sendPermissionResultAndFinish(false);
  }
}

Perhaps we should just send false instead:

if (isGranted) {
  sendPermissionResultAndFinish(true);
} else {
  sendPermissionResultAndFinish(false);
}

// or simply
// sendPermissionResultAndFinish(isGranted);

Then, the next time the user starts the app, the rational UI will be shown to "explain" why the permission is needed. If still denied, there will be no more "explaining".

@gerhardol
Copy link
Collaborator

Perhaps we should just send false instead:

Seem reasonable, no deep thoughts

There are reasons permissions for GPS and battery savings are annoying (if they are sufficient I am not the one to answer...), the notifications should not be.

Modified the ActivityResultCallback in RequestPermissionActivity
for permission requests. If a permission is denied, the activity
now sends the negative result and finishes the current permission
flow.

On subsequent starts of the Wear app, the rationale UI will be
presented if the permission is still denied. This approach
aligns better with Android permission guidelines.
@roberi
Copy link
Collaborator Author

roberi commented Aug 13, 2025

I think this change better aligns the permission request workflow with the Android guidelines.

RunnerUp-permission2.mp4

The "explanations" can still be improved if needed.

@jonasoreland jonasoreland requested a review from gerhardol August 15, 2025 04:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants