I have a Web Panel on Genexus X Ev2 U7 where I´m trying to send a push notification to my Android app developerd on Genexus X Ev3 U5.
The code is the following:
Event Start
&MessageCharacter = 'Mi Notificacion'
&GpsDeviceToken = 'APx91bFWDR86o4sx7DeP2mmqLaO5RIRp1g_giDFu2grYIpDQxY5Nw3F_AcYERmAkQLjqzVcXtY9tveUYOemUztFzH8DVfeWefIhxmsNMkPHDFjP44cao_ch97PMmianhdpahQtQANPubc70FsKUpFJqrSNZcGVurEQ'
&GpsDeviceType = SmartDeviceType.Android
EndEvent
Event Enter
&RemoteNotification = new()
&RemoteNotification.DeviceToken = &GpsDeviceToken
&RemoteNotification.DeviceType = &GpsDeviceType
&RemoteNotification.Message = &MessageCharacter
//&RemoteNotification. .Event.Name = &EventNameCharacter
//Send
&Notifications.OpenSession("EncuestasMoviles")
&Notifications.Add(&remoteNotification)
&Notifications.Send()
EndEvent
When I execute enter event, web page keeps waiting.
Is this the correct way to send notifications?
Regards,
Rogelio Arosemena
The problem was that in Genexus Ev2, sending method is different. The code that works is:
&Notifications.Call(&SdAplicationMainPanelName,&DeviceType,&DeviceToken,&MessageCharacter)
Related
Hello dear community I am teaching myself app programming via Sketchware.
I'm writing a GPS tracker that does the following.
The user sets a time after which the location data is sent as an SMS. Ex: send location data every 60 minutes.
The battery state of charge is constantly monitored and at 30 percent it sends an SMS to the user to draw attention to it.
My problem now is that no SMS is sent when the screen is off. However, the app does not have to be visible. I read a lot of reports about power management and try to get a PARTIAL_WAKE_LOCK all the time. No matter how I try, it always ends in an error. I would be very happy to get help with my problem.
private void initializeLogic() {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DoNotSleep");
wl.acquire();
setBG = 0;
VideoView.setVisibility(View.GONE);
setTitle("GPS - Tracker BETA BUILD");
ArabWare = ArabWare.getDefault();
if (geoData.getString("setFirstRun", "").equals("")) {
_setVarDefault();
}
else {
if (geoData.getString("setFirstRun", "").equals("1")) {
_setSplash();
_getStats();
_batState();
_lfzV14();
_testInfo();
}
}
geoData.edit().putString("setFinish", "0").commit();
}
It is not possible for me to implement the PowerManager in the onCreate in Sketchware. Even if I edit the code manually, it always ends up in private void initializeLogic() I'm not getting a wake lock. This instruction PowerManager.WakeLock wl; always leads to an error.
wl cannot be resolved to a variable
[NOTE: updated to better reflect understanding of the issue]
I am trying to move all events from one Google calendar to another using Google Scripts.
I have written the following code:
function move_all_events()
{
var fromYear = 2016;
var toYear=2020
var fromDate = new Date(fromYear,0,1,0,0,0); //Year, Month (where 0 = Jan, 1 = Feb...), Hour, Min, Sec, Millisecond
var toDate = new Date(toYear,1,0,0,0);
var fromCalendarName = 'Calendar1';
var toCalendarName = 'Calendar2';
// Move from start of fromYear to start of toYear (for month 0 = Jan, 1 = Feb...)
var fromCalendar = CalendarApp.getCalendarsByName(fromCalendarName)[0];
var toCalendar = CalendarApp.getCalendarsByName(toCalendarName)[0];
var fromCalendarId = fromCalendar.getId();
var toCalendarId = toCalendar.getId();
Logger.log(fromCalendarId);
Logger.log(toCalendarId);
var events = fromCalendar.getEvents(fromDate, toDate);
for(var i=0; i<events.length;i++){
var evId = events[i].getId().replace("#google.com", "");
Logger.log(evId); // show event Id in log
Calendar.Events.move(fromCalendarId, evId, toCalendarId);
}
}
The above code WORKS fine when the events to-be-moved have been created manually from within Google Calendar.
However, the code FAILS when the events to-be-moved were created externally in an ical/ics file and then IMPORTED into Google calendar.
When I run the code, I get the following error:
API call to calendar.events.move failed with error: Not Found (line 86, file "Code")
where line 86 is the line with Calendar.Events.move.
Note the log shows:
[20-04-24 01:26:15:031 EDT] myname#gmail.com
[20-04-24 01:26:15:032 EDT] asfdsfdsfdsfekwlkkllkpauc700#group.calendar.google.com
[20-04-24 01:26:15:986 EDT] myeventidprefix-a3a597f53ff059959e950fc513df33af
All seems "correct" and indeed the event Id is exactly the UID that I created externally in the ics file that I then imported.
Yet somehow, it seems that Calendar.Events.move is not able to find the event itself in the fromCalendar.
Any idea what is going wrong here?
A SECOND problem that I noted is that even when the routine works (i.e. for events created within Google Calendar), the 'notifications' are not moved. I.e., if I create an event in fromCalendar with notifications, the moved events in toCalendar have lost the notification. Note that neither calendar has Event or 'All Day' notifications turned-on generally.
Interestingly, if I move that same event back to fromCalendar, the notifications magically reappear.
So any idea why the notifications are seemingly still internally intact but are not visible along with the other event data
OK - I solved the first part.
The problem is that for imported iCal events, the iCal UID is not the same as the Google event ID. In particular, .getId() returns the iCal UID, while the function Calendar.Events.move needs the Google event ID which can be retrieved via: Calendar.Events.list(fromCalendarId).items
See: How can I find the Event Id of my Google Calendar event?
This of course is not an issue for native events since the ID's are the same which explains why my original code worked for native events.
Revised code is as follows:
for(var i=0; i<events.length; i++){
var evId = events[i].id;
Logger.log(i + ": " + evId); // show event Id in log
Calendar.Events.move(fromCalendarId, evId, toCalendarId); //Note need to turn on Calendar API under Resources
}
This however moves some but not all of the events which is weird... and I don't see any pattern... Indeed, among many similar events some are moved and others aren't.
(Also, as noted above, the notifications don't move over as mentioned before.)
Using the Google CAF Receiver SDK, how do we prevent the receiver from timing out and automatically killing the cast session when we're not using the receiver player?
The standard Google Cast use case is to send media from a device to the cast receiver and have the receiver render the media using a player. The CAF receiver SDK provides this functionality in a beautiful, simple way using the element cast-media-player.
But for those instances when we want to cast from a device and render content where it's not relevant to use the cast-media-player (e.g. an HTML dashboard), how do we keep the receiver alive?
The following custom receiver for example (HAML for brevity), results in the cast session automatically terminating after 5 minutes...
!!! 5
%html
%head
:css
cast-media-player {
display: none;
}
= javascript_include_tag 'https://www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js'
%body
%cast-media-player
:javascript
const context = cast.framework.CastReceiverContext.getInstance();
const player = context.getPlayerManager();
player.setMessageInterceptor(cast.framework.messages.MessageType.LOAD, loadRequestData => {
...[load custom view]...
return false;
});
context.start();
The receiver log shows the line cast.framework.common.IdleTimeoutManager] timer expired and then shuts down. Example receiver log shown here.
I've tried:
Increasing cast.framework.CastReceiverOptions#maxInactivity to a very large number
Periodically loading new data from the sender
Periodically sending custom messages from the receiver to the sender
Periodically sending custom messages from the sender to the receiver
Any help is very much appreciated!
I ran into the same problem while developing a custom receiver app that does not play media. Here is the solution I implemented:
var idleTime = 0;
const context = cast.framework.CastReceiverContext.getInstance();
const CUSTOM_CHANNEL = '[MY CHANNEL HERE]';
context.addCustomMessageListener(CUSTOM_CHANNEL, function(customEvent) {
var eventData = customEvent.data;
parseCommand(eventData);
idleTime = 0;
});
const options = new cast.framework.CastReceiverOptions();
options.disableIdleTimeout = true;
context.start(options);
var idleInterval = setInterval(timerIncrement, 60000); // 1 minute
function timerIncrement() {
idleTime = idleTime + 1;
if (idleTime > 4) { // 5 minutes
context.stop();
}
}
With CastReveiverOptions I disable idle timeout, which according to the documentation: "If true, the receiver will not set an idle timeout to close receiver if there is no activity. Should only be used for non media apps."
https://developers.google.com/cast/docs/reference/caf_receiver/cast.framework.CastReceiverOptions#constructor_1
Since mine is a "non media app," I believe this is correct usage.
I then set my own time out based on 5 minutes of inactivity in my custom channel.
I figured out an alternative way to stop this which is more efficient than periodically sending a silent clip, but it feels dirty. Basically we have to stop Chromecast's setTimeout from firing and closing the connection due to no media. The quickest solution is to simply re-declare setTimeout as a dummy no-op function before loading the Chromecast receiver script. It does not seem to break anything Chromecast-related in this scenario because it looks like Chromecast's timeouts are all related to video which aren't relevant to this use case.
window._setTimeout = window.setTimeout;
window.setTimeout = function(a, b) {
// disable setTimeout so chromecast won't kill us after 5 minutes...
};
Then in our own app if we need to use a timeout we call _setTimeout instead.
I would be interested if anyone has discovered a better way to achieve this, aside from manually hosting cast_receiver_framework.js with the offending line commented out (which is inside the Wn(a, b) function) or sending a silent clip every few minutes. But self-hosting isn't recommended by Google.
A better solution may be to dig deep in the minified code to work out how Xn(a) is called as that disables the timeout whenever media is playing, and then find a way to call that from within the Chromecast app.
Loading a short inaudible audio clip from the sender to the receiver every 4 minutes seems to do the trick. This should not impact performance much if the file is small. Here is some android code.
MediaMetadata metadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MUSIC_TRACK);
MediaInfo mediaInfo = new MediaInfo.Builder("https://some-inaudible-clip.mp3")
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setContentType("audio/mpeg")
.setMetadata(metadata)
.build();
RemoteMediaClient remoteMediaClient = castSession.getRemoteMediaClient();
remoteMediaClient.load(mediaInfo, true);
It is possible to send a custom namespace message from the receiver to the sender. That should keep the heartbeat live. However, your use case is not directly supported by the Cast SDK, so you would have to experiment on a solution.
Currently when i create a NSUserNotification using Alert style it won't hide unless i manually close it.
Is there a way i can auto close/hide it say after 2 sec?
NSUserNotification code is for reference :
let notification:NSUserNotification = NSUserNotification()
notification.title = "Title"
notification.subtitle = "Subtitle"
notification.informativeText = "Informative text"
notification.soundName = NSUserNotificationDefaultSoundName
notification.deliveryDate = NSDate(timeIntervalSinceNow: 10)
notification.hasActionButton = false
let notificationcenter:NSUserNotificationCenter = NSUserNotificationCenter.defaultUserNotificationCenter()
notificationcenter.scheduleNotification(notification)
It's actually very simple to do this, using NSObject's
performSelector:withObject:afterDelay: method.
Because you're scheduling the notification delivery after a certain time interval, you need to add the additional delay before dismissing, to the initial delay before delivering. Here, I've written them out as constants of 10 seconds before delivery, and 2 seconds before dismissal:
let delayBeforeDelivering: NSTimeInterval = 10
let delayBeforeDismissing: NSTimeInterval = 2
let notification = NSUserNotification()
notification.title = "Title"
notification.deliveryDate = NSDate(timeIntervalSinceNow: delayBeforeDelivering)
let notificationcenter = NSUserNotificationCenter.defaultUserNotificationCenter()
notificationcenter.scheduleNotification(notification)
notificationcenter.performSelector("removeDeliveredNotification:",
withObject: notification,
afterDelay: (delayBeforeDelivering + delayBeforeDismissing))
And for Swift 5 you can use the following:
let delayBeforeDelivering: TimeInterval = 10
let delayBeforeDismissing: TimeInterval = 2
let notification = NSUserNotification()
notification.title = "Title"
notification.deliveryDate = Date(timeIntervalSinceNow: delayBeforeDelivering)
let notificationcenter = NSUserNotificationCenter.default
notificationcenter.scheduleNotification(notification)
notificationcenter.perform(#selector(NSUserNotificationCenter.removeDeliveredNotification(_:)),
with: notification,
afterDelay: (delayBeforeDelivering + delayBeforeDismissing))
You can use removeDeliveredNotification: or removeAllDeliveredNotifications with timer
// Clear a delivered notification from the notification center. If the notification is not in the delivered list, nothing happens.
- (void)removeDeliveredNotification:(NSUserNotification *)notification;
// Clear all delivered notifications for this application from the notification center.
- (void)removeAllDeliveredNotifications;
OS X (10.8 and later)
Blockquote Is there a way i can auto close/hide it say after 2 sec?
No, you do not have any such option till OSX 10.11, may be in future Apple may provide.
There are three ways a user can customise the NSUserNotification also known as Growl notification:
None
Banner
Alert
You as a developer can not control over the system settings. This is upto the user to enable or disable and choose what kind of notification he likes.
If you want any alert to be shown to user you can create your own alert window and show it in that corner. You can set a timer to close, or provide action button to close it once you need.
Update 1:
Cocoa provides NSWindow & NSPanel(HUD and normal panel). You can either customize Window or panel according to your need. Check there are multiple options that would help you to form as per your requirement.
If you can't get, say you wanted a rounded corner then you need to customize the window/view etc.
Please tell me how do I click in point coordinates in application window?
I trying to UI automate my application on OSX 10.10 using JXA technology.
In documentation I found that it's possible using click at event. By I'am beginner of JXA and cant find how make a call.
Code snippet which I tried in Script Editor:
var app = Application('my_application_path')
app.window.click.at('{100,100}')
Thank you for help
You can interact with an application's user interface using the System Events application. Here is a script that clicks at certain coordinates in Safari:
// Activate Safari, so you will be able to click like a user
Application("Safari").activate()
// Access the Safari process of System Events
var SystemEvents = Application("System Events")
var Safari = SystemEvents.processes["Safari"]
// Call the click command, sending an array of coordinates [x, y]
Safari.click({ at: [300, 100] })
If you want to click a specific button (or other element of the user interface), it is more appropriate to click that specific element. For example:
// Click the third button of Safari's first window to minimize it
Safari.windows[0].buttons[2].click()
To learn what user interface elements can be interacted with and how, check out the Processes Suite in System Events' scripting dictionary. To open the dictionary, in Script Editor's menu bar, choose Window > Library, then select System Events in the Library window.
See https://github.com/dtinth/JXA-Cookbook/wiki/System-Events#clicking-menu-items
For example:
var fileMenu = proc.menuBars[0].menuBarItems.byName('File');
Below is an example of a portion of a script I wrote that automates creating mailboxes (aka folders) in Mail. I ended up using the UI file menus and click because using make() in the Mail DOM had issues for me. Hope it helps someone.
(() => {}
//this is part of a script that automates creating mailboxes (ie folders) in Apple Mail
//I used the file menu UI because when I tried the Mail library and make() method
//there was strange behavior when trying to interact with the new mailbox.
//However, when creating the new mailboxes thru the file menu, all seems to work fine
const Mail = Application('Mail');
const strId = Mail.accounts.byName('Exchange').id();
const exchange = Mail.accounts.byId(strId);
const activeClientFolder = exchange.mailboxes.byName('ActiveClient');
const SysEvents = Application('System Events');
const mail = SysEvents.processes.byName('Mail');
//next two lines insure Mail will be open and in front
mail.windows[0].actions.byName('AXRaise').perform();
mail.frontmost = true;
const mailboxMenu = mail.menuBars[0].menus.byName('Mailbox');
//below shows EXAMPLES of using .click(), keystroke(), and keyCode()
let newFolder = function (parentFolder, newFolderName, addTrailingDelay = true) {
//next line will select the parent mailbox (aka folder) where the new mailbox will be inserted
Mail.messageViewers[0].selectedMailboxes = parentFolder;
mailboxMenu.click();
delay(.2);
mailboxMenu.menuItems.byName('New Mailbox…').click();
delay(.2);
SysEvents.keystroke(newFolderName);
SysEvents.keyCode(36);
//delay is needed when creating multiple mailboxes with a loop
if (addTrailingDelay == true){
delay(1);
}
}
//now the payoff
const count = newActiveClients.length;
for(let i=0;i<count;i++){
/* Client Root Mailbox */
newFolder(activeClientFolder, newActiveClients[i], true);
/* Client Email Folders */
newFolder(activeClientFolder.mailboxes.byName(newActiveClients[i]), 'Client', true);
newFolder(activeClientFolder.mailboxes.byName(newActiveClients[i]).mailboxes.byName('Client'), 'Client_FYI_Sent');
newFolder(activeClientFolder.mailboxes.byName(newActiveClients[i]).mailboxes.byName('Client'), 'Client_FYI_Inbox');
newFolder(activeClientFolder.mailboxes.byName(newActiveClients[i]).mailboxes.byName('Client'), 'Client_FYI_Client_To');
newFolder(activeClientFolder.mailboxes.byName(newActiveClients[i]).mailboxes.byName('Client'), 'Client_From', false);
}
})()