I'm trying to send a message to my custom receiver for ChromeCast. I use the following code in my Android app to send a code to the receiver;
Cast.CastApi.sendMessage(mApiClient, "urn:x-cast:move", "TEST");
On the receiving side I have the following code;
window.mediaElement = document.getElementById('media');
window.mediaManager = new cast.receiver.MediaManager(window.mediaElement);
window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
window.castReceiverManager.start();
window.castReceiverManager.onSenderConnected = function(event) {
//This is called
}
window.customMessageBus = window.castReceiverManager.getCastMessageBus('urn:x-cast:move', cast.receiver.CastMessageBus.MessageType.STRING);
var defaultFunction = window.customMessageBus.onMessage;
window.customMessageBus.onMessage = function(event) {
//This is not called
defaultFunction(event);
};
As I pointed out in the code, the 'onSenderConnected' is called, so I know it connected to the app. But when I try to send a message over the custom messagebus, it doesnt give me anything. I'm completely new to android and cast, so I could be doing a thousand things wrong. Can anybody help me solve this?
I solved it myself. What I did wrong was starting the castReceiverManager before adding the custom namespace. So the correct code for the receiver compared to what I posted in the question would be;
window.mediaElement = document.getElementById('media');
window.mediaManager = new cast.receiver.MediaManager(window.mediaElement);
window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
//Removed the start here
window.castReceiverManager.onSenderConnected = function(event) {
//OnConnect
}
window.customMessageBus = window.castReceiverManager.getCastMessageBus('urn:x-cast:move', cast.receiver.CastMessageBus.MessageType.STRING);
var defaultFunction = window.customMessageBus.onMessage;
window.customMessageBus.onMessage = function(event) {
//OnMessage
defaultFunction(event);
};
//Start at the end
window.castReceiverManager.start();
Related
I am using Google Cloud Channels in Android's WebView, but the same problem probably occurs as well when using any socket in a similar way.
Problem: The argument is not passed on by the handler, possibly because functions are called in a different scope.
Here is my code:
<html>
<head>
<script src='{{ channelurl }}jsapi'></script>
</head>
<body>
<script type="text/javascript">
onMessage = function(message) {
};
var token = '{{ token }}';
var channel = new goog.appengine.Channel(token);
var handler = {
'onmessage': onMessage,
};
var socket = channel.open(handler);
socket.onmessage = onMessage;
</script>
</body>
</html>
onMessage has a single argument (string) and my onMessage function is properly called, but the argument is 'undefined', probably because it is in a different scope.
This question might be a duplicate of these or other similar questions, and I tried to apply the recipes given there, but no success.
How do I pass arguments to an event handler?
How to pass event as argument to an inline event handler in JavaScript?
I actually applied the code from here
http://2cor214.blogspot.com/2010/08/passing-arguments-to-event-handler-in.html
and tried to play with things like this:
socket.onmessage = (function (message) {return onMessage})(message)
in many variants, but couldn't get it to work.
I admit I am not normally developing JavaScript and I don't exactly understand what JavaScript does here, but it seems to me that the argument needs to be extracted the function wrapped somehow.
Can anybody shed light please.
--
I removed parts of my code for brevity.
The problem was not a JavaScript issue, as I assumed. The assumption that the same issue would occur with any socket type was also incorrect.
The problem had to do with how Google Cloud Channels hands over the message in onMessage().
As I could see from code that Google posted for their Tic Tac Toe example here http://code.google.com/p/channel-tac-toe/source/browse/trunk/index.html, line 175ff, they hand over the string as an event with the variable "data", but called the argument "m" (as in message).
onOpened = function() {
sendMessage('/opened');
};
onMessage = function(m) {
newState = JSON.parse(m.data);
state.board = newState.board || state.board;
state.userX = newState.userX || state.userX;
state.userO = newState.userO || state.userO;
state.moveX = newState.moveX;
state.winner = newState.winner || "";
state.winningBoard = newState.winningBoard || "";
updateGame();
}
openChannel = function() {
var token = '{{ token }}';
var channel = new goog.appengine.Channel(token);
var handler = {
'onopen': onOpened,
'onmessage': onMessage,
'onerror': function() {},
'onclose': function() {}
};
var socket = channel.open(handler);
socket.onopen = onOpened;
socket.onmessage = onMessage;
}
Kind of confusing and undocumented here https://cloud.google.com/appengine/docs/java/channel/?csw=1 and here https://cloud.google.com/appengine/docs/java/channel/javascript, but when I changed the message signature to
onMessage = function(message) {
ChannelListener.onMessage(message.data); // message
};
it worked perfectly fine.
I don't know if I'm right or wrong. But as I know I can't create a version change transaction manually. The only way to invoke this is by changing the version number when opening the indexed DB connection. If this is correct, in example1 and example2 new objectStore will never be created?
Example1
function createObjectStore(name){
var request2 = indexedDB.open("existingDB");
request2.onupgradeneeded = function() {
var db = request2.result;
var store = db.createObjectStore(name);
};
}
Example2
function createObjectStore(name){
var request2 = indexedDB.open("existingDB");
request2.onsuccess = function() {
var db = request2.result;
var store = db.createObjectStore(name);
};
}
Example3 - This should work:
function createObjectStore(name){
var request2 = indexedDB.open("existingDB", 2);
request2.onupgradeneeded = function() {
var db = request2.result;
var store = db.createObjectStore(name);
};
}
If I want to create multiple objectStore's in one database how can I get/fetch database version before opening the database??
So is there a way to automate this process of getting database version number??
Is there any other way to create objectStore other than that using onupgradeneeded event handler.
Please help. Thanks a lot.
Edit:
Here is same problem that I have:
https://groups.google.com/a/chromium.org/forum/#!topic/chromium-html5/0rfvwVdSlAs
You need to open the database to check it's current version and open it again with version + 1 to trigger the upgrade.
Here is the sample code:
function CreateObjectStore(dbName, storeName) {
var request = indexedDB.open(dbName);
request.onsuccess = function (e){
var database = e.target.result;
var version = parseInt(database.version);
database.close();
var secondRequest = indexedDB.open(dbName, version+1);
secondRequest.onupgradeneeded = function (e) {
var database = e.target.result;
var objectStore = database.createObjectStore(storeName, {
keyPath: 'id'
});
};
secondRequest.onsuccess = function (e) {
e.target.result.close();
}
}
}
The only way you can create an object store is in the onupgradeneeded event. You need a version_change transaction to be able to change the schema. And the only way of getting a version_change transaction is through a onupgradeneeded event.
The only way to trigger the onupgradeneeded event is by opening the database in a higher version than the current version of the database. The best way to do this is keeping a constant with the current version of the database you need to work with. Every time you need to change the schema of the database you increase this number. Then in the onupgradeneeded event, you can retrieve the current version of the database. With this, you can decide which upgrade path you need to follow to get to the latest database schema.
I hope this answers your question.
I'm writing a restartless Firefoxextension where I have to enumerate all open tabs and work with them.
Here's the code-part that throws the error:
getInfoString : function ()
{
infos = "";
HELPER.alerting("url", "URL-Function");
var winMediator = Components.classes["#mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
HELPER.alerting("url", "Mediator initialized");
var mrw = winMediator.getEnumerator(null);
while(mrw.hasMoreElements())
{
var win = mrw.getNext();
var t = win.gBrowser.browsers.length;
HELPER.alerting("url", "browsers: " + t);
for (var i = 0; i < t; i++)
{
var b = win.gBrowser.getBrowserAtIndex(i);
if(b.currentURI.spec.substr(0,3) != "http")
{
continue;
}
HELPER.alerting(b.title,b.currentURI.spec);
var doc = b.contentDocument;
var src = doc.documentElement.innerHTML;
infos = infos + src
HELPER.alerting("doc", src);
}
}
return infos;
}
I have a JavascriptDebugger-Addon running while testing this and Firefox executes everything fine to the line
HELPER.alerting("url", "browsers: " + t);
But AFTER this line, the debugger-addons throws an error, saying that:
win.gBrowser is undefined
... pointing to the line:
var t = win.gBrowser.browsers.length;
But before it throws the error I get my alertmessage which gives me the correct number of tabs. So the error is thrown after the line was executed and not directly WHEN it was executed.
Does anyone has an idea how to fix this, because the extension stops working after the error has been thrown.
Greetz
P.S.: If someone has a better headline for this, feel free to edit it.
Using winMediator.getEnumerator(null) would give you all types of window, that may or may not be browser windows. You should try changing the following line
var mrw = winMediator.getEnumerator(null);
with
var mrw = winMediator.getEnumerator('navigator:browser');
I finally figured out that this behavior can happen sometimes.
I just rearranged the code a bit, removing some alerts inside the for-loop and it works just fine again.
So if someone has this error too, just rearrange your code and it should work like a charm again.
I have a Windows app that contains a browser control that loads pages from my website. However, due to the Windows app, I cannot debug Javascript in the usual ways (Firebug, console, alerts, etc).
I was hoping to write a jQuery plug-in to log to an external browser window such that I can simply do something like:
$.log('test');
So far, with the following, I am able to create the window and display the templateContent, but cannot write messages to it:
var consoleWindow;
function getConsoleWindow() {
if (typeof (consoleWindow) === 'undefined') {
consoleWindow = createConsoleWindow();
}
return consoleWindow;
}
function createConsoleWindow() {
var newConsoleWindow = window.open('consoleLog', '', 'status,height=200,width=300');
var templateContent = '<html><head><title>Console</title></head>' +
'<body><h1>Console</h1><div id="console">' +
'<span id="consoleText"></span></div></body></html>';
newConsoleWindow.document.write(templateContent);
newConsoleWindow.document.close();
return newConsoleWindow;
}
function writeToConsole(message) {
var console = getConsoleWindow();
var consoleDoc = console.document.open();
var consoleMessage = document.createElement('span');
consoleMessage.innerHTML = message;
consoleDoc.getElementById('consoleText').appendChild(consoleMessage);
consoleDoc.close();
}
jQuery.log = function (message) {
if (window.console) {
console.log(message);
} else {
writeToConsole(message);
}
};
Currently, getElementById('consoleText') is failing. Is what I'm after possible, and if so, what am I missing?
Try adding
consoleDoc.getElementById('consoleText');
right before
consoleDoc.getElementById('consoleText').appendChild(consoleMessage);
If the line you added is the one that fails, then that means consoleDoc is not right, if the next line is the only one that fails then ..ById('consoleText') is not matching up
If I don't close() the document, it appears to work as I hoped.
I'm initiating an email create, by calling the code below, and adding an attachment to it.
I want the user to be able to type in the receipient, and modify the contents of the message, so I'm not sending it immediately.
Why do I get a RangeError the 2nd time the method is called?
(The first time it works correctly.)
function NewMailItem(p_recipient, p_subject, p_body, p_file, p_attachmentname)
{
try
{
var objO = new ActiveXObject('Outlook.Application');
var objNS = objO.GetNameSpace('MAPI');
var mItm = objO.CreateItem(0);
mItm.Display();
if (p_recipient.length > 0)
{
mItm.To = p_recipient;
}
mItm.Subject = p_subject;
if (p_file.length > 0)
{
var mAts = mItm.Attachments;
mAts.add(p_file, 1, p_body.length + 1, p_attachmentname);
}
mItm.Body = p_body;
mItm.GetInspector.WindowState = 2;
} catch(e)
{
alert('unable to create new mail item');
}
}
The error is occuring on the mAts.add line. So when it tries to attach the document, it fails.
Also the file name (p_file) is a http address to a image.
Won't work outside of IE, the user needs to have Outlook on the machine and an account configured on it. Are you sure you want to send an email this way?
I'm trying it with this little snippet, and it works flawlessly:
var objO = new ActiveXObject('Outlook.Application');
var mItm = objO.CreateItem(0);
var mAts = mItm.Attachments;
var p_file = [
"http://stackoverflow.com/content/img/vote-arrow-up.png",
"http://stackoverflow.com/content/img/vote-arrow-down.png"
];
for (var i = 0; i < p_file.length; i++) {
mAts.add(p_file[i]);
}
Note that I left off all optional arguments to Attachments.Add(). The method defaults to adding the attachments at the end, which is what you seem to want anyway.
Can you try this standalone snippet? If it works for you, please do a step-by-step reduction of your code towards this absolute minimum, and you will find what causes the error.
first do mItm.display()
then write mItm.GetInspector.WindowState = 2;
this will work