Skip to content

Commit

Permalink
Request POST_NOTIFICATIONS permission in Android 13+
Browse files Browse the repository at this point in the history
  • Loading branch information
dpalou committed Apr 12, 2023
1 parent 7a248a5 commit 7ec3ad4
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 5 deletions.
7 changes: 6 additions & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@
<config-file target="AndroidManifest.xml" parent="/manifest">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" android:required="false" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
</config-file>

<source-file
Expand Down Expand Up @@ -206,6 +207,10 @@
src="src/android/notification/util/AssetUtil.java"
target-dir="src/de/appplant/cordova/plugin/notification/util" />

<source-file
src="src/android/notification/util/CallbackContextUtil.java"
target-dir="src/de/appplant/cordova/plugin/notification/util" />

<source-file
src="src/android/notification/Builder.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
Expand Down
38 changes: 36 additions & 2 deletions src/android/LocalNotification.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
import android.content.Context;
import android.util.Pair;
import android.view.View;
import android.Manifest;
import android.content.pm.PackageManager;
import android.util.Log;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
Expand All @@ -48,6 +51,7 @@
import de.appplant.cordova.plugin.notification.Options;
import de.appplant.cordova.plugin.notification.Request;
import de.appplant.cordova.plugin.notification.action.ActionGroup;
import de.appplant.cordova.plugin.notification.util.CallbackContextUtil;

import static de.appplant.cordova.plugin.notification.Notification.Type.SCHEDULED;
import static de.appplant.cordova.plugin.notification.Notification.Type.TRIGGERED;
Expand All @@ -61,6 +65,8 @@
@SuppressWarnings({"Convert2Diamond", "Convert2Lambda"})
public class LocalNotification extends CordovaPlugin {

public static final String TAG = "LocalNotification";

// Reference to the web view for static access
private static WeakReference<CordovaWebView> webView = null;

Expand Down Expand Up @@ -210,7 +216,7 @@ private void launch(CallbackContext command) {
* JavaScript.
*/
private void check (CallbackContext command) {
boolean allowed = getNotMgr().hasPermission();
boolean allowed = getNotMgr().areNotificationsEnabled();
success(command, allowed);
}

Expand All @@ -221,7 +227,23 @@ private void check (CallbackContext command) {
* JavaScript.
*/
private void request (CallbackContext command) {
check(command);
if (getNotMgr().areNotificationsEnabled()) {
success(command, true);

return;
}

if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.TIRAMISU) {
// Notifications are disabled and POST_NOTIFICATIONS runtime permission is not supported.
success(command, false);

return;
}

// Request the runtime permission.
int requestId = CallbackContextUtil.storeContext(command);

cordova.requestPermissions(this, requestId, new String[]{Manifest.permission.POST_NOTIFICATIONS});
}

/**
Expand Down Expand Up @@ -635,6 +657,18 @@ private Manager getNotMgr() {
return Manager.getInstance(cordova.getActivity());
}

public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) {
try {
CallbackContext context = CallbackContextUtil.getContext(requestCode);
CallbackContextUtil.clearContext(requestCode);

success(context, grantResults[0] == PackageManager.PERMISSION_GRANTED);
} catch (Exception e) {
String error = "Exception occurred onRequestPermissionsResult: ".concat(e.getMessage());
Log.e(TAG, error);
}
}

}

// codebeat:enable[TOO_MANY_FUNCTIONS]
4 changes: 2 additions & 2 deletions src/android/notification/Manager.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ public static Manager getInstance(Context context) {
}

/**
* Check if app has local notification permission.
* Ask if user has enabled permission for local notifications.
*/
public boolean hasPermission () {
private boolean areNotificationsEnabled () {
return getNotCompMgr().areNotificationsEnabled();
}

Expand Down
113 changes: 113 additions & 0 deletions src/android/notification/util/CallbackContextUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/

package de.appplant.cordova.plugin.notification.util;

import java.util.HashMap;
import java.util.Random;

import org.apache.cordova.CallbackContext;

/**
* Utils class to handle callback contexts.
* Most of the code in this class was copied from the Diagnostic plugin: https://github.com/dpa99c/cordova-diagnostic-plugin
*/
public final class CallbackContextUtil {

// Map of permission request code to callback context.
protected static HashMap<Integer, CallbackContext> callbackContexts = new HashMap<Integer, CallbackContext>();

/**
* Constructor
*/
private CallbackContextUtil() {
}

/**
* Gets a callback context.
*
* @param requestId Request ID.
* @return Callback context.
*/
public static CallbackContext getContext(int requestId) throws Exception {
if (!callbackContexts.containsKey(requestId)) {
throw new Exception("No context found for request id=" + requestId);
}

return callbackContexts.get(requestId);
}

/**
* Store a callback context.
*
* @param callbackContext Context to store.
* @return Random request ID.
*/
public static int storeContext(CallbackContext callbackContext){
Integer requestId = generateRandomRequestId();
callbackContexts.put(requestId, callbackContext);

return requestId;
}

/**
* Removes a callback context.
*
* @param requestId Request ID.
*/
public static void clearContext(int requestId) {
if (!callbackContexts.containsKey(requestId)) {
return;
}

callbackContexts.remove(requestId);
}

/**
* Generate a random request ID.
*
* @return Random request ID.
*/
private static Integer generateRandomRequestId() {
Integer requestId = null;

while (requestId == null) {
requestId = generateRandom();
if (callbackContexts.containsKey(requestId)) {
requestId = null;
}
}

return requestId;
}

/**
* Generate a random number.
*
* @return Random number.
*/
private static Integer generateRandom() {
Random rn = new Random();

return rn.nextInt(1000000) + 1;
}

}

0 comments on commit 7ec3ad4

Please sign in to comment.