-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cannot sendMessage() to cast URL #78
Comments
I'm not totally sure, but you can try pasting the code below to the console. It should ask you to choose a chromecast, then open example.com on your chromecast. (worked for me on android). This is just a slight modification of example.js from the home page. (I have marked the parts I changed with One note, it looks like the DeMilla stuff relies on custom messages. The client-side document.addEventListener("deviceready", function () {
// Must wait for deviceready before using chromecast
// File globals
var _session;
var _media;
initialize();
function initialize () {
// use default app id
/* DeMille START1 */
var appId = "5CB45E5A"; // --> You have to use DeMille's app id to send messages to their receiver
// var appId = chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID;
/* DeMille END1 */
var apiConfig = new chrome.cast.ApiConfig(new chrome.cast.SessionRequest(appId), function sessionListener (session) {
// The session listener is only called under the following conditions:
// * will be called shortly chrome.cast.initialize is run
// * if the device is already connected to a cast session
// Basically, this is what allows you to re-use the same cast session
// across different pages and after app restarts
}, function receiverListener (receiverAvailable) {
// receiverAvailable is a boolean.
// True = at least one chromecast device is available
// False = No chromecast devices available
// You can use this to determine if you want to show your chromecast icon
});
// initialize chromecast, this must be done before using other chromecast features
chrome.cast.initialize(apiConfig, function () {
// Initialize complete
// Let's start casting
requestSession();
}, function (err) {
// Initialize failure
});
}
function requestSession () {
// This will open a native dialog that will let
// the user choose a chromecast to connect to
// (Or will let you disconnect if you are already connected)
chrome.cast.requestSession(function (session) {
// Got a session!
_session = session;
/* DeMille START2 */
var namespace = 'urn:x-cast:com.url.cast';
var msg = {
"type": "loc",
"url": "http://example.com"
}
session.sendMessage(namespace, msg, onSuccess, onErr);
// Load a video
//loadMedia();
/* DeMille END2 */
}, function (err) {
// Failed, or if err is cancel, the dialog closed
});
}
function loadMedia () {
var videoUrl = 'https://ia801302.us.archive.org/1/items/TheWater_201510/TheWater.mp4';
var mediaInfo = new chrome.cast.media.MediaInfo(videoUrl, 'video/mp4');
_session.loadMedia(new chrome.cast.media.LoadRequest(mediaInfo), function (media) {
// You should see the video playing now!
// Got media!
_media = media;
// Wait a couple seconds
setTimeout(function () {
// Lets pause the media
pauseMedia();
}, 4000);
}, function (err) {
// Failed (check that the video works in your browser)
});
}
function pauseMedia () {
_media.pause({}, function () {
// Success
// Wait a couple seconds
setTimeout(function () {
// stop the session
stopSession();
}, 2000)
}, function (err) {
// Fail
});
}
function stopSession () {
// Also stop the session (if )
_session.stop(function () {
// Success
}, function (err) {
// Fail
});
}
}); |
Hi Lindsay, thanks for your great answer! In my previous attempts I did exactly what you wrote in your code, but I got the error on the namespace. I was testing on iOS. I will try again on Android where you had a working experience, but right now I am experiencing build issues (not related to this plugin) so it is taking me some more time to provide feedback. I will do come back here as soon as I will be able to test on Android platform. |
Hello Lindsay! I managed to test on Android, and it worked at the first time with the same code of iOS... there must be some trouble with sendMessage() method in iOS implementation only. More specifically, the error I get "Namespace not founded, undefined", only appears into this piece of code in MLPChromecastSession.m (ios folder):
I am not expert in Swift at all, but I believe that this means that "channel" variable is "nil", so the pluginResult keeps that value. Do you have any idea why this is not working as expected? |
@enricodente Sorry for the slow reply (I didn't notice the notification >.<) I kind of suspected that the problem might be the incomplete/untested implementation. >.< (Just a side note, the ios implementation is written in obj-c, just incase you try to google anything) I don't have this project setup for development atm, so everything I am saying is just based on looking at the code. (so accuracy might be low xD) Probably the easiest way to find out what is wrong (if you have xcode):
Honestly, I'm not an obj-c expert either, but my guess is that the problem line is indeed: GCKGenericChannel* channel = self.genericChannels[namespace]; I'm guessing this channel doesn't exist in the "genereicChannels" (whatever they are), and maybe we need to make a call to - (void)createMessageChannelWithCommand:(CDVInvokedUrlCommand*)command namespace:(NSString*)namespace{
GCKGenericChannel* newChannel = [self getMessageChannel:namespace];
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
- (GCKGenericChannel*)getMessageChannel:(NSString*)namespace{
GCKGenericChannel* channel = self.genericChannels[namespace];
if (channel != nil) {
return channel;
}
GCKGenericChannel* newChannel = [[GCKGenericChannel alloc] initWithNamespace:namespace];
newChannel.delegate = self;
self.genericChannels[namespace] = newChannel;
[currentSession addChannel:newChannel];
return newChannel;
}
- (void)sendMessageWithCommand:(CDVInvokedUrlCommand*)command namespace:(NSString*)namespace message:(NSString*)message {
GCKGenericChannel* channel = [self getMessageChannel:namespace];
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[NSString stringWithFormat:@"Namespace %@ not founded",namespace]];
if (channel != nil) {
GCKError* error = nil;
[channel sendTextMessage:message error:&error];
if (error != nil) {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error.description];
} else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
}
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
Let me know how it goes! |
Hi Lindsay, I kind of solved the issue, and I believe we came up with a similar solution. Yours looks better in terms of implementation, mine is more of an hack, but I confirm I tested it yesterday and it works:
If you confirm your solution is cleaner and would be worth a PR, I can try to implement it your way, test it to be working, and create a PR. Can you approve PRs on this repository, or should I do it on miloproductionsinc's? |
I am glad to hear you got it to work! (Nice job!) It looks like we were effectively doing the same thing! The only difference is the solution I wrote caches that channel instead of creating it each time. I think if this works, it might be slightly better. (Not sure if maybe you actually need to create the channel each time or not though :p) I'm not sure if I can approve PR's here. I was given some permissions... I know for sure I can't approve my own PR. :p For sure, you should definitely branch off of I think more people find this repo first though. So maybe you can submit to both? If I can approve your PR on Jellyfin then that will update this repo too which would be good for everyone else. If not, I will definitely accept it on miloproductionsinc! |
Hello and thanks for this amazing plugin.
I have set it up and got the example with the video and pause/stop working in few minutes.
Unfortunately, that is not the use I would like to achieve: I would need to open a remote URL on the screen. I have found this project that uses Chromecast APIs and works like a charm on their web-example using Chrome browser:
Project: https://github.com/DeMille/url-cast-receiver
Example: https://demille.github.io/url-cast-receiver/
Basically, I would like to achieve that using this plugin.
I have tried to adapt their implementation inside my test cordova app, but I always get issues when calling the requestSession method: the error callback gets triggered, and the error I get is: "namespace 'urn:x-cast:com.url.cast' not founded unverified"
I have tried both using the recommended App ID and namespace from the project, and also tried using one generated by me, but always get that error. After that, it looks like I can no longer close the session, not even force closing the app, so the only way to be able to scan again my Chromecast TV is to uninstall the app and re-install again, but I believe this is only a side effect of the main issue.
Thanks for any hint!
The text was updated successfully, but these errors were encountered: