Android/Firebase - Error while parsing timestamp in GCM event - Null timestamp
Even though notification
is apparently a supported element (according to the Firebase web docs), the only way I could get rid of the exception was to remove it entirely, and use the data
section only, and then in my app create a notification (rather than letting firebase do the notification).
I used this site to work out how to raise the notifications: https://www.androidhive.info/2012/10/android-push-notifications-using-google-cloud-messaging-gcm-php-and-mysql/
My notification now looks like the following:
$fields = array("to" => "<valid-token>",
"data" => array("data"=>
array(
"message"=>"This is some data",
"title"=>"This is the title",
"is_background"=>false,
"payload"=>array("my-data-item"=>"my-data-value"),
"timestamp"=>date('Y-m-d G:i:s')
)
)
);
...
<curl stuff here>
...
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
My onMessageReceived
looks like this:
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());
try {
JSONObject json = new JSONObject(remoteMessage.getData().toString());
handleDataMessage(json);
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
}
}
which calls handleDataMessage
which looks like this:
private void handleDataMessage(JSONObject json) {
Log.e(TAG, "push json: " + json.toString());
try {
JSONObject data = json.getJSONObject("data");
String title = data.getString("title");
String message = data.getString("message");
boolean isBackground = data.getBoolean("is_background");
String timestamp = data.getString("timestamp");
JSONObject payload = data.getJSONObject("payload");
// play notification sound
NotificationUtils notificationUtils = new NotificationUtils(getApplicationContext());
notificationUtils.playNotificationSound();
if (!NotificationUtils.isBackgroundRunning(getApplicationContext())) {
// app is in foreground, broadcast the push message
Intent pushNotification = new Intent(ntcAppManager.PUSH_NOTIFICATION);
pushNotification.putExtra("message", message);
LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);
} else {
// app is in background, show the notification in notification tray
Intent resultIntent = new Intent(getApplicationContext(), MainActivity.class);
resultIntent.putExtra("message", message);
showNotificationMessage(getApplicationContext(), title, message, timestamp, resultIntent);
}
} catch (JSONException e) {
Log.e(TAG, "Json Exception: " + e.getMessage());
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.getMessage());
}
}
this then calls showNotificationMessage
/**
* Showing notification with text only
*/
private void showNotificationMessage(Context context, String title, String message, String timeStamp, Intent intent) {
notificationUtils = new NotificationUtils(context);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
notificationUtils.showNotificationMessage(title, message, timeStamp, intent);
}
And subsequently notificationUtils.showNotificationMessage
public void showNotificationMessage(String title, String message, String timeStamp, Intent intent) {
showNotificationMessage(title, message, timeStamp, intent, null);
}
public void showNotificationMessage(final String title, final String message, final String timeStamp, Intent intent, String imageUrl) {
// Check for empty push message
if (TextUtils.isEmpty(message))
return;
// notification icon
final int icon = R.mipmap.ic_launcher;
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent resultPendingIntent =
PendingIntent.getActivity(
mContext,
0,
intent,
PendingIntent.FLAG_CANCEL_CURRENT
);
final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
mContext);
final Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
+ "://" + mContext.getPackageName() + "/raw/notification");
showSmallNotification(mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);
playNotificationSound();
}
private void showSmallNotification(NotificationCompat.Builder mBuilder, int icon, String title, String message, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) {
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
inboxStyle.addLine(message);
Notification notification;
notification = mBuilder.setSmallIcon(icon).setTicker(title).setWhen(0)
.setAutoCancel(true)
.setContentTitle(title)
.setContentIntent(resultPendingIntent)
.setSound(alarmSound)
.setStyle(inboxStyle)
.setWhen(getTimeMilliSec(timeStamp))
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon))
.setContentText(message)
.build();
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(ntcAppManager.NOTIFICATION_ID, notification);
}
More detail in the link above, and it's a lot of handling but at least the exception's gone and I'm in control of the notifications.
EDIT - Firebase Timestamp Causing 'Cannot read properties of null' error in HTML interpolation while adding new document
Alright, the solution is surprisingly simple but it took me a while to even figure out what the problem was. In the end, I went back to an article I had read when I was first working with firebase timestamps on medium. There is a lot of detail, but the upshot is that until the timestamp is finalized it's going to default returning a null value, which is what was causing my null error.
The solution is to use 'SnapshotOptions' to modify each documentsnapshot with an estimate of what the timestamp would be. I don't need nanosecond precision, so this is perfect for my usage.
In the end, my change wasn't even in something I had originally posted, it's inside of the service and is what returns the subscription for sessionSource in ngOnIt.
Below is the entire section, but all I did was add { serverTimestamps: 'estimate' } as an option to the payload.doc.data() function. This set's an estimated timestamp, and I no longer have the null errors.
getSessionList(pid: string){
return this.afs.collection(this.CollectionPath+pid+'/Sessions', ref => ref.orderBy('startDate', 'desc')).snapshotChanges().pipe(
map(actions => {
return actions.map(a => {
const data = a.payload.doc.data({ serverTimestamps: 'estimate' }) as sessions_list;
const id = a.payload.doc.id;
return { id, ...data };
})
}
))
}
There is a similar question I found while looking for a solution.
Firebase Cloud Message Push Notifications giving errors
To fix the failed to post notification on channel null problem, you have to update your firebase-messaging version to latest or at least 15.0.2. Hope this will resolve the problem.
In addition to this you may add the below meta data in your AndroidManifest to double sure that it will work. Thanks
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id"/>
Xamarin.Forms Android app hangs when opened by tapping push message
Start your pushes by checking android OS first:
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
SetOreoNotification();
}
else
{
DispatchNotificationThatServiceIsRunning();
}
Then do this (taken from a project of mine that works fine on all Android devices:)
void DispatchNotificationThatServiceIsRunning()
{
int id = 50;
try
{
RemoteViews contentView = new RemoteViews(PackageName, Resource.Layout.Notification);
contentView.SetTextViewText(Resource.Id.txt_crrentSong_notification, Activity_Player.txt_CurrentSong.Text);
contentView.SetTextViewText(Resource.Id.txt_crrentSong__artist_notification, Activity_Player.txt_CurrentArtist.Text);
notificationBuilder = new Notification.Builder(ApplicationContext);
Notification.Builder builder = new Notification.Builder(this)
.SetSmallIcon(Resource.Drawable.btn_icon_header)
.SetCustomContentView(contentView);
Task.Delay(_countDownFirstRound).ContinueWith(t =>
{
NotificationManager notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Notify(id, notificationBuilder.Build());
DispatchNotificationThatServiceIsRunning();//This is for repeate every 1s.
_countDownFirstRound = 50;
// Click on notification, and return to app. Only works, because _2TimerRunning is set as : "LaunchMode = LaunchMode.SingleInstance"
Intent notificationIntent = new Intent(this, typeof(Activity_Player));
notificationIntent.SetAction(Intent.ActionMain);
notificationIntent.AddCategory(Intent.CategoryLauncher);
PendingIntent contentIntent = PendingIntent.GetActivity(this, 1, notificationIntent, PendingIntentFlags.UpdateCurrent);
notificationBuilder.SetContentIntent(contentIntent);
},
TaskScheduler.FromCurrentSynchronizationContext());
}
catch
{
Toast.MakeText(this, "ERROR NOTIFY", ToastLength.Short).Show();
}
}
void SetOreoNotification()
{
RemoteViews contentView = new RemoteViews(PackageName, Resource.Layout.NotificationOreo);
contentView.SetTextViewText(Resource.Id.txt_crrentSong_notification_oreo, Activity_Player.txt_CurrentSong.Text);
contentView.SetTextViewText(Resource.Id.txt_crrentSong__artist_notification_oreo, Activity_Player.txt_CurrentArtist.Text);
const string URGENT_CHANNEL = "com.xamarin.myapp.urgent";
string chanName = "xy";
var importance = NotificationImportance.Default;
NotificationChannel chan = new NotificationChannel(URGENT_CHANNEL, chanName, importance);
chan.SetSound(null, null);
//chan.EnableVibration(true);
chan.LockscreenVisibility = NotificationVisibility.Private;
NotificationManager notificationManager =
(NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(chan);
Intent notificationIntent = new Intent(this, typeof(Activity_Player));
notificationIntent.SetAction(Intent.ActionMain);
notificationIntent.AddCategory(Intent.CategoryLauncher);
PendingIntent contentIntent = PendingIntent.GetActivity(this, 1, notificationIntent, PendingIntentFlags.UpdateCurrent);
Notification.Builder builder = new Notification.Builder(this)
.SetSmallIcon(Resource.Drawable.btn_icon_header)
.SetCustomContentView(contentView)
.SetChannelId(URGENT_CHANNEL)
.SetContentIntent(contentIntent)
.SetGroupAlertBehavior(NotificationGroupAlertBehavior.Summary)
.SetGroup("My group")
.SetGroupSummary(false);
const int NOTIFY_ID = 1100;
notificationManager.Notify(NOTIFY_ID, builder.Build());
}
Notification message seems to be empty when app is on foreground
This was solved by updating (1)firebase-messaging
and (2)flutter_local_notifications
to their latest versions.
Cant receive Notifications from FCM while the app is in Foreground state
I discovered the problem, It was that I am using Android O and didn't set the Channel ID for the notification which is a must if you want to receive it on Android 8.0 or higher
so here is the solution code
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
Related Topics
Android Exporting to CSV and Sending as Email Attachment
Receiver Not Registered Exception Error
Android Viewpager Get the Current View
Could Not Access the Package Manager. Is the System Running While Installing Android Application
Why Is the Android Test Runner Reporting "Empty Test Suite"
What Are the Differences Among Internal Storage, External Storage, Sd Card and Removable Storage
How to Know When Tts Is Finished
Webview Textarea Doesn't Pop Up the Keyboard
Disable Soft-Keyboard from Edittext But Still Allow Copy/Paste
Android Sdk Cannot Be Found by Flutter
Equivalent of Clean & Build in Android Studio
Com.Google.Android.Gsf Package Couldn't Be Found
Android Set Button Background Programmatically
How to Change Color of Listview Items on Focus and on Click
Applying Effects on Video Being Played
Unsigned APK Can Not Be Installed
How to Check If APK Is Signed or "Debug Build"
Android Youtubeplayer with Unauthorized Overlay on Top of Player