Skip to content

Commit 555fc56

Browse files
authored
Merge pull request #221 from Unity-Technologies/android-api33-support
Android API 33 support
2 parents 45377b7 + 4068135 commit 555fc56

File tree

4 files changed

+170
-2
lines changed

4 files changed

+170
-2
lines changed

TestProjects/Main/Assets/Scripts/AndroidTest.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ void Start()
9393
((Action)m_groups["Channels"]["Create Secondary Simple Channel"]).Invoke();
9494
((Action)m_groups["Channels"]["Create Fancy Channel"]).Invoke();
9595
m_LOGGER.Clear().White("Welcome!");
96+
97+
HandleNotificationPermission();
9698
HandleLastNotificationIntent();
9799
}
98100

@@ -103,10 +105,25 @@ void OnApplicationPause(bool isPaused)
103105
.Gray($"isPaused = {isPaused}", 1);
104106
if (isPaused == false)
105107
{
108+
HandleNotificationPermission();
106109
HandleLastNotificationIntent();
107110
}
108111
}
109112

113+
private void HandleNotificationPermission()
114+
{
115+
var permission = AndroidNotificationCenter.UserPermissionToPost;
116+
switch (permission)
117+
{
118+
case PermissionStatus.Allowed:
119+
m_LOGGER.Green("Permission granted to post notifications");
120+
break;
121+
default:
122+
m_LOGGER.Red("No permission to post notifications: " + permission);
123+
break;
124+
}
125+
}
126+
110127
private void HandleLastNotificationIntent()
111128
{
112129
AndroidNotificationIntentData notificationIntentData = AndroidNotificationCenter.GetLastNotificationIntent();
@@ -159,6 +176,7 @@ private void InstantiateAllTestButtons()
159176
m_groups["General"]["Open Settings"] = new Action(() => { AndroidNotificationCenter.OpenNotificationSettings(); });
160177
m_groups["General"]["Notification batch size: "+NotificationBatchSizes[_CurrentNotificationBatchSizeIndex]] = new Action(() => { ChangeNotificationBatchSize(NotificationBatchSizes); });
161178
m_groups["General"]["Reset notification counter"] = new Action(() => { NotificationCounter = 0; });
179+
m_groups["General"]["Request permission"] = new Action(() => { RequestNotificationPermission(); });
162180

163181
m_groups["Modify"] = new OrderedDictionary();
164182
//m_groups["Modify"]["Create notification preset"] = new Action(() => { });
@@ -270,6 +288,31 @@ private void InstantiateAllTestButtons()
270288
m_gameObjectReferences.ButtonGroupTemplate.gameObject.SetActive(false);
271289
}
272290

291+
void RequestNotificationPermission()
292+
{
293+
var permission = AndroidNotificationCenter.UserPermissionToPost;
294+
if (permission == PermissionStatus.Allowed)
295+
m_LOGGER.Green("Already authorized");
296+
if (permission == PermissionStatus.DeniedDontAskAgain)
297+
m_LOGGER.Red("Denied, don't ask again");
298+
else
299+
{
300+
m_LOGGER.Blue("Requesting permission");
301+
permission = AndroidNotificationCenter.RequestPermissionToPost();
302+
switch (permission)
303+
{
304+
case PermissionStatus.Allowed:
305+
m_LOGGER.Green("Permission granted");
306+
break;
307+
case PermissionStatus.RequestPending:
308+
return;
309+
default:
310+
m_LOGGER.Red(permission.ToString());
311+
break;
312+
}
313+
}
314+
}
315+
273316

274317
public void ChangeNotificationBatchSize(int[] notificationBatchSizes)
275318
{

com.unity.mobile.notifications/Editor/AndroidNotificationPostProcessor.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ private void InjectAndroidManifest(string projectPath)
8282
AppendAndroidPermissionField(manifestPath, manifestDoc, "android.permission.RECEIVE_BOOT_COMPLETED");
8383
}
8484

85+
AppendAndroidPermissionField(manifestPath, manifestDoc, "android.permission.POST_NOTIFICATIONS");
86+
8587
manifestDoc.Save(manifestPath);
8688
}
8789

com.unity.mobile.notifications/Runtime/Android/AndroidNotificationCenter.cs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Linq;
33
using System.Collections.Generic;
44
using UnityEngine;
5+
using UnityEngine.Android;
56

67
#if UNITY_2022_2_OR_NEWER
78
using JniMethodID = System.IntPtr;
@@ -13,6 +14,37 @@
1314

1415
namespace Unity.Notifications.Android
1516
{
17+
/// <summary>
18+
/// Represents a status of the Android runtime permission.
19+
/// </summary>
20+
public enum PermissionStatus
21+
{
22+
/// <summary>
23+
/// No permission as user was not prompted for it.
24+
/// </summary>
25+
NotRequested = 0,
26+
27+
/// <summary>
28+
/// User gave permission.
29+
/// </summary>
30+
Allowed = 1,
31+
32+
/// <summary>
33+
/// User denied permission.
34+
/// </summary>
35+
Denied = 2,
36+
37+
/// <summary>
38+
/// User denied permission and expressed intent to not be prompted again.
39+
/// </summary>
40+
DeniedDontAskAgain = 3,
41+
42+
/// <summary>
43+
/// A request for permission was made and user hasn't responded yet.
44+
/// </summary>
45+
RequestPending = 4,
46+
}
47+
1648
/// <summary>
1749
/// Current status of a scheduled notification, can be queried using CheckScheduledNotificationStatus.
1850
/// </summary>
@@ -535,6 +567,15 @@ public static JniMethodID FindMethod(AndroidJavaClass clazz, string name, string
535567
/// </summary>
536568
public class AndroidNotificationCenter
537569
{
570+
private static int API_POST_NOTIFICATIONS_PERMISSION_REQUIRED = 33;
571+
private static string PERMISSION_POST_NOTIFICATIONS = "android.permission.POST_NOTIFICATIONS";
572+
573+
/// <summary>
574+
/// A PlayerPrefs key used to save users reply to POST_NOTIFICATIONS request (integer value of the PermissionStatus).
575+
/// </summary>
576+
/// <see cref="PermissionStatus"/>
577+
public static string SETTING_POST_NOTIFICATIONS_PERMISSION = "com.unity.androidnotifications.PostNotificationsPermission";
578+
538579
/// <summary>
539580
/// The delegate type for the notification received callbacks.
540581
/// </summary>
@@ -547,6 +588,8 @@ public class AndroidNotificationCenter
547588

548589
private static AndroidJavaObject s_CurrentActivity;
549590
private static JniApi s_Jni;
591+
private static int s_DeviceApiLevel;
592+
private static int s_TargetApiLevel;
550593
private static bool s_Initialized = false;
551594

552595
/// <summary>
@@ -575,11 +618,86 @@ public static bool Initialize()
575618
var notificationManager = notificationManagerClass.CallStatic<AndroidJavaObject>("getNotificationManagerImpl", s_CurrentActivity, new NotificationCallback());
576619
s_Jni = new JniApi(notificationManagerClass, notificationManager);
577620

621+
using (var version = new AndroidJavaClass("android/os/Build$VERSION"))
622+
s_DeviceApiLevel = version.GetStatic<int>("SDK_INT");
623+
s_TargetApiLevel = notificationManager.Call<int>("getTargetSdk");
624+
578625
s_Initialized = true;
579626
#endif
580627
return s_Initialized;
581628
}
582629

630+
static void SetPostPermissionStting(PermissionStatus status)
631+
{
632+
PlayerPrefs.SetInt(SETTING_POST_NOTIFICATIONS_PERMISSION, (int)status);
633+
}
634+
635+
/// <summary>
636+
/// Has user given permission to post notifications.
637+
/// Before Android 13 (API 33) no permission is required.
638+
/// </summary>
639+
public static PermissionStatus UserPermissionToPost
640+
{
641+
get
642+
{
643+
if (!Initialize())
644+
return PermissionStatus.Denied;
645+
if (s_DeviceApiLevel < API_POST_NOTIFICATIONS_PERMISSION_REQUIRED)
646+
return PermissionStatus.Allowed;
647+
648+
var permissionStatus = (PermissionStatus)PlayerPrefs.GetInt(SETTING_POST_NOTIFICATIONS_PERMISSION, (int)PermissionStatus.NotRequested);
649+
var allowed = Permission.HasUserAuthorizedPermission(PERMISSION_POST_NOTIFICATIONS);
650+
if (allowed)
651+
{
652+
if (permissionStatus != PermissionStatus.Allowed)
653+
SetPostPermissionStting(PermissionStatus.Allowed);
654+
return PermissionStatus.Allowed;
655+
}
656+
657+
switch (permissionStatus)
658+
{
659+
case PermissionStatus.NotRequested:
660+
break;
661+
case PermissionStatus.Allowed:
662+
permissionStatus = PermissionStatus.Denied;
663+
SetPostPermissionStting(permissionStatus);
664+
break;
665+
}
666+
667+
return permissionStatus;
668+
}
669+
}
670+
671+
/// <summary>
672+
/// Request user permission to post notifications.
673+
/// Before Android 13 (API 33) will allow immediately.
674+
/// May succeed or fail immediately. Users response is saved to PlayerPrefs.
675+
/// Respects users wish to not be asked again.
676+
/// </summary>
677+
/// <returns>PermissionStatus.RequestPending if user is prompted for permission or immediately known reply.</returns>
678+
/// <seealso cref="SETTING_POST_NOTIFICATIONS_PERMISSION"/>
679+
public static PermissionStatus RequestPermissionToPost()
680+
{
681+
var permissionStatus = UserPermissionToPost;
682+
if (permissionStatus == PermissionStatus.Allowed)
683+
return permissionStatus;
684+
if (permissionStatus == PermissionStatus.DeniedDontAskAgain)
685+
return permissionStatus;
686+
// Can only request permission if applications target SDK is 33, not actual device SDK
687+
if (s_TargetApiLevel < API_POST_NOTIFICATIONS_PERMISSION_REQUIRED)
688+
{
689+
SetPostPermissionStting(PermissionStatus.DeniedDontAskAgain);
690+
return PermissionStatus.DeniedDontAskAgain;
691+
}
692+
693+
var callbacks = new PermissionCallbacks();
694+
callbacks.PermissionGranted += (unused) => SetPostPermissionStting(PermissionStatus.Allowed);
695+
callbacks.PermissionDenied += (unused) => SetPostPermissionStting(PermissionStatus.Denied);
696+
callbacks.PermissionDeniedAndDontAskAgain += (unused) => SetPostPermissionStting(PermissionStatus.DeniedDontAskAgain);
697+
Permission.RequestUserPermission(PERMISSION_POST_NOTIFICATIONS, callbacks);
698+
return PermissionStatus.RequestPending;
699+
}
700+
583701
/// <summary>
584702
/// Creates a notification channel that notifications can be posted to.
585703
/// Notification channel settings can be changed by users on devices running Android 8.0 and above.

com.unity.mobile.notifications/Runtime/Android/Plugins/com/unity/androidnotifications/UnityNotificationManager.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ private void initialize(Activity activity, NotificationCallback notificationCall
7777
mNotificationCallback = notificationCallback;
7878
if (mScheduledNotifications == null)
7979
mScheduledNotifications = new ConcurrentHashMap();
80-
if (mBackgroundThread == null)
80+
if (mBackgroundThread == null || !mBackgroundThread.isAlive())
8181
mBackgroundThread = new UnityNotificationBackgroundThread(this, mScheduledNotifications);
8282
if (mRandom == null)
8383
mRandom = new Random();
@@ -108,7 +108,8 @@ private void initialize(Activity activity, NotificationCallback notificationCall
108108
Log.e(TAG_UNITY, "Failed to load meta-data, NullPointer: " + e.getMessage());
109109
}
110110

111-
mBackgroundThread.start();
111+
if (!mBackgroundThread.isAlive())
112+
mBackgroundThread.start();
112113
}
113114

114115
static synchronized UnityNotificationManager getNotificationManagerImpl(Context context) {
@@ -137,6 +138,10 @@ public NotificationManager getNotificationManager() {
137138
return (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
138139
}
139140

141+
public int getTargetSdk() {
142+
return mContext.getApplicationInfo().targetSdkVersion;
143+
}
144+
140145
public void registerNotificationChannel(
141146
String id,
142147
String name,

0 commit comments

Comments
 (0)