Skip to content

Commit

Permalink
Merge pull request #17 from Innim/feature/2248.analytics-for-notify
Browse files Browse the repository at this point in the history
Feature/2248.analytics for notify
  • Loading branch information
greymag authored Jun 27, 2024
2 parents 53fdfa1 + 64c1cda commit 529a66f
Show file tree
Hide file tree
Showing 11 changed files with 187 additions and 13 deletions.
9 changes: 9 additions & 0 deletions flutter_local_notifications/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# [17.0.3]

* [Android] Added `shownNotificationsInfo` param to `NotificationDetails`. If you pass this param
it will save in local store if notification show.
* You can load this stored information by `FlutterLocalNotificationsPlugin.getShownNotificationsInfo()`
method and clear stored info by `FlutterLocalNotificationsPlugin.cleanShownNotificationsInfo()` method.

* [Android] Fixed: `inexactWindowLengthMillis` always null in `NotificationDetails`.

# [17.0.2]

* [Android] Remove old corrupted notifications.
Expand Down
4 changes: 4 additions & 0 deletions flutter_local_notifications/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ This is fork of [flutter_local_notifications](https://github.com/MaikuB/flutter_
* Ability to set your own custom layout for notifications.
* More detailed exceptions in `ScheduledNotificationReceiver.onReceive()`.
* Ability to set notification window for inexact alarm. See `AndroidNotificationDetails.inexactWindowLengthMillis`
* Ability to store info about shown notifications. See `AndroidNotificationDetails.shownNotificationsInfo`. If you pass this param
it will save in local store if notification show.
* You can load this stored information by `FlutterLocalNotificationsPlugin.getShownNotificationsInfo()`
method and clear stored info by `FlutterLocalNotificationsPlugin.cleanShownNotificationsInfo()` method.

### iOS

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ public class FlutterLocalNotificationsPlugin
private static final String GET_NOTIFICATION_CHANNELS_METHOD = "getNotificationChannels";
private static final String START_FOREGROUND_SERVICE = "startForegroundService";
private static final String STOP_FOREGROUND_SERVICE = "stopForegroundService";
private static final String GET_SHOWN_NOTIFICATIONS_INFO = "getShownNotificationsInfo";
private static final String CLEAR_SHOWN_NOTIFICATIONS_INFO = "clearShownNotificationsInfo";
private static final String PENDING_NOTIFICATION_REQUESTS_METHOD = "pendingNotificationRequests";
private static final String GET_ACTIVE_NOTIFICATIONS_METHOD = "getActiveNotifications";
private static final String SHOW_METHOD = "show";
Expand Down Expand Up @@ -1645,12 +1647,32 @@ public void fail(String message) {
case STOP_FOREGROUND_SERVICE:
stopForegroundService(result);
break;
case GET_SHOWN_NOTIFICATIONS_INFO:
getShownNotificationsInfo(result);
break;
case CLEAR_SHOWN_NOTIFICATIONS_INFO:
clearShownNotificationsInfo(result);
break;
default:
result.notImplemented();
break;
}
}

private void getShownNotificationsInfo(Result result) {
final ShownNotificationsPreferences prefs =
new ShownNotificationsPreferences(applicationContext);
final ArrayList<String> res = prefs.getShownNotificationsInfo();
result.success(res);
}

private void clearShownNotificationsInfo(Result result) {
final ShownNotificationsPreferences prefs =
new ShownNotificationsPreferences(applicationContext);
prefs.clearShownNotificationsInfo();
result.success(true);
}

private void pendingNotificationRequests(Result result) {
ArrayList<NotificationDetails> scheduledNotifications =
loadScheduledNotifications(applicationContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@
/** Created by michaelbui on 24/3/18. */
@Keep
public class ScheduledNotificationReceiver extends BroadcastReceiver {

private static final String TAG = "ScheduledNotifReceiver";

@Override
@SuppressWarnings("deprecation")
public void onReceive(final Context context, Intent intent) {

String notificationDetailsJson =
intent.getStringExtra(FlutterLocalNotificationsPlugin.NOTIFICATION_DETAILS);
if (StringUtils.isNullOrEmpty(notificationDetailsJson)) {
Expand Down Expand Up @@ -93,6 +93,13 @@ public void onReceive(final Context context, Intent intent) {
return;
}

final String info = notificationDetails.shownNotificationsInfo;
if (!StringUtils.isNullOrEmpty(info)) {
final ShownNotificationsPreferences preferences =
new ShownNotificationsPreferences(context);
preferences.saveShownNotificationInfo(info);
}

try {
FlutterLocalNotificationsPlugin.scheduleNextNotification(context, notificationDetails);
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.dexterous.flutterlocalnotifications;

import android.content.Context;
import android.content.SharedPreferences;

import java.util.ArrayList;
import java.util.Arrays;

public class ShownNotificationsPreferences {
private static final String SHARED_PREFS_FILE_NAME =
"flutter_local_notifications_plugin_shown_info";
private final String SHOWN_NOTIFICATIONS_INFO_KEY =
"com.dexterous.flutterlocalnotifications.SHOWN_NOTIFICATIONS_INFO_KEY";
private final String SHOWN_NOTIFICATIONS_INFO_DIVIDER = "/";

private final Context context;

public ShownNotificationsPreferences(Context context) {

this.context = context;
}

public void saveShownNotificationInfo(String info) {
final SharedPreferences pref = get();
final SharedPreferences.Editor editor = pref.edit();
String currentInfo = pref.getString(SHOWN_NOTIFICATIONS_INFO_KEY, "");
if (!currentInfo.isEmpty()) {
currentInfo = currentInfo + SHOWN_NOTIFICATIONS_INFO_DIVIDER + info;
} else {
currentInfo = info;
}
editor.putString(SHOWN_NOTIFICATIONS_INFO_KEY, currentInfo);
editor.apply();
}

public ArrayList<String> getShownNotificationsInfo() {
final SharedPreferences pref = get();
final String currentInfo = pref.getString(SHOWN_NOTIFICATIONS_INFO_KEY, "");
if (currentInfo.isEmpty()) {
return new ArrayList<>();
}
final String[] list = currentInfo.split(SHOWN_NOTIFICATIONS_INFO_DIVIDER);
return new ArrayList<>(Arrays.asList(list));
}

public void clearShownNotificationsInfo() {
final SharedPreferences pref = get();
final SharedPreferences.Editor editor = pref.edit();
editor.remove(SHOWN_NOTIFICATIONS_INFO_KEY);
editor.apply();
}

private SharedPreferences get() {
return context.getSharedPreferences(SHARED_PREFS_FILE_NAME, Context.MODE_PRIVATE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ public class NotificationDetails implements Serializable {
private static final String CUSTOM_LAYOUT_COLLAPSED_NAME = "customLayoutCollapsedName";
private static final String CUSTOM_LAYOUT_EXPANDED_NAME = "customLayoutExpandedName";
private static final String INEXACT_WINDOW_LENGTH_MILLIS = "inexactWindowLengthMillis";
private static final String SHOWN_NOTIFICATION_INFO = "shownNotificationsInfo";

public Integer id;
public String title;
Expand Down Expand Up @@ -208,6 +209,8 @@ public class NotificationDetails implements Serializable {
public Integer iconResourceId;
public Long inexactWindowLengthMillis;

public String shownNotificationsInfo;

public static NotificationDetails from(Map<String, Object> arguments) {
NotificationDetails notificationDetails = new NotificationDetails();
notificationDetails.payload = (String) arguments.get(PAYLOAD);
Expand Down Expand Up @@ -244,13 +247,6 @@ public static NotificationDetails from(Map<String, Object> arguments) {
notificationDetails.day = (Integer) arguments.get(DAY);
}

if (arguments.containsKey(INEXACT_WINDOW_LENGTH_MILLIS)) {
notificationDetails.inexactWindowLengthMillis =
(Long) arguments.get(INEXACT_WINDOW_LENGTH_MILLIS);
} else {
notificationDetails.inexactWindowLengthMillis = 0L;
}

readPlatformSpecifics(arguments, notificationDetails);
return notificationDetails;
}
Expand Down Expand Up @@ -325,6 +321,20 @@ private static void readPlatformSpecifics(
}
}
}

if (platformChannelSpecifics.containsKey(INEXACT_WINDOW_LENGTH_MILLIS)) {
notificationDetails.inexactWindowLengthMillis =
(Long) platformChannelSpecifics.get(INEXACT_WINDOW_LENGTH_MILLIS);
} else {
notificationDetails.inexactWindowLengthMillis = 0L;
}

if (platformChannelSpecifics.containsKey(SHOWN_NOTIFICATION_INFO)) {
notificationDetails.shownNotificationsInfo =
(String) platformChannelSpecifics.get(SHOWN_NOTIFICATION_INFO);
} else {
notificationDetails.shownNotificationsInfo = "";
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,42 @@ class FlutterLocalNotificationsPlugin {
}
}

/// Returns info that stored when notifications was shown.
/// See [AndroidNotificationDetails.shownNotificationsInfo]
Future<List<Map<String, dynamic>>> getShownNotificationsInfo() async {
if (defaultTargetPlatform != TargetPlatform.android) {
assert(
false,
'The method getShownNotificationsInfo available only for android.',
);
return const <Map<String, dynamic>>[];
}

final List<Map<String, dynamic>> res =
(await resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.getShownNotificationsInfo()) ??
const <Map<String, dynamic>>[];
return res;
}

/// Clear all stored info obout shown notifications.
Future<bool> clearShownNotificationsInfo() async {
if (defaultTargetPlatform != TargetPlatform.android) {
assert(
false,
'The method clearShownNotificationsInfo available only for android.',
);
return false;
}

final bool res = (await resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.clearShownNotificationsInfo()) ??
false;
return res;
}

/// Cancel/remove the notification with the specified id.
///
/// This applies to notifications that have been scheduled and those that
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:convert';
import 'dart:ui';

import 'package:clock/clock.dart';
Expand Down Expand Up @@ -107,7 +108,7 @@ class MethodChannelFlutterLocalNotificationsPlugin
/// Android implementation of the local notifications plugin.
class AndroidFlutterLocalNotificationsPlugin
extends MethodChannelFlutterLocalNotificationsPlugin {
DidReceiveNotificationResponseCallback? _ondidReceiveNotificationResponse;
DidReceiveNotificationResponseCallback? _onDidReceiveNotificationResponse;

/// Initializes the plugin.
///
Expand All @@ -131,7 +132,7 @@ class AndroidFlutterLocalNotificationsPlugin
DidReceiveBackgroundNotificationResponseCallback?
onDidReceiveBackgroundNotificationResponse,
}) async {
_ondidReceiveNotificationResponse = onDidReceiveNotificationResponse;
_onDidReceiveNotificationResponse = onDidReceiveNotificationResponse;
_channel.setMethodCallHandler(_handleMethod);

final Map<String, Object> arguments = initializationSettings.toMap();
Expand Down Expand Up @@ -513,6 +514,27 @@ class AndroidFlutterLocalNotificationsPlugin
Future<bool?> canScheduleExactNotifications() async =>
await _channel.invokeMethod<bool>('canScheduleExactNotifications');

/// Returns info that stored when notifications was shown.
/// See [AndroidNotificationDetails.shownNotificationsInfo]
Future<List<Map<String, dynamic>>> getShownNotificationsInfo() async {
final List<Object?>? res =
await _channel.invokeMethod<List<Object?>>('getShownNotificationsInfo');
if (res == null || res.isEmpty) {
return <Map<String, dynamic>>[];
}
return res
.map((Object? e) => jsonDecode(e as String) as Map<String, dynamic>)
.toList();
}

/// Clear all stored info obout shown notifications.
Future<bool> clearShownNotificationsInfo() async {
final bool? res =
await _channel.invokeMethod<bool?>('clearShownNotificationsInfo');

return res ?? false;
}

AndroidNotificationSound? _getNotificationChannelSound(
Map<dynamic, dynamic> channelMap) {
final int? soundSourceIndex = channelMap['soundSource'];
Expand All @@ -531,7 +553,7 @@ class AndroidFlutterLocalNotificationsPlugin
Future<void> _handleMethod(MethodCall call) async {
switch (call.method) {
case 'didReceiveNotificationResponse':
_ondidReceiveNotificationResponse?.call(
_onDidReceiveNotificationResponse?.call(
NotificationResponse(
id: call.arguments['notificationId'],
actionId: call.arguments['actionId'],
Expand Down Expand Up @@ -637,7 +659,7 @@ class IOSFlutterLocalNotificationsPlugin
);
},
);

/// Sets badge number.
Future<void> setBadgeNumber(int value) =>
_channel.invokeMethod<bool>('setBadgeNumber', <String, int>{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ extension AndroidNotificationDetailsMapper on AndroidNotificationDetails {
'colorized': colorized,
'number': number,
'audioAttributesUsage': audioAttributesUsage.value,
'inexactWindowLengthMillis': inexactWindowLengthMillis,
'shownNotificationsInfo': shownNotificationsInfo,
}
..addAll(_convertActionsToMap(actions))
..addAll(_convertStyleInformationToMap())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ class AndroidNotificationDetails {
this.customLayoutCollapsedName,
this.customLayoutExpandedName,
this.inexactWindowLengthMillis,
this.shownNotificationsInfo,
}) : customLayoutLegacyName = customLayoutLegacyName ?? customLayoutName;

/// The icon that should be used when displaying the notification.
Expand Down Expand Up @@ -458,4 +459,9 @@ class AndroidNotificationDetails {
/// zero, inexact alarm will plan in this length, should be 10 minutes
/// or more, see more in docs https://developer.android.com/about/versions/14/changes/schedule-exact-alarms#use-cases
final int? inexactWindowLengthMillis;

/// Some info that will save in local store if notification show, to get
/// it from store use
/// [AndroidFlutterLocalNotificationsPlugin.getShownNotificationsInfo()].
final String? shownNotificationsInfo;
}
2 changes: 1 addition & 1 deletion flutter_local_notifications/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: flutter_local_notifications_plus
description: A cross platform plugin for displaying and scheduling local
notifications for Flutter applications with the ability to customise for each
platform.
version: 17.0.2
version: 17.0.3
homepage: https://github.com/Innim/flutter_local_notifications
repository: https://github.com/Innim/flutter_local_notifications
issue_tracker: https://github.com/Innim/flutter_local_notifications/issues
Expand Down

0 comments on commit 529a66f

Please sign in to comment.