Skip to content

Commit

Permalink
Add permission prompt fallback (#1517)
Browse files Browse the repository at this point in the history
  • Loading branch information
rlepinski authored Sep 13, 2024
1 parent c2eddfc commit b25d4b6
Show file tree
Hide file tree
Showing 12 changed files with 834 additions and 370 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.urbanairship.json.JsonException;
import com.urbanairship.json.JsonValue;
import com.urbanairship.permission.Permission;
import com.urbanairship.permission.PermissionPromptFallback;
import com.urbanairship.permission.PermissionRequestResult;
import com.urbanairship.permission.PermissionStatus;
import com.urbanairship.permission.PermissionsManager;
Expand Down Expand Up @@ -154,23 +155,12 @@ protected void prompt(@NonNull Args args, @Nullable ResultReceiver resultReceive
PermissionsManager permissionsManager = Objects.requireNonNull(permissionsManagerSupplier.get());

permissionsManager.checkPermissionStatus(args.permission, before -> {
permissionsManager.requestPermission(args.permission, args.enableAirshipUsage, requestResult -> {
if (shouldFallbackToAppSettings(args, requestResult)) {
navigatePermissionSettings(args.permission);
GlobalActivityMonitor activityMonitor = GlobalActivityMonitor.shared(UAirship.getApplicationContext());
activityMonitor.addApplicationListener(new SimpleApplicationListener() {
@Override
public void onForeground(long time) {
permissionsManager.checkPermissionStatus(args.permission, after -> {
sendResult(args.permission, before, after, resultReceiver);
activityMonitor.removeApplicationListener(this);
});
}
});
} else {
sendResult(args.permission, before, requestResult.getPermissionStatus(), resultReceiver);
}
});
permissionsManager.requestPermission(
args.permission,
args.enableAirshipUsage,
args.fallbackSystemSettings ? PermissionPromptFallback.SystemSettings.INSTANCE : PermissionPromptFallback.None.INSTANCE,
requestResult -> sendResult(args.permission, before, requestResult.getPermissionStatus(), resultReceiver)
);
});
}

Expand All @@ -193,77 +183,6 @@ public boolean shouldRunOnMainThread() {
return true;
}

boolean shouldFallbackToAppSettings(@NonNull Args args, @NonNull PermissionRequestResult result) {
return args.fallbackSystemSettings &&
result.getPermissionStatus() == PermissionStatus.DENIED &&
result.isSilentlyDenied();
}

@MainThread
private static void navigatePermissionSettings(@NonNull Permission permission) {
if (permission == Permission.DISPLAY_NOTIFICATIONS) {
navigateToNotificationSettings();
} else {
navigateToAppSettings();
}
}

@MainThread
private static void navigateToNotificationSettings() {
Context context = UAirship.getApplicationContext();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, UAirship.getPackageName())
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

try {
context.startActivity(intent);
return;
} catch (ActivityNotFoundException e) {
UALog.d(e, "Failed to launch notification settings.");
}
}

Intent intent = new Intent("android.settings.APP_NOTIFICATION_SETTINGS")
.putExtra("app_package", UAirship.getPackageName())
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra("app_uid", UAirship.getAppInfo().uid);

try {
context.startActivity(intent);
return;
} catch (ActivityNotFoundException e) {
UALog.d(e, "Failed to launch notification settings.");
}

navigateToAppSettings();
}

private static void navigateToAppSettings() {
Context context = UAirship.getApplicationContext();
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
.addCategory(Intent.CATEGORY_DEFAULT)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.setData(Uri.parse("package:" + UAirship.getPackageName()));

try {
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
UALog.e(e, "Unable to launch settings details activity.");
}

intent = new Intent(Settings.ACTION_APPLICATION_SETTINGS)
.addCategory(Intent.CATEGORY_DEFAULT)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.setData(Uri.parse("package:" + UAirship.getPackageName()));

try {
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
UALog.e(e, "Unable to launch settings activity.");
}
}

protected static class Args {

public final boolean enableAirshipUsage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public interface PermissionDelegate {
*
* @param context The application context.
* @param callback The callback.
* @return The {@link PermissionStatus}.
*/
@MainThread
void checkPermissionStatus(@NonNull Context context, @NonNull Consumer<PermissionStatus> callback);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* Copyright Airship and Contributors */

package com.urbanairship.permission

/**
* Fallback for when a permission is silently denied.
*/
public sealed class PermissionPromptFallback {

/**
* Navigate to system settings. On return the status will be checked again.
*/
public data object SystemSettings: PermissionPromptFallback()

/**
* Run a custom callback. After running the callback, the status will be checked again.
*/
public class Callback(internal val callback: suspend () -> Unit): PermissionPromptFallback()

/**
* No fallback
*/
public data object None: PermissionPromptFallback()
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

package com.urbanairship.permission;

import java.util.Objects;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.core.util.ObjectsCompat;

/**
* Permission request result. See {@link PermissionsManager#requestPermission(Permission, boolean)}
Expand Down Expand Up @@ -69,6 +72,19 @@ public PermissionStatus getPermissionStatus() {
return permissionStatus;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PermissionRequestResult that = (PermissionRequestResult) o;
return isSilentlyDenied == that.isSilentlyDenied && permissionStatus == that.permissionStatus;
}

@Override
public int hashCode() {
return ObjectsCompat.hash(permissionStatus, isSilentlyDenied);
}

@Override
public String toString() {
return "PermissionRequestResult{" +
Expand Down
Loading

0 comments on commit b25d4b6

Please sign in to comment.