I'm experiencing an issue that I've tried different ways to resolve and have been unsuccessful with. Whenever receiving a message via CrossFirebasePushNotification.Current.OnNotificationReceived I get the payload and can read it, but I can't do anything "visual" in my app. In other words, I get the notification but when I want to either redirect to another page or even display a DisplayAlert message, nothing happens. MessagingCenter can be received, but any instructions within the procedure that have to do with redirecting or DisplayAlert (anything changing the UI it appears) will not be executed.
Looking for help in how to visually show in the app the user has received a message.
This is in MainShell.xaml.cs (I've also placed it in App.xaml.cs too):
CrossFirebasePushNotification.Current.OnNotificationReceived += (s, p) =>
{
System.Diagnostics.Debug.WriteLine("Received"); // this works
foreach (var data in p.Data)
{
System.Diagnostics.Debug.WriteLine($"{data.Key} : {data.Value}"); // this works
}
//TODO: Code to determine if user is signed in
if (true)
{
System.Diagnostics.Debug.WriteLine("Debug: Goto Registration page from MainShell"); // this works
//Task.Run(async () => await Shell.Current.GoToAsync("registration")); // this does not work (just ignores it and doesn't fire constructor)
//Task.Run(async () => await Current.DisplayAlert("Request Received", "A message is waiting...", "Ok")); // this does not work
MessagingCenter.Send(this, "RequestReceived"); // this works, the receiver will display debug info, but will not redirect nor display any UI messages or interact with the UI.
}
};
Thank you for any help or guidance,
Robert
I want to do a very simple thing: if a person goes to a specific page within my webview I want them to be redirected to a different page. I want to do this to prevent an errorpage from showing on session timeout. So this needs to happen from within Xamarin because I have to resend the user credentials.
To do that, I believe I have to catch the Navigating event, check if the webpage corresponds with the page I don't want to see. Cancel the Navigating event and set the browser URL to the page I want to redirect to.
private void Navigating(object sender, WebNavigatingEventArgs e)
{
String url = e.Url;
if (url.Contains("unauthenticated.xhtml"))
{
url = getURL();
e.Cancel = true;
browser.Source = url;
} else
{
e.Cancel = false;
}
LogService.log("navigating to " + url);
}
This doesn't work. I still get to see the ugly unauthenticated.xhtml page and no redirect. If I debug I run through the code correctly so I know the event is always caught well and the check for the website works. If I got to the new url in the browser the correct page is displayed.
Now, if I remove this line
e.Cancel = true;
I get closer to the result I want. Then I do get redirected to unauthenticated.xhtml, but within a second I am redirected again towards the correct page. So the warning flashes on the screen and disappears. (Makes sense: both Navigation events still go through)
I have also tried placing these two lines in this order:
browser.Source = url;
e.Cancel = true;
But the result didn't change.
How can I get a well working redirection from within the program?
Thank you for your help.
I have SAPUI5 application where I am using Shell. I have different views in my Shell and I am able to navigate from one view to another. The problem is that I don't know how can I create or change URL adress to each view. I need to set URL adresses to be able to use "back" button in a browser. I want to add unique URL adress to each view inside my Shell to use "back" and "forward" buttons.
Thanks!
Take a look at this simple sap.ui.core.routing.Router example it shows how to easily set up and use routes and a hash changer with an app Shell container.
sap.ui.core.routing is a javascript routes utilty, it handles URL changes and dispatches control based on pattern logic to views and event handlers, part of routing is HashChanger and History functionality.
if you are using the desktop shell this routing example with sap.ui.ux3.Shell
A lot of examples use jQuery.sap.history.js IMO it doesn't properly support bookmarks and has limited features which means you have to use it with other techniques
Unfortunately, History API presents in modern browsers only. For IE6+ I recommend you to use "hashchange" event of window:
function router(){
var sViewName = window.location.hash.slice(1),
oView = sap.ui.getCore().byId(sViewName) || new sap.ui.view.XMLView({id : sViewName, viewName : sViewName});
sap.ui.getCore().byId("uxShell").setContent(oView);
return false;
}
if("onhashchange" in window){
if(window.attachEvent){ //IE8
attachEvent('onhashchange', router);
} else if(window.addEventListener){ //IE9+, Chrome, Opera, Firefox
addEventListener('hashchange', router);
}
} else { //IE6-7
var oldHref = window.location.hash;
setInterval(function(){
var newHref = window.location.hash;
if(oldHref !== newHref){
oldHref = newHref;
router();
}
}, 100);
}
But to make it work you need to set href property to navigation items like this: #catalog.viewName
I have an application that uses a combination of the onhashchange event (for new browsers) and the hashchange plugin by Ben Alman (for old browsers) to track the history while making ajax calls or actions. Works like a charm in all browsers, back and forward buttons let the user navigate the actions that get recorded by changing the hash. So far so good. Now our page will be hosted in an iframe on a clients page in a diff domain(cross domain). Chrome kind of works but if you put to many changes in the history it stops working at some point (we can live with that). IE dosen't work at all. When I navigate our application by clicking on links and updating the hash new history items get created in the parent page but when I hit the back button the hash in the nested page is not updated therefore the hashchange event never fires. Anyone solved this problem before? Many thanks
Initialize the hash change event handling
if ("onhashchange" in window && !($j.browser.msie && $j.browser.version == '7.0')) {
window.onhashchange = function() {
var params = parseHash(location.hash)
if (params.tabId) {
if (getSelectedTabId() == params.tabId) return;
reloadPage(params.tabId);
}
};
}
else {// Plugin for older browsers
$j(window).bind('hashchange', function() {
var params = parseHash(location.hash)
if (params.tabId) {
if (getSelectedTabId() == params.tabId) return;
reloadPage(params.tabId);
}
});
}
I have protocol (like http) with scheme managed with 3rd party App registered in Mac OS X.
I.e, x-someapp://someaction or something like that.
How can I open this URL with Google Chrome?
By default, Chrome starts searching in Google engine instead launching App and passing URL handling to it...
Safari launches some registered App. And it is right thing.
Firefox and Opera asks what to do... and I can launch App also.
But Chrome... Doesn't ask.
I even tried to write some HTML page with JavaScript inside to send XHttpRequest:
function _httpExecuteCallback()
{
if (httpRequestCallbackFunction != null) {
if (httpRequest.readyState == 4) {
if (httpRequest.status == 200) {
httpRequestCallbackFunction();
httpRequestCallbackFunction = null;
}
}
}
}
function _httpGet(url, callbackFunction)
{
httpRequest = false;
httpRequestCallbackFunction = callbackFunction;
httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = _httpExecuteCallback;
httpRequest.open('GET', url, true);
httpRequest.send(null);
}
_httpGet('x-someapp://test',function(){})
No results also...
The current accepted solution has a problem with Chrome for SSL https. Watching the console log, Chrome blocks the request because it thinks the custom url protocol is not secure:
[blocked] The page at reports blah blah ran insecure content from customproto//blah blah
Here is a solution (this took me a few days to research):
<input type='button' value='Test Custom Url' onclick='exec()'>
<script>
function submitRequest(buttonId) {
var d = (window.parent)?window.parent.document:window.document
if (d.getElementById(buttonId) == null || d.getElementById(buttonId) == undefined) return;
if (d.getElementById(buttonId).dispatchEvent) {
var e = d.createEvent("MouseEvents");
e.initEvent("click", true, true);
d.getElementById(buttonId).dispatchEvent(e);
}
else {
d.getElementById(buttonId).click();
}
}
function exec(){
var d = (window.parent)?window.parent.document:window.document
var f = d.getElementById('customUrlLink')
if (f ) {f.parentNode.removeChild(f);}
var a = d.createElement('a');
a.href = 'mycustomproto://arg1';
a.innerHTML = "Link"
a.setAttribute('id', 'customUrlLink');
a.setAttribute("style", "display:none; ");
d.body.appendChild(a);
submitRequest("customUrlLink");
}
</script>
This code will not work for IE. I've found using this technique IE limits the argument of the custom protocol to less than 1000 where as using the iFrame technique IE will allow 2083 chars.
The only way to overcome the url limit in javascript is chuck the data and call multiple times. If anyone wants to take a stab at that, please let me know how it goes. I would like to use it.
To handle long urls in the executing app, pass a token into the app and have it go get the data from a url GET.
So for right now I am using one function for Chrome/FF and another function for IE.
These links helped me develop this solution:
https://superuser.com/questions/655405/custom-protocol-handler-not-working-in-chrome-on-ssl-page
Simulating a click in jQuery/JavaScript on a link
(wish I had known this a few days ago....hope this helps someone)
==================================================
Update: (8hr later)
==================================================
Jake posted a great solution for chrome: https://superuser.com/questions/655405/custom-protocol-handler-not-working-in-chrome-on-ssl-page
This works in chrome only:
window.location.assign("customprotocol://");
It will fail in an iframe so this is working:
var w = (window.parent)?window.parent:window
w.location.assign(service + '://' + data)
==================================================
Update: (weeks later)
==================================================
All of the examples of opening the custom protocol, including my own, have a "://" in the url. And this is what is causing the SSL warnings.
Turns out the solution is to change "://" to ":"
so do this:
src="x-myproto:query" .....
and the SSL warnings will go away.
==================================================
Follow: (after months of production use)
==================================================
This has been working well for chorme. Detect the browser and if chrome do this:
var w = (window.parent)?window.parent:window
w.location.assign('myproto://xyzabcdefetc')
For IE and other browsers I do something slightly different.
Note that browsers do impose a limit on how much data you can put in custom url protocol. As long as your string is under 800 chars this seems to be the magic number for which works in all browsers.
It looks like it's Google's locationbar parsing which is getting in the way.
The browser, however, does seem to handle custom URL schemes properly. Try this in your locationbar:
javascript:document.location = 'myscheme://whatever'
Any link on your page that uses the custom scheme should also do the right thing.
I found the solution that works with Chrome.
I use the IFRAME-way.
Example (with JQuery):
$("body").append('<span id="__protoProxy"></span>');
function queryWord(aWord)
{
var protoProxy = document.getElementById('__protoProxy');
if (protoProxy)
{
var word = aWord.replace('"','\"');
protoProxy.innerHTML = '<div style="display:none;"><iframe src="x-myproto://query?' + word + '"></iframe></div>';
}
}
queryWord('hello');
Here's a solution that also includes a redirect to the App Store / Play Store if the user doesn't have the app. It uses a setTimeout for this. It also makes use of an iframe to support more browsers. So this works on Chrome, and any other mobile browser. We use this as my company, Branch. Just modify the two links below to correspond to your URI and App Store link.
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
window.onload = function() {
// Deep link to your app goes here
document.getElementById("l").src = "my_app://somepath";
setTimeout(function() {
// Link to the App Store should go here -- only fires if deep link fails
window.location = "https://itunes.apple.com/us/app/myapp/id123456789?ls=1&mt=8";
}, 500);
};
</script>
<iframe id="l" width="1" height="1" style="visibility:hidden"></iframe>
</body>
</html>
Again, this should work on any browser, thanks to the iframe.
If Chrome does not recognize the URL scheme, it defaults to a search.
This is what I see in Safari:
alt text http://img62.imageshack.us/img62/6792/clipboard02oh.jpg
and in Firefox:
alt text http://img138.imageshack.us/img138/9986/clipboard04xk.jpg
I believe the reason why Chrome defaults to search is that there are special google searches that use the colon.
E.g:
define: dictionary
filetype:pdf google chromium
This is one of the annoyances I have with Firefox, I have to jump to the "search box" rather than the address bar to execute these types of searches. Since Chrome does not have a separate search box like Firefox, IE and Safari have, this functionality is required.
Ajax requests won't get you around this.
Some weeks later ....
Looks like window.location.replace('myscheme://whatever') has full cross-browser support , works with chrome,firefox,safari,edge,opera see https://developer.mozilla.org/en-US/docs/Web/API/Location/replace