I was looking for a way to enable multi line notifications for Firemonkey in Delphi 10 Seattle on Android and this is the solution I came up with. If you search for Android multiline notifications there are lots of solutions out there which are all in Java. The trick is to convert the Java into Object Pascal using the Delphi Android JNI. Two examples of how to add multiline notifications to Android in Java are here and here. I referenced these examples to create the solution. First I will describe how I came up with the solution so that you can follow this method when using the Android JNI to add other functionality and then I will list the full step by step guide at the end so you can skip the long explanation if you want. This code affects local notifications only as push notifications are defined elsewhere. You should be able to use this code with Appmethod and it can be adapted to C++Builder as well. Obviously it does not apply to IOS, OSX, or Windows.
Hacking The Android JNI
The solution involves creating a BigTextStyle and calling .setStyle() to apply it to the NotificationBuilder object. The code where NotificationBuilder is located is in System.Android.Notification.pas (or FMX.Notification.Android.pas under earlier versions of Delphi). You will need to copy this RTL unit to your project folder. I found the location by searching the RTL itself for ‘notificationManager’ with a Find In Files search using Textpad (my text editor of choice). Any fragment of the Java (or Object Pascal) code you are looking for can be used to search for the Android JNI interface equivalent in the RTL. The BigTextStyle interface object itself is not in the RTL so it will need to be added. It should be added into Androidapi.JNI.Support.pas so you will need to also copy this file into your project folder as well. I found the JNotificationCompat_Style definition by searching the RTL for ‘setStyle(‘. You can find the interface definition for BigTextStyle here on Github. All of the Object Pascal interface files for Android version 7 through 23 are also available from that Github repository as well. They were created with Java2Pas.
Creating The NotificationCompat.BigTextStyle Interface
In the interface definition there are three things I figured out through trial and error which I had to change. First the Java class which is defined as android/app/Notification_BigTextStyle actually needs to be defined as android/support/v4/app/NotificationCompat$BigTextStyle. I figured this out by looking at how the parent class was defined which is android/support/v4/app/NotificationCompat$Style. You can see the BigTextStyle class hierarchy here in the Android docs. Second, through trial and error I also figured out that I needed to change the JObject and JObjectClass interface definitions so that they became JNotificationCompat_Style and JNotificationCompat_StyleClass. This was required because .setStyle() needs a JNotificationCompat_Style parameter and it would not originally accept JNotification_BigTextStyle. And third I had to define the new JNotificationCompat_BigTextStyleClass interfaces below the JNotificationCompat_Style interface. I found it easier to merge the contents of android.app.Notification_BigTextStyle.pas into Androidapi.JNI.Support.pas. I just added the different sections of the JNotificationCompat_BigTextStyle interface after each comparable section of the JNotificationCompat_Style interface (which remember is the parent type).
Lastly I noticed that there was a section in Androidapi.JNI.Support.pas which looks like this TRegTypes.RegisterType(‘Androidapi.JNI.Support.JNotificationCompat_Style’, TypeInfo(Androidapi.JNI.Support.JNotificationCompat_Style)); so I added a similar line like this for the new BigTextStyle type TRegTypes.RegisterType(‘Androidapi.JNI.Support.JNotificationCompat_BigTextStyle’, TypeInfo(Androidapi.JNI.Support.JNotificationCompat_BigTextStyle));.
Adding setStyle() To System.Android.Notification
Once you have the BigTextStyle class defined the rest of the code is pretty straightforward. In System.Android.Notification.pas there is the CreateNativeNotification() function which is where JNotificationCompat_Builder is used. Referencing back to the original solution you will see how the Java code and the Object Pascal code are similar. For example, you will see calls to setContentTitle in both sets of code. I chose the setSmallIcon line to add the new code after but I’m not sure that it matters where you add in the new setStyle call. I looked at this line NotificationBuilder := TJNotificationCompat_Builder.JavaClass.init(TAndroidHelper.Context); for guidance on how to create a new BigTextStyle object. A NotificationBuilder: JNotificationCompat_Builder; was defined in the var section so I added an equivalent BigTextStyle: JNotificationCompat_BigTextStyle; to the var section. I attempted BigTextStyle := TJNotificationCompat_BigTextStyle.JavaClass.init(NotificationBuilder); but that just ended up crashing the app. Through trial and error I ended up with BigTextStyle := TJNotificationCompat_BigTextStyle.JavaClass.init();
Referencing the Java and the Object Pascal code I could see that the message needed to be passed in to the bigText function and the message in Object Pascal was retrievable via GetContentText so I ended up with BigTextStyle.bigText(GetContentText); Finally I needed to apply the new BigTextStyle object to the NotificationBuilder which I did with NotificationBuilder := NotificationBuilder.setStyle(BigTextStyle); I mentioned about how setStyle would not originally take BigTextStyle because it was of the wrong type. So I actually ran into the wrong type issue at this point and this is when I went back into the BigTextStyle interface in Androidapi.JNI.Support.pas and upgraded it to subclass off of the original Style object.
Android MultiLine Notification Step By Step Guide
Step #1: Follow the instructions in the Delphi DocWiki to create a notification project. Here is that code snippet:
procedure TForm1.RepeatedNotificationClick(Sender: TObject);
var
MyNotification: TNotification;
begin
MyNotification := NotificationCenter1.CreateNotification;
try
MyNotification.Title := 'MyNotification';
MyNotification.AlertBody := 'Repeating notification each minute! But reaaaaallly reeeaaalllly long with lots of data here to make sure it shows up multiline.';
//Fired in 10 seconds
MyNotification.FireDate := Now + EncodeTime(0, 0, 10, 0);
//Repeated each minute
MyNotification.RepeatInterval := TRepeatInterval.Minute;
// Send notification to the notification center
NotificationCenter1.ScheduleNotification(MyNotification);
finally
MyNotification.Free;
end;
end;
Step #2:Â Copy Androidapi.JNI.Support.pas and System.Android.Notification.pas (or FMX.Notification.Android.pas) to your project directory.
Step #3:Â Edit Androidapi.JNI.Support.pas.
Step #4:Â After this line:
JNotificationCompat_Style = interface;//android.support.v4.app.NotificationCompat$Style
Add:
JNotificationCompat_BigTextStyle = interface;
Step #5:
After this line:
TJNotificationCompat_Style = class(TJavaGenericImport<JNotificationCompat_StyleClass, JNotificationCompat_Style>) end;
Add:
JNotificationCompat_BigTextStyleClass = interface(JNotificationCompat_StyleClass)
['{0E443407-40E9-4985-9F1D-6D0CF1C5F652}']
function bigText(cs : JCharSequence) : JNotificationCompat_BigTextStyle; cdecl; // (Ljava/lang/CharSequence;)Landroid/app/Notification$BigTextStyle; A: $1
function init : JNotificationCompat_BigTextStyle; cdecl; overload; // ()V A: $1
function init(builder : JNotificationCompat_Builder) : JNotificationCompat_BigTextStyle; cdecl; overload;// (Landroid/app/Notification$Builder;)V A: $1
function setBigContentTitle(title : JCharSequence) : JNotificationCompat_BigTextStyle; cdecl;// (Ljava/lang/CharSequence;)Landroid/app/Notification$BigTextStyle; A: $1
function setSummaryText(cs : JCharSequence) : JNotificationCompat_BigTextStyle; cdecl;// (Ljava/lang/CharSequence;)Landroid/app/Notification$BigTextStyle; A: $1
end;
//
[JavaSignature('android/support/v4/app/NotificationCompat$BigTextStyle')]
JNotificationCompat_BigTextStyle = interface(JNotificationCompat_Style)
['{3AFC570E-365A-4261-9954-ADE1BEC12986}']
function bigText(cs : JCharSequence) : JNotificationCompat_BigTextStyle; cdecl; // (Ljava/lang/CharSequence;)Landroid/app/Notification$BigTextStyle; A: $1
function setBigContentTitle(title : JCharSequence) : JNotificationCompat_BigTextStyle; cdecl;// (Ljava/lang/CharSequence;)Landroid/app/Notification$BigTextStyle; A: $1
function setSummaryText(cs : JCharSequence) : JNotificationCompat_BigTextStyle; cdecl;// (Ljava/lang/CharSequence;)Landroid/app/Notification$BigTextStyle; A: $1
end;
//
TJNotificationCompat_BigTextStyle = class(TJavaGenericImport<JNotificationCompat_BigTextStyleClass, JNotificationCompat_BigTextStyle>)
end;
Step #6:
After:
TRegTypes.RegisterType('Androidapi.JNI.Support.JNotificationCompat_Style', TypeInfo(Androidapi.JNI.Support.JNotificationCompat_Style));
Add:
TRegTypes.RegisterType('Androidapi.JNI.Support.JNotificationCompat_BigTextStyle', TypeInfo(Androidapi.JNI.Support.JNotificationCompat_BigTextStyle));
Step #7:Â Edit System.Android.Notification.pas (or FMX.Notification.Android.pas).
Step #8:
In this function:
function TNotificationCenterAndroid.CreateNativeNotification(const ANotification: TNotification): JNotification;
Add:
var
BigTextStyle: JNotificationCompat_BigTextStyle;
Step #9:
After:
NotificationBuilder := NotificationBuilder.setSmallIcon(GetDefaultIconID);
Add:
BigTextStyle := TJNotificationCompat_BigTextStyle.JavaClass.init();
BigTextStyle.bigText(GetContentText);
NotificationBuilder := NotificationBuilder.setStyle(BigTextStyle);
Step #10:Â Deploy your project to Android and test!
Lastly, there are actually four different styles that subclass off of NotificationCompat.Style. They are NotificationCompat.BigPictureStyle, NotificationCompat.BigTextStyle, NotificationCompat.InboxStyle, and NotificationCompat.MediaStyle. You can implement the other three custom styles yourself and use the full range of custom notifications with photos and more.
Check out the full Android documentation for NotificationCompat.Style and it’s sub classes.
Hi,
I made this project in Delphi 10 Seattle and i made the changes for a BigTextStyle in both pas-files.
But how do i apply that in my project
I can´t find a NotificationBuilder for Delphi
Maybe you have an example for me.
Thanks in advance
Kor Blaauw
procedure TForm1.RepeatedNotificationClick(Sender: TObject);
var
MyNotification: TNotification;
begin
MyNotification := NotificationCenter1.CreateNotification;
try
MyNotification.Title := ‘MyNotification’;
MyNotification.AlertBody := ‘Repeating notification each minute! But reaaaaallly reeeaaalllly long with lots of data here to make sure it shows up multiline.’;
//Fired in 10 seconds
MyNotification.FireDate := Now + EncodeTime(0, 0, 10, 0);
//Repeated each minute
MyNotification.RepeatInterval := TRepeatInterval.Minute;
// Send notification to the notification center
NotificationCenter1.ScheduleNotification(MyNotification);
finally
MyNotification.Free;
end;
end;
You have to copy the said files from the c:\program files (x86)\embarcadero source code directory to the directory of your project.
Yes
That was step 2 but after step 10 there is no way to set the bigtext at MyNotification
I think it has to be done by the NotificationBuilder
But that was not the example from step 1
That is a complete other way to create a notification
Pls tell me if i’m wrong
Does you System.Android.Notification.pas (or FMX.Notification.Android.pas) contain NotificationBuilder? What version of Delphi?
The problem is that the code calls for ScheduleNotification at the end, but you would need PresentNotification, because that’s the part that call for CreateNativeNotification, which was changed.
After that it works lie a charm.
The author might wanna change that in his code example.
Helge
Hi,
I made this project in Delphi 10 Seattle(SDK API-Level 22) and i made the changes for a BigTextStyle in both pas-files (Androidapi.JNI.Support.pas, System.Android.Notification.pas) just like Android MultiLine Notification Step By Step Guide.
But notification style is not multiLine and as before.
Hi Admin.
Mee too, I made all the modifications of your ten steps, checked twice, but my notifications continue to show on a single line, both on an Asus tablet with Android 4.2.2 and on a Samsung S5 (Lollipop)..
May you help me to understand where I have to look? 😉
Thanks
Marco
Hello,
Is possible do it with GCM Push Notifications (remote notifications)?
Just for anyone else looking at this, these instructions are for Local Notifications, not GCM Push Notifications.
I’m guessing, that something similar can be done for GCM Push Notifications as well.