New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Push Notification - iOS & Android Updates! (Now includes FCM - Fuse 1.10+) #1220

Open
wants to merge 8 commits into
base: master
from
@@ -14,7 +14,7 @@ namespace Fuse.Maps.Android
MOVE = 2
}

[Require("Gradle.Dependency.Implementation", "com.google.android.gms:play-services-maps:12.0.1")]
[Require("Gradle.Dependency.Implementation", "com.google.android.gms:play-services-maps:16.0.0")]
extern (Android) public class MapView : Fuse.Controls.Native.Android.LeafView, IMapView
{
public bool IsReady { get; private set; }
@@ -1,25 +1,22 @@
<Extensions Backend="CPlusPlus" Condition="Android">
<Require AndroidManifest.Permission="com.google.android.c2dm.permission.RECEIVE" />

<ProcessFile Name="PushNotificationReceiver.java" TargetName="@(Java.SourceDirectory)/com/fuse/PushNotifications/PushNotificationReceiver.java" />
<ProcessFile Name="PushNotificationIDService.java" TargetName="@(Java.SourceDirectory)/com/fuse/PushNotifications/PushNotificationIDService.java" />
<ProcessFile Name="BigPictureStyleHttp.java" TargetName="@(Java.SourceDirectory)/com/fuse/PushNotifications/BigPictureStyleHttp.java" />
<ProcessFile Name="BundleFiles.java" TargetName="@(Java.SourceDirectory)/com/fuse/PushNotifications/BundleFiles.java" />

<Require AndroidManifest.ApplicationElement><![CDATA[
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
<receiver android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >

<service android:name="com.fuse.PushNotifications.PushNotificationReceiver">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="@(Activity.Package)" />
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</receiver>

<service
android:name="com.fuse.PushNotifications.PushNotificationReceiver"
android:exported="false" >
</service>

<service android:name="com.fuse.PushNotifications.PushNotificationIDService">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
]]></Require>

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -0,0 +1,14 @@
package com.fuse.PushNotifications;

import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;

public class PushNotificationIDService extends FirebaseInstanceIdService
{
@Override
public void onTokenRefresh()
{
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
com.foreign.Fuse.PushNotifications.AndroidImpl.RegistrationIDUpdated(refreshedToken);
}
}
@@ -2,21 +2,32 @@

import android.os.Bundle;
import java.util.ArrayList;
import com.google.android.gms.gcm.GcmListenerService;
import java.util.Map;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class PushNotificationReceiver extends GcmListenerService {
public class PushNotificationReceiver extends FirebaseMessagingService {
public static ArrayList<Bundle> _cachedBundles = new ArrayList<Bundle>();
public static boolean InForeground = false;
public static String ACTION = "fuseBackgroundNotify";
static int _notificationID = -1;
public static int nextID() { return _notificationID += 1; }
private static Object lock = new Object();


public PushNotificationReceiver() {
super();
}

@Override
public void onMessageReceived(String from, Bundle bundle)
public void onMessageReceived(RemoteMessage message)
{
synchronized (lock) {
com.foreign.Fuse.PushNotifications.AndroidImpl.OnNotificationRecieved(this, from, bundle);
Bundle bundle = new Bundle();
for (Map.Entry<String, String> entry : message.getData().entrySet()) {
bundle.putString(entry.getKey(), entry.getValue());
}
com.foreign.Fuse.PushNotifications.AndroidImpl.OnNotificationRecieved(this, message.getFrom(), bundle);
}
}

}
@@ -9,6 +9,18 @@ using Uno.Threading;

namespace Fuse.PushNotifications
{

[ForeignInclude(Language.Java,
"android.util.Log",
"com.google.firebase.iid.FirebaseInstanceId",
"java.util.ArrayList",
"java.util.List",
"android.graphics.Color"
)]
[Require("Gradle.Dependency.ClassPath", "com.google.gms:google-services:4.2.0")]
[Require("Gradle.AllProjects.Repository", "maven {url 'https://maven.google.com'}")]
[Require("Gradle.Dependency.Implementation", "com.google.firebase:firebase-core:16.0.0")]
[Require("Gradle.BuildFile.End", "apply plugin: 'com.google.gms.google-services'")]
public static class PushNotify
{
extern(Android)
@@ -150,5 +162,13 @@ namespace Fuse.PushNotifications
}

public extern(!iOS) static void Register() { }

public extern(iOS) static bool IsRegisteredForRemoteNotifications()
{
return iOSImpl.IsRegisteredForRemoteNotifications();
}

public extern(Android) static bool IsRegisteredForRemoteNotifications() { return true; }
public extern(!iOS && !Android) static bool IsRegisteredForRemoteNotifications() { return true; }
}
}
@@ -28,8 +28,18 @@ If you haven't already registered an Android app, follow these steps:
"Package": "com.mycompany.myapp",
}

- After adding the Android app, you will be prompted to download a `google-services.json` file.
This can be ignored, as it's not needed for push notifications and can always be downloaded later if needed.
- After adding the Android app, you will be prompted to download a `google-services.json` file. Download and copy it to the root of your project.
- Add the following file to tell fuse to copy google-services.json to your android app folder:

Android.uxl

```
<Extensions Backend="CPlusPlus" Condition="Android">
<CopyFile Condition="Android" Name="google-services.json" TargetName="app/google-services.json" />
</Extensions>
```



### Sending notifications

@@ -136,3 +136,232 @@ Google and Apple has different limits on the size of push notifications.
- Google limits to 4096 bytes
- Apple limits to 2048 bytes on iOS 8 and up but only 256 bytes on all earlier versions




## Additional Android Push Notification Features

Since Android 8+ (Oreo or API 26), it is mandatory to define and assign a channel to every notification.

We have defined a default channel (named "App") to be assigned to notifications if they aren't already assigned a channel, so you don't need to define one but if you do want to customise it, read on.

NB! Once a channel is created, you CANNOT change its properties later.

Apart from the Notification Channel feature discussed above, here is a list of the other android features implemented thus far:

- Notification Sound
- Notification Color
- Notification Priority
- Notification Category
- Notification Lockscreen Visibility

Android 8+
- Notification Channel
- Nofitication Channel Group
- Notification Channel Importance
- Notification Channel Lockscreen Visibility
- Notification Channel Light Color
- Notification Channel Sound
- Notification Channel Vibration
- Notification Channel Show Badge
- Notification Badge Number
- Notification Badge Icon Type


We'll show you how to implement them here in fuse but read more about each feature [here](https://developer.android.com/guide/topics/ui/notifiers/notifications).


#### Notification Sound - Value - default

'notification': {
alert: {
'title': 'Well would ya look at that!',
'body': 'Hello from the server',
'sound': 'default'
}
},


#### Notification Color - Values - #RRGGBB | #AARRGGBB

'notification': {
alert: {
'title': 'Well would ya look at that!',
'body': 'Hello from the server',
'color': '#8811FF'
}
},


#### Notification Priority - Values - high | low | max | min

'notification': {
alert: {
'title': 'Well would ya look at that!',
'body': 'Hello from the server',
'notificationPriority': 'high'
}
},


#### Notification Category - Values - alarm | reminder | event | call | message | email | promo | recommendation | social | error | progress | service | status | system | transport

'notification': {
alert: {
'title': 'Well would ya look at that!',
'body': 'Hello from the server',
'notificationCategory': 'social'
}
},


#### Notification Lockscreen Visibility - Values - public | secret | private

'notification': {
alert: {
'title': 'Well would ya look at that!',
'body': 'Hello from the server',
'notificationLockscreenVisibility': 'secret'
}
},



#### Notification Channel

Notification Channel and a Notification Channel Group:

'notification': {
alert: {
'title': 'Well would ya look at that!',
'body': 'Hello from the server',
'notificationChannelGroupId': 'sports',
'notificationChannelGroupName': 'Sports',
'notificationChannelId': 'sports_football_highlights',
'notificationChannelName': 'Football Highlights',
'notificationChannelDescription': 'Video commentary once a week'
}
},

Notification Channel Importance - Values - urgent | high | medium | low | none

'notification': {
alert: {
'title': 'Well would ya look at that!',
'body': 'Hello from the server',
'notificationChannelGroupId': 'sports',
'notificationChannelGroupName': 'Sports',
'notificationChannelId': 'sports_basketball_highlights',
'notificationChannelName': 'Basketball Highlights',
'notificationChannelDescription': 'Video commentary once a week',
'notificationChannelImportance': 'urgent',

}
},


Notification Channel Lockscreen Visibility - Values - public | secret | private

'notification': {
alert: {
'title': 'Well would ya look at that!',
'body': 'Hello from the server',
'notificationChannelLockscreenVisibility': 'private'
}
},


Notification Channel Light Color - Values - #RRGGBB

'notification': {
alert: {
'title': 'Well would ya look at that!',
'body': 'Hello from the server',
'notificationChannelLightColor': '#1188FF'
}
},


Notification Channel Sound - Values - true | false

'notification': {
alert: {
'title': 'Well would ya look at that!',
'body': 'Hello from the server',
'notificationChannelIsSoundOn': 'true'
}
},


Notification Channel Vibration - Values - true | false

'notification': {
alert: {
'title': 'Well would ya look at that!',
'body': 'Hello from the server',
'notificationChannelIsVibrationOn': 'true'
}
},


Notification Channel Show Badge - Values - true | false

'notification': {
alert: {
'title': 'Well would ya look at that!',
'body': 'Hello from the server',
'notificationChannelIsShowBadgeOn': 'true'
}
},


#### Notification Badge

Notification Channel Badge Number

'notification': {
alert: {
'title': 'Well would ya look at that!',
'body': 'Hello from the server',
'notificationBadgeNumber': '23'
}
},


Notification Channel Badge Icon Type - Values - none | small | large

'notification': {
alert: {
'title': 'Well would ya look at that!',
'body': 'Hello from the server',
'notificationBadgeIconType': 'small'
}
},



#### Notification Uno Project Configurations

The following notification settings can be set via the `.unoproj` settings:

"Android": {
...
"Notification": {
"DefaultChannelGroupId": "default_group",
"DefaultChannelGroupName": "Categories",
"DefaultChannelId": "default_channel",
"DefaultChannelName": "App",
"DefaultChannelDescription": "",
"DefaultChannelImportance": "high",
"DefaultChannelLightColor": "#FF2C37",
"NotificationChannelLockscreenVisibility": "secret",
"NotificationChannelIsSoundOn": true,
"NotificationChannelIsShowBadgeOn": true,
"NotificationChannelIsVibrationOn": true
}
...
},


Note: notification payload settings will always override the notification settings from `.unoproj`.
NB! Once a channel is created, you CANNOT change its properties later.
@@ -29,6 +29,7 @@

"Android/Impl.uno:Source",
"Android/Impl.cpp.uxl:Extensions",
"Android/PushNotificationIDService.java:File",
"Android/PushNotificationReceiver.java:File",
"Android/BigPictureStyleHttp.java:File",
"Android/BundleFiles.java:File",
Oops, something went wrong.
ProTip! Use n and p to navigate between commits in a pull request.