How can I update my app's live tile at a fixed interval, for example half a day, using JavaScript?
Moreover, it has to be able to update even though the app itself is not running (like the weather app for example)
EDIT: I want to update it locally without having to connect to the internet. And please give some example in JavaScript, not C# please!
To be more specific, for example, how can I set the tile to update once per day, showing the current date?
If the content on the tile is going to be the date, scheduled tile updates are a good option (see ScheduledTileNotification and the JavaScript Scheduled notifications sample on MSDN). You can schedule a notification to occur once a day with the date as the content.
If you can stand up a web service, periodic updates would be a good option. Using this approach, a tile will be updated on a fixed interval whether or not the app is running. Alternatively, you could use push, or update the tile using a background task.
MSDN has a good article on choosing the right notification delivery mechanism, and links to related code samples: http://msdn.microsoft.com/en-us/library/windows/apps/hh779721.aspx
You can use a background task on a schedule for an interval for anything greater than 15 mins. The tasks are designed to be run by the OS separate to your application, so will be executed if it is not active or open.
Here is a detailed blog post on getting started with background tasks: http://www.silverlightshow.net/items/Windows-8-metro-make-your-app-alive-with-background-tasks.aspx
Register a Background Task that executes ever 12 hours and Updates your Tile.
var RegisterBackgroundTask = function (taskEntryPoint, taskName, trigger, condition) {
UnregisterTask(taskName);
Windows.ApplicationModel.Background.BackgroundExecutionManager.requestAccessAsync();
var TaskBuilder = new Windows.ApplicationModel.Background.BackgroundTaskBuilder();
TaskBuilder.name = taskName;
TaskBuilder.taskEntryPoint = taskEntryPoint;
TaskBuilder.setTrigger(trigger);
if (condition !== null) {
TaskBuilder.addCondition(condition);
// If the condition changes while the background task is executing then it will be canceled.
TaskBuilder.cancelOnConditionLoss = true;
}
var task = TaskBuilder.register();
// Remove previous completion status from local settings.
var settings = Windows.Storage.ApplicationData.current.localSettings;
settings.values.remove(taskName);
};
var UnregisterBackgroundTask = function (sTaskName) {
var iter = Windows.ApplicationModel.Background.BackgroundTaskRegistration.allTasks.first();
var hascur = iter.hasCurrent;
while (hascur) {
var cur = iter.current.value;
if (cur.name === sTaskName) {
cur.unregister(true);
}
hascur = iter.moveNext();
}
}
Register Task like this:
RegisterTask(
"App_JS\\LiveTileTask.js",
"Task.LiveTileTask",
new Windows.ApplicationModel.Background.TimeTrigger(15, false),
new Windows.ApplicationModel.Background.SystemCondition(Windows.ApplicationModel.Background.SystemConditionType.internetAvailable)); // 15 min are minimum
In a dedicated File "LiveTileTask.js" you write the Code of your Live Tile Updater:
(function () {
"use strict";
importScripts("//Microsoft.Phone.WinJS.2.1/js/base.js");
var backgroundTaskInstance = Windows.UI.WebUI.WebUIBackgroundTaskInstance.current;
var Notifications = Windows.UI.Notifications;
var tileUpdateManager = Notifications.TileUpdateManager.createTileUpdaterForApplication();
tileUpdateManager.clear();
tileUpdateManager.enableNotificationQueue(true);
for (var i = 0; i < 6; i++) {
var tileWideXml = Notifications.TileUpdateManager.getTemplateContent(Notifications.TileTemplateType.tileSquare150x150Text04),
tileAttributes = tileWideXml.getElementsByTagName("text");
tileAttributes[0].appendChild(tileWideXml.createTextNode("My Live Tile Text No. " + i));
var currentTime = new Date(),
dueTime = new Date(currentTime.getTime() + 30),
tileNotification = new Notifications.ScheduledTileNotification(xmlTile, dueTime),
tileUpdater = Notifications.TileUpdateManager.createTileUpdaterForApplication();
tileUpdater.addToSchedule(tileNotification);
}
backgroundTaskInstance.succeeded = true;
close();
})();
Finally do not forget to register the backgroundtask in your appxmanifest. Under "declarations" select "Background Task" and activate "Timer" and set "Start Page" to "App_JS\LiveTileTask.js". This way you should be able to update your Tile.
You use Azure and Push Notifications to send out notifications to all your app users: http://msdn.microsoft.com/en-us/library/windows/apps/hh465460.aspx
I recommend you create an Azure Mobile Service. It's really easy and cheap and means you get all of the advantages of a separate push service (instead of a scheduled tile notification on the device) to send your push notifications but without all the work. You can sign up for a free trial if you'd like and create up to 10 mobile services for free. You just create a mobile services and then create a scheduled script that runs every 12 hours and in the script you write a little bit of server-side JavaScript code that does your push. That's just one of the things the Mobile Services gives you. You also get data, authentication, and more. www.windowsazure.com
Related
I was using an external service to get Aggregate Rating in my recipes blog, but dis service disappeared so I decided to build one myself. First of all, this is my first experience with cloud data and JavaScript programming so please, be paciente with me :-).
I'm doing my experiments in this duplicate of my blog: https://jleavalc.blogspot.com/
by now it works as I planned, letting one to vote and storing results in a oracle table, making it possible to retrieve results from a view of this table to get ratingCount and ratingValue values, as anyone can see in that link...
But at the end, despite you can see the stars, despite you can vote and get result stored, showing voting results, Structured data testing tool don't see tag values, so all work is useless.
I think I'm getting close to the problem, but not getting close to the solution. I have the impression that the cause of my problems is the asynchrony of the execution of the script that brings the data from the table, while the function is executed, the browser continues to render the page and it doesn't arrive in time to write those values before the google tool can read them, so they appear empty to it.
I have tried everything including labels and variables in GTM with the same result. The latest version of the code, from this morning is installed right before the "/head" tag and it looks like this:
<script style='text/javascript'>
var myPostId = "<data:widgets.Blog.first.posts.first.id/>";
// <![CDATA[
var micuenta = 0;
var nota = 0;
getText("https://ge4e65cc87f573d-XXXXXXXXXXXX.adb.eu-amsterdam-1.oraclecloudapps.com/ords/admin/notas/?q={\"receta\":{\"$eq\":\"" + myPostId + "\"}}");
async function getText(file) {
let x = await fetch(file);
let y = await x.text();
let datos = JSON.parse(y);
nota = datos.items[0].media;
micuenta = datos.items[0].votos;
};
// This version gives the same result and is interchangeable with the previous one. I keep it commented so as not to forget it:
// var settings = {
// "url": "https://ge4e65cc87f573d-db20220526112405.adb.eu-amsterdam-1.oraclecloudapps.com/ords/admin/notas/?q={\"receta\":{\"$eq\":\"" + myPostId + "\"}}",
// "method": "GET",
// "timeout": 0,
// "async": false,
// };
// $.ajax(settings).done(function (response) {
// if (response.items.length != 0) {
// micuenta = response.items[0].votos;
// nota = response.items[0].media;
// }
// });
</script>
The key is, I think, getting this call to execute before Google's tool finishes rendering the Blogger post page.
The URL that I invoke to get the data calls an oracle view that returns a single row with the corresponding data from the recipe, placing this call:
recipe
In the browser the result is the following:
{"items":[{"receta":"5086941171011962392","media":4.5,"votos":12}],"hasMore":false,"limit":25,"offset":0,"count":1,"links":[{"rel":"self","href":"https://ge4e65cc87f573d-db20220526112405.adb.eu-amsterdam-1.oraclecloudapps.com/ords/admin/notas/?q=%7B%22receta%22:%7B%22%24eq%22:%225086941171011962392%22%7D%7D"},{"rel":"edit","href":"https://ge4e65cc87f573d-db20220526112405.adb.eu-amsterdam-1.oraclecloudapps.com/ords/admin/notas/?q=%7B%22receta%22:%7B%22%24eq%22:%225086941171011962392%22%7D%7D"},{"rel":"describedby","href":"https://ge4e65cc87f573d-db20220526112405.adb.eu-amsterdam-1.oraclecloudapps.com/ords/admin/metadata-catalog/notas/"},{"rel":"first","href":"https://ge4e65cc87f573d-db20220526112405.adb.eu-amsterdam-1.oraclecloudapps.com/ords/admin/notas/?q=%7B%22receta%22:%7B%22%24eq%22:%225086941171011962392%22%7D%7D"}]}
And I just need to take the median and votes values to create the RatingCount and RatingValue labels
Can anyone offer me an idea that solves this little problem? :-)
In the feature flag offerings out there (flagship, launchdarkly, unleashed,...) you can toggle a feature-flag on and off.
There are situations where a toggle will happen in the future. E.g. the site will shut down in xx minutes
How do we best implement such features toggles given that you only have on/off toggles? Use two feature flags? One specifying the site will go down within 10 minutes, and another toggle to actually close the site.
Most Feature Flag (LaunchDarkly, DevCycle) tools allow you to use numbers as well as booleans (toggles) to evaluate the feature flag. You could use a number as the time the site is going down and use that to evaluate the message to users and then at that time disable the site.
When you didn’t need to have the message you can just disable the Feature Flag so that it doesn’t get evaluated.
I would do something like this:
Create a new Feature Flag called time-of-site-to-go-own and set the value to 1642723544000 (Jan 21, 2022 12:05:44 am GST). Then enable it for all users.
So using the DevCycle React SDK this would look like this:
import { useDVCVariable } from '#devcycle/devcycle-react-sdk'
export default function CountDown() {
const variableKey = 'time-of-site-to-go-down'
const defaultValue = 0
const featureVariable = useDVCVariable(variableKey, defaultValue)
if (featureVariable == null) {
return (<></>);
}
if (featureVariable.value == 0) {
return (<div>Site is up</div>)
}
var currentTime = new Date().getTime()
if (currentTime > featureVariable.value) {
return (<div>Site is down</div>)
}
return (
<div>
The site will shutdown at: { (new Date(featureVariable?.value)).toString() }
</div>
)
}
This would then allow your Product Manager to enable the FF and set the time when they want to turn shut the site down.
I need to load a web page and refresh it, automatically, each 5 minutes. It should be refreshed 6 times (30 minutes) and no more. In another question I made, I got a link ( Robust auto-refresh web page ) where a reply from member Reboot has a code I think could be changed to be used as I need. Is it possible to change that code in order to re-load the web page, automatically, for a fixed number of times? If so, how to do it?
This uses sessionStorage to save the number of reloads which should work in IE8+ except for Opera Mini. If this is a problem, set cookies instead (but then the client has to accept cookies).
Tweak maxReloads and pollIntervalSecs to your liking.
<script>
var pollIntervalId;
var pollIntervalSecs = 6;
var maxReloads = 3;
var doReload = function(){
var reloads = sessionStorage.getItem("reloads");
if (!reloads) sessionStorage.setItem("reloads", 0);
reloads++;
if(reloads > maxReloads) {
window.clearInterval(pollIntervalId);
} else {
sessionStorage.setItem("reloads", reloads);
document.location.reload(true);
}
}
pollIntervalId = setInterval(doReload, pollIntervalSecs * 1000);
</script>
I have an app that uses RavenDB. It has a WPF front-end GUI app. I would like for that app to be notified of certain types of new documents. For example, if my app loads the most recent 50 Foos for display, and someone else adds 10 more Foos later, I would like the app to know about these new 10 and update the UI.
I could poll the DB every few seconds to check for new documents, but it would be nice to have a real-time, two-way call-back notification from RavenDB. Does this functionality exist?
My searches have ended with smuggler and listeners, but I don't know that either is intended for this purpose.
RavenDB V2 will support push notifications:
store.Changes()
.ForDocument("users/1")
.Subscribe(notification => {
using(var session = store.OpenSession())
{
var user = session.Load<User>(notification.Name);
Console.WriteLine("Wow! " + notification.Name + " changed. New name: " + user.Name);
}
});
I've been trying to send data from my background page to a content script in my chrome extension. i can't seem to get it to work. I've read a few posts online but they're not really clear and seem quite high level. I've got managed to get the oauth working using the Oauth contacts example on the Chrome samples. The authentication works, i can get the data and display it in an html page by opening a new tab.
I want to send this data to a content script.
i'm having a lot of trouble with this and would really appreciate if someone could outline the explicit steps you need to follow to send data from a bg page to a content script or even better some code. Any takers?
the code for my background page is below (i've excluded the oauth paramaeters and other )
` function onContacts(text, xhr) {
contacts = [];
var data = JSON.parse(text);
var realdata = data.contacts;
for (var i = 0, person; person = realdata.person[i]; i++) {
var contact = {
'name' : person['name'],
'emails' : person['email']
};
contacts.push(contact); //this array "contacts" is read by the
contacts.html page when opened in a new tab
}
chrome.tabs.create({ 'url' : 'contacts.html'}); sending data to new tab
//chrome.tabs.executeScript(null,{file: "contentscript.js"});
may be this may work?
};
function getContacts() {
oauth.authorize(function() {
console.log("on authorize");
setIcon();
var url = "http://mydataurl/";
oauth.sendSignedRequest(url, onContacts);
});
};
chrome.browserAction.onClicked.addListener(getContacts);`
As i'm not quite sure how to get the data into the content script i wont bother posting the multiple versions of my failed content scripts. if I could just get a sample on how to request the "contacts" array from my content script, and how to send the data from the bg page, that would be great!
You have two options getting the data into the content script:
Using Tab API:
http://code.google.com/chrome/extensions/tabs.html#method-executeScript
Using Messaging:
http://code.google.com/chrome/extensions/messaging.html
Using Tab API
I usually use this approach when my extension will just be used once in a while, for example, setting the image as my desktop wallpaper. People don't set a wallpaper every second, or every minute. They usually do it once a week or even day. So I just inject a content script to that page. It is pretty easy to do so, you can either do it by file or code as explained in the documentation:
chrome.tabs.executeScript(tab.id, {file: 'inject_this.js'}, function() {
console.log('Successfully injected script into the page');
});
Using Messaging
If you are constantly need information from your websites, it would be better to use messaging. There are two types of messaging, Long-lived and Single-requests. Your content script (that you define in the manifest) can listen for extension requests:
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.method == 'ping')
sendResponse({ data: 'pong' });
else
sendResponse({});
});
And your background page could send a message to that content script through messaging. As shown below, it will get the currently selected tab and send a request to that page.
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {method: 'ping'}, function(response) {
console.log(response.data);
});
});
Depends on your extension which method to use. I have used both. For an extension that will be used like every second, every time, I use Messaging (Long-Lived). For an extension that will not be used every time, then you don't need the content script in every single page, you can just use the Tab API executeScript because it will just inject a content script whenever you need to.
Hope that helps! Do a search on Stackoverflow, there are many answers to content scripts and background pages.
To follow on Mohamed's point.
If you want to pass data from the background script to the content script at initialisation, you can generate another simple script that contains only JSON and execute it beforehand.
Is that what you are looking for?
Otherwise, you will need to use the message passing interface
In the background page:
// Subscribe to onVisited event, so that injectSite() is called once at every pageload.
chrome.history.onVisited.addListener(injectSite);
function injectSite(data) {
// get custom configuration for this URL in the background page.
var site_conf = getSiteConfiguration(data.url);
if (site_conf)
{
chrome.tabs.executeScript({ code: 'PARAMS = ' + JSON.stringify(site_conf) + ';' });
chrome.tabs.executeScript({ file: 'site_injection.js' });
}
}
In the content script page (site_injection.js)
// read config directly from background
console.log(PARAM.whatever);
I thought I'd update this answer for current and future readers.
According to the Chrome API, chrome.extension.onRequest is "[d]eprecated since Chrome 33. Please use runtime.onMessage."
See this tutorial from the Chrome API for code examples on the messaging API.
Also, there are similar (newer) SO posts, such as this one, which are more relevant for the time being.