How to access delivered UNNotifications in Titanium Hyperloop on iOS? - appcelerator

I'm creating an application in Titanium and I'm using hyperloop to access different parts of the native API's and this has been working great. But now I'm trying to count the notifications a user has received based on notification id, but this doesn't seem to work (it's close to working).
Titanium SDK: 7.1.1.GA
iOS: 11.4.1
Device: iPhone 5s
This is what I'm trying now (I want to get the userInfo.id eventually)
exports.getDelivered = function() {
var UNUserNotificationCenter = require('UserNotifications/UNUserNotificationCenter');
var nc = UNUserNotificationCenter.currentNotificationCenter();
nc.getDeliveredNotificationsWithCompletionHandler(function(notifications) {
for (var i = 0; i < notifications.count; i++) {
var notification = notifications.objectAtIndex(i);
console.log('notification: ' + notification);
console.log('notification.request.identifier: ' + notification.request.identifier);
}
});
};
This does seem to get the right notification, as the first log statement gives me:
<UNNotification: 0x101075150;
date: 2018-08-14 12:58:00 +0000,
request: <UNNotificationRequest: 0x10106cbd0;
identifier: DB9191AC-B716-4F43-8E03-7613C8D6BFC6,
content: <UNNotificationContent: 0x106326930;
title: ,
subtitle: (null),
body: Have you completed one crossword, puzzle or brain game today?,
categoryIdentifier: ,
launchImageName: ,
peopleIdentifiers: (),
threadIdentifier: ,
attachments: (),
badge: 1,
sound: (null),
hasDefaultAction: YES,
defaultActionTitle: (null),
shouldAddToNotificationsList: YES,
shouldAlwaysAlertWhileAppIsForeground: NO,
shouldLockDevice: NO,
shouldPauseMedia: NO,
isSnoozeable: NO,
fromSnooze: NO,
darwinNotificationName: (null),
darwinSnoozedNotificationName: (null),
trigger: <UNLegacyNotificationTrigger: 0x100f87010;
repeats: YES,
date: 2018-08-14 12:58:00 +0000,
timeZone: Europe/Amsterdam (CEST) offset 7200 (Daylight),
remainingRepeatCount: -2147483648,
totalRepeatCount: -2147483648,
repeatInterval: 16,
repeatCalendar: (null)
>
>
>
>
But the second log statement seems to cause some kind of exception without a message. So my question is how do I actually access the notification object, especially the id that I've given to the notification (userInfo.id)?

I found the answer, apparently I have to cast to notification to a UNNotification first.
exports.getDelivered = function() {
var UNUserNotificationCenter = require('UserNotifications/UNUserNotificationCenter');
var UNNotification = require('UserNotifications/UNNotification');
var nc = UNUserNotificationCenter.currentNotificationCenter();
nc.getDeliveredNotificationsWithCompletionHandler(function(notifications) {
for (var i = 0; i < notifications.count; i++) {
var notification = UNNotification.cast(notifications.objectAtIndex(i));
console.log('notification: ' + notification);
console.log('notification.date: ' + notification.request.content.userInfo.objectForKey("id"));
}
});
};

Related

create local notification in xamarin ios with http request

i have xamarin forms app that support notification, i have done it in android with broadcast receiver now i have to do notification in ios ! , my service is depending on API REST so i want every 60 second ios app run HTTP request and get data then show it as notification, i searched for many days but i can't reach to my approach ?
if this is impossible can i use nuget or something like that in ios project only "in xamarin forms solution " or not ?
content = new UNMutableNotificationContent();
content.Title = "Notification Title";
content.Subtitle = "Notification Subtitle";
content.Body = "This is the message body of the notification.";
content.Badge = 1;
content.CategoryIdentifier = "message";
var trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(60, true);
var requestID = "sampleRequest";
var request = UNNotificationRequest.FromIdentifier(requestID, content, trigger);
UNUserNotificationCenter.Current.AddNotificationRequest(request, (err) =>
{
if (err != null)
{
// Do something with error...
}
});
Here is my code for generating a local notification on iOS
var alertsAllowed = false;
UNUserNotificationCenter.Current.GetNotificationSettings((settings) =>
{
alertsAllowed = (settings.AlertSetting == UNNotificationSetting.Enabled);
});
if (alertsAllowed)
{
var content = new UNMutableNotificationContent();
content.Title = "Incident Recorder";
content.Subtitle = "Not Synchronised";
content.Body = "There are one or more new incidents that have not been synchronised to the server.";
var trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(5, false);
var requestID = "sampleRequest";
var request = UNNotificationRequest.FromIdentifier(requestID, content, trigger);
UNUserNotificationCenter.Current.AddNotificationRequest(request, (err) =>
{
if (err != null)
{
Console.WriteLine(err.LocalizedFailureReason);
}
});
}
The first parameter in CreateTrigger is how long before the notification is generated. I notice you have 60 in yours. Also bear in mind a notification will not appear if your app is foregrounded.

Parse IOS push dropping messages when sent consecutively

Parse is dropping pushes for IOS. I send 10 messages in a row, with 3 secs interval, works well for Android, but parse drops messages randomly for IOS. The messages are sent through a clound function, which works well for Android. You can see in the picture four failed in a row then 3 succeeded in a row, then fail and succeed. my Cloud function is pretty simple, it first searches the installations and then check if it's iOS, does a little formatting and send it.
Function pushToInstallations(results, messageObject, response) {
var pushedCount = 0;
var failedCount = 0;
for (i in results) {
Parse.Cloud.useMasterKey();
var installation = new Parse.Installation(results[i]);
console.log("processing installation " + i);
// console.log(installation);
var deviceType = installation.get("deviceType");
console.log("installation deviceType " + deviceType);
var payload;
if (deviceType == "android") {
payload = createAndroidPayload(messageObject, installation);
} else {
payload = createIosPayload(messageObject, installation);
}
var query = new Parse.Query(Parse.Installation);
console.log("installation id" + installation.get("installationId"))
query.equalTo("installationId", installation.get("installationId"));
Parse.Push.send({
where: query,
data: payload
}).then(function() {
pushedCount++;
.....
}, function(error) {
failedCount++;
.....
});
}
}
You have to know that the Push Notification is not 100% guarantee. And it's indicated by Apple clearly.

Map pans and zooms when opening info window

when I click on a marker the map always re-pans and zooms to the initial state. Not such a big deal for a single marker but if I start with a cluster, zoom in and then click on a marker there is the problem. It zooms out, reclusters and then pops up the window. Anybody come across this issue?
This is what it looks like:
Here is the relevant code:
var loc = { latitude: item.Latitude, longitude: item.Longitude };
var marker = { location: loc, label: item.Label, id: item.Id, value: item.Value,showWindow:false };
markers.push(marker);
marker.onClick = function () {
if ($scope.$$phase || $scope.$root.$$phase) {
this.model.showWindow = true;
} else {
var self = this;
$scope.$apply(function() {
self.model.showWindow = true;
});
}
};
And the markup. This is in another directive that allows me to just keep a list of different layer types:
'<markers models="mylayer.locations" coords="\'location\'" doRebuildAll="true" idKey="\'id\'" doCluster="true" fit="true" options="mylayer.options" click="\'onClick\'">' +
'<windows show="\'showWindow\'" doRebuildAll="false" disableAutoPan="true" data-ng-if="mylayer.options.clickable" ng-cloak>' +
'<div>hello</div>' +
'</windows>' +
'</markers>'
Turns out the problem happened when updating from version 1.1.0 of angular-google-maps.js to version 1.1.4. Reverted and it works fine now.

google map v3, cannot load marks for firefox 26.0(latest version)

For now we are using google map v3, after we upgraded firefox 26.0, the marks cannot be loaded
I set many alerts and compared them between Chrome and firefox 26.0, I found here is a variable this.ready_ cannot be assigned a value(true) in firefox 26.0 , that is this method cannot be called below
MarkerClusterer.prototype.onAdd = function() {
alert("enter MarkerClusterer.prototype.onAdd!");
this.setReady_(true);
};
MarkerClusterer.prototype.setReady_ = function(ready) {
alert("enter setReady!");
if (!this.ready_) {
this.ready_ = ready;
alert("will enter createClusters_() in setReady_");
this.createClusters_();
}
};
I tried to find where does call onAdd for pinpoint the issue, however, it called by google itself, here is stack call
MarkerClusterer.onAdd MarkerClusterer.js:225
mG VM148:1
anonymous function %7Bmain,places%7D.js:11
Thank you by advance!
Jason
I have fixed this issue, the problem was from MarkerClusterer.js, someone commentted these 2 lines below leads to this issue(just comment them off will be ok), hope it is also helpful for others.
in MarkerClusterer.js
MarkerClusterer.prototype.setupStyles_ = function() {
if (this.styles_.length) {
return;
}
// for (var i = 0, size; size = this.sizes[i]; i++) {
this.styles_.push({
url: this.imagePath_ + '.' + this.imageExtension_,
height: 36,
width: 43
// });
}

Using sockets (nsIServerSocket) in XPCOM component (Firefox Extension) (sockets + new window = seg faults)

PLEASE READ THE UPDATE #2 BELOW IF YOU ARE INTERESTED IN THIS PROBLEM ;)
Say I put this code into the JS of my extension.
var reader = {
onInputStreamReady : function(input) {
var sin = Cc["#mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
sin.init(input);
sin.available();
var request = '';
while (sin.available()) {
request = request + sin.read(512);
}
console.log('Received: ' + request);
input.asyncWait(reader,0,0,null);
}
}
var listener = {
onSocketAccepted: function(serverSocket, clientSocket) {
console.log("Accepted connection on "+clientSocket.host+":"+clientSocket.port);
input = clientSocket.openInputStream(0, 0, 0).QueryInterface(Ci.nsIAsyncInputStream);
output = clientSocket.openOutputStream(Ci.nsITransport.OPEN_BLOCKING, 0, 0);
input.asyncWait(reader,0,0,null);
}
}
var serverSocket = Cc["#mozilla.org/network/server-socket;1"].
createInstance(Ci.nsIServerSocket);
serverSocket.init(-1, true, 5);
console.log("Opened socket on " + serverSocket.port);
serverSocket.asyncListen(listener);
Then I run Firefox and connect to the socket via telnet
telnet localhost PORT
I send 5 messages and they get printed out, but when I try to send 6th message I get
firefox-bin: Fatal IO error 11 (Resource temporarily unavailable) on X server :0.0.
Even worse, when I try to put this same code into an XPCOM component (because that's where I actually need it), after I try sending a message via telnet I get
Segmentation fault
or sometimes
GLib-ERROR **: /build/buildd/glib2.0-2.24.1/glib/gmem.c:137: failed to allocate 32 bytes
aborting...
Aborted
printed to the terminal from which I launched firefox.
This is really weird stuff.. Can you spot something wrong with the code I've pasted or is smth wrong with my firefox/system or is the nsIServerSocket interface deprecated?
I'm testing with Firefox 3.6.6.
I would really appreciate some answer. Perhaps you could point me to a good example of using Sockets within an XPCOM component. I haven't seen many of those around.
UPDATE
I just realised that it used to work so now I think that my Console
component breaks it. I have no idea how this is related. But if I
don't use this component the sockets are working fine.
Here is the code of my Console component. I will try to figure out
what's wrong and why it interferes and I'll post my findings later.
Likely I'm doing something terribly wrong here to cause Segmentation
faults with my javascript =)
Voodoo..
components/Console.js:
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
Console.prototype = (function() {
var win;
var initialized = false;
var ready = false;
var _log = function(m, level, location) {
if (initialized&&ready) {
var prefix = "INFO: ";
switch (level) {
case "empty":
prefix = ""
break;
case "error":
prefix = "ERORR: "
break;
case "warning":
prefix = "WARNING: "
break;
}
win.document.getElementById(location).value =
win.document.getElementById(location).value + prefix + m + "\n";
win.focus();
} else if (initialized&&!ready) {
// Now it is time to create the timer...
var timer = Components.classes["#mozilla.org/timer;1"]
.createInstance(Components.interfaces.nsITimer);
// ... and to initialize it, we want to call
event.notify() ...
// ... one time after exactly ten second.
timer.initWithCallback(
{ notify: function() { log(m); } },
10,
Components.interfaces.nsITimer.TYPE_ONE_SHOT
);
} else {
init();
log(m);
}
}
var log = function(m, level) {
_log(m, level, 'debug');
}
var poly = function(m, level) {
_log(m, "empty", 'polyml');
}
var close = function() {
win.close();
}
var setReady = function() {
ready = true;
}
var init = function() {
initialized = true;
var ww = Components.classes["#mozilla.org/embedcomp/window-
watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher);
win = ww.openWindow(null, "chrome://polymlext/content/
console.xul",
"console", "chrome,centerscreen,
resizable=no", null);
win.onload = setReady;
return win;
}
return {
init: init,
log : log,
poly : poly,
}
}());
// turning Console Class into an XPCOM component
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
function Console() {
this.wrappedJSObject = this;
}
prototype2 = {
classDescription: "A special Console for PolyML extension",
classID: Components.ID("{483aecbc-42e7-456e-b5b3-2197ea7e1fb4}"),
contractID: "#ed.ac.uk/poly/console;1",
QueryInterface: XPCOMUtils.generateQI(),
}
//add the required XPCOM glue into the Poly class
for (attr in prototype2) {
Console.prototype[attr] = prototype2[attr];
}
var components = [Console];
function NSGetModule(compMgr, fileSpec) {
return XPCOMUtils.generateModule(components);
}
I'm using this component like this:
console = Cc["#ed.ac.uk/poly/console;1"].getService().wrappedJSObject;
console.log("something");
And this breaks the sockets :-S =)
UPDATE #2
Ok, if anyone is interested in checking this thing out I would really
appreciate it + I think this is likely some kind of bug (Seg fault
from javascript shouldn't happen)
I've made a minimal version of the extension that causes the problem,
you can install it from here:
http://dl.dropbox.com/u/645579/segfault.xpi
The important part is chrome/content/main.js:
http://pastebin.com/zV0e73Na
The way my friend and me can reproduce the error is by launching the
firefox, then a new window should appear saying "Opened socket on
9999". Connect using "telnet localhost 9999" and send a few messages.
After 2-6 messages you get one of the following printed out in the
terminal where firefox was launched:
1 (most common)
Segmentation fault
2 (saw multiple times)
firefox-bin: Fatal IO error 11 (Resource temporarily unavailable) on
X
server :0.0.
3 (saw a couple of times)
GLib-ERROR **: /build/buildd/glib2.0-2.24.1/glib/gmem.c:137: failed
to
allocate 32 bytes
aborting...
Aborted
4 (saw once)
firefox-bin: ../../src/xcb_io.c:249: process_responses: Assertion
`(((long) (dpy->last_request_read) - (long) (dpy->request)) <= 0)'
failed.
Aborted
If you need any more info or could point me to where to post a bug
report :-/ I'll be glad to do that.
I know this is just one of the many bugs... but perhaps you have an
idea of what should I do differently to avoid this? I would like to
use that "console" of mine in such way.
I'll try doing it with buffer/flushing/try/catch as people are suggesting, but I wonder whether try/catch will catch the Seg fault...
This is a thread problem. The callback onInputStreamReady happened to be executed in a different thread and accessing UI / DOM is only allowed from the main thread.
Solution is really simple:
change
input.asyncWait(reader,0,0,null);
to
var tm = Cc["#mozilla.org/thread-manager;1"].getService();
input.asyncWait(reader,0,0,tm.mainThread);

Resources