Windows Phone 8 Receiving raw Push Notification issue - windows-phone-8

I am unable to receive raw notification on my WindowsPhone8.
Followed :https://github.com/barryvdh/PushPlugin/#uccb-wp8-only
Able to get toast notification. In my app toggle is happening like below.
Case 1: If I comment ecb able to get both raw and toast but not
channel uri.
Case 2: If I won't comment ecb able to get toast and channel uri but
not raw
My code as follows:
if (device.platform == "Win32NT") {
console.log("called");
pushNotification.register(
channelHandler,
errorHandler,
{
"channelName": "channelName",
"ecb": onNotificationWP8,
"uccb": channelHandler,
"errcb": jsonErrorHandler
});
}
else {
console.log("not called");
}
}
function channelHandler(event) {
var uri = event.uri;
console.log("UUUUURRRRRRRRRRRIIIIIIIII :" + uri);
}
function errorHandler(e) {
}
function jsonErrorHandler(error) {
$("#app-status-ul").append('<li style="color:red;">error:' + error.code + '</li>');
$("#app-status-ul").append('<li style="color:red;">error:' + error.message + '</li>');
}
function onNotificationWP8(e) {
console.log("notification called");
if (e.type == "toast" && e.jsonContent){
pushNotification.showToastNotification(successHandler, errorHandler,
{
"Title": e.jsonContent["wp:Text1"], "Subtitle": e.jsonContent["wp:Text2"], "NavigationUri": e.jsonContent["wp:Param"]
});
}
if (e.type == "raw" && e.jsonContent) {
alert(e.jsonContent.Body);
}
}
Tried with error and trail methods. Please suggest what might went wrong.

The issue observed does not appear to be related to Worklight at all. From the description and the code snippet, you are bypassing Worklight client SDK and server completely , and using a custom Cordova Push plugin. The custom plugin's working in your application should be analyzed to understand the variance in behaviour.
Since you are not using Worklight Push at all, you can try disabling it and check if this helps your case.
To do this, navigate to the config.xml . This will be located in apps/YourAppName/WindowsPhone8/native/Resources folder.
Look for :
<feature name="Push">
<param name="wp-package" value="Push" />
</feature>
Change this to:
<feature name="Push">
<param name="wp-package" value="Push" />
<param name="onload" value="false" />
</feature>
On the query regarding Worklight API:
There are no Worklight APIs that return Channel URI. When using Worklight SDK for Push, all this is done automatically and hidden from the user. Even with a Push Adapter in place, it is not possible to obtain the channel URI as there no APIs published to obtain this information.

Finally it got solved by adding Coding4Fun.Toolkit.Controls.dll
And some code updation in PushPlugin.cs
using Coding4Fun.Toolkit.Controls;
using System.Windows.Threading;
void PushChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
string msg = string.Empty;
foreach (var item in e.Collection)
{
if (item.Key == "wp:Text1")
{
msg = item.Value;
}
}
MessageBox.Show(msg, "Notification", MessageBoxButton.OK);
});
}
My heart-full thanks to Rajith who helped me to make it happen.

Related

Can a website detect extensions that are installed using Developed Mode? [duplicate]

I am in the process of building a Chrome extension, and for the whole thing to work the way I would like it to, I need an external JavaScript script to be able to detect if a user has my extension installed.
For example: A user installs my plugin, then goes to a website with my script on it. The website detects that my extension is installed and updates the page accordingly.
Is this possible?
Chrome now has the ability to send messages from the website to the extension.
So in the extension background.js (content.js will not work) add something like:
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (request) {
if (request.message) {
if (request.message == "version") {
sendResponse({version: 1.0});
}
}
}
return true;
});
This will then let you make a call from the website:
var hasExtension = false;
chrome.runtime.sendMessage(extensionId, { message: "version" },
function (reply) {
if (reply) {
if (reply.version) {
if (reply.version >= requiredVersion) {
hasExtension = true;
}
}
}
else {
hasExtension = false;
}
});
You can then check the hasExtension variable. The only drawback is the call is asynchronous, so you have to work around that somehow.
Edit:
As mentioned below, you'll need to add an entry to the manifest.json listing the domains that can message your addon. Eg:
"externally_connectable": {
"matches": ["*://localhost/*", "*://your.domain.com/*"]
},
2021 Update:
chrome.runtime.sendMessage will throw the following exception in console if the extension isn't installed or it's disabled.
Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist
To fix this, add this validation inside the sendMessage callback
if (chrome.runtime.lastError) {
// handle error
}
I am sure there is a direct way (calling functions on your extension directly, or by using the JS classes for extensions), but an indirect method (until something better comes along):
Have your Chrome extension look for a specific DIV or other element on your page, with a very specific ID.
For example:
<div id="ExtensionCheck_JamesEggersAwesomeExtension"></div>
Do a getElementById and set the innerHTML to the version number of your extension or something. You can then read the contents of that client-side.
Again though, you should use a direct method if there is one available.
EDIT: Direct method found!!
Use the connection methods found here: https://developer.chrome.com/extensions/extension#global-events
Untested, but you should be able to do...
var myPort=chrome.extension.connect('yourextensionid_qwerqweroijwefoijwef', some_object_to_send_on_connect);
Another method is to expose a web-accessible resource, though this will allow any website to test if your extension is installed.
Suppose your extension's ID is aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, and you add a file (say, a transparent pixel image) as test.png in your extension's files.
Then, you expose this file to the web pages with web_accessible_resources manifest key:
"web_accessible_resources": [
"test.png"
],
In your web page, you can try to load this file by its full URL (in an <img> tag, via XHR, or in any other way):
chrome-extension://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/test.png
If the file loads, then the extension is installed. If there's an error while loading this file, then the extension is not installed.
// Code from https://groups.google.com/a/chromium.org/d/msg/chromium-extensions/8ArcsWMBaM4/2GKwVOZm1qMJ
function detectExtension(extensionId, callback) {
var img;
img = new Image();
img.src = "chrome-extension://" + extensionId + "/test.png";
img.onload = function() {
callback(true);
};
img.onerror = function() {
callback(false);
};
}
Of note: if there is an error while loading this file, said network stack error will appear in the console with no possibility to silence it. When Chromecast used this method, it caused quite a bit of controversy because of this; with the eventual very ugly solution of simply blacklisting very specific errors from Dev Tools altogether by the Chrome team.
Important note: this method will not work in Firefox WebExtensions. Web-accessible resources inherently expose the extension to fingerprinting, since the URL is predictable by knowing the ID. Firefox decided to close that hole by assigning an instance-specific random URL to web accessible resources:
The files will then be available using a URL like:
moz-extension://<random-UUID>/<path/to/resource>
This UUID is randomly generated for every browser instance and is not your extension's ID. This prevents websites from fingerprinting the extensions a user has installed.
However, while the extension can use runtime.getURL() to obtain this address, you can't hard-code it in your website.
I thought I would share my research on this.
I needed to be able to detect if a specific extension was installed for some file:/// links to work.
I came across this article here
This explained a method of getting the manifest.json of an extension.
I adjusted the code a bit and came up with:
function Ext_Detect_NotInstalled(ExtName, ExtID) {
console.log(ExtName + ' Not Installed');
if (divAnnounce.innerHTML != '')
divAnnounce.innerHTML = divAnnounce.innerHTML + "<BR>"
divAnnounce.innerHTML = divAnnounce.innerHTML + 'Page needs ' + ExtName + ' Extension -- to intall the LocalLinks extension click here';
}
function Ext_Detect_Installed(ExtName, ExtID) {
console.log(ExtName + ' Installed');
}
var Ext_Detect = function (ExtName, ExtID) {
var s = document.createElement('script');
s.onload = function () { Ext_Detect_Installed(ExtName, ExtID); };
s.onerror = function () { Ext_Detect_NotInstalled(ExtName, ExtID); };
s.src = 'chrome-extension://' + ExtID + '/manifest.json';
document.body.appendChild(s);
}
var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
if (is_chrome == true) {
window.onload = function () { Ext_Detect('LocalLinks', 'jllpkdkcdjndhggodimiphkghogcpida'); };
}
With this you should be able to use Ext_Detect(ExtensionName,ExtensionID) to detect the installation of any number of extensions.
Another possible solution if you own the website is to use inline installation.
if (chrome.app.isInstalled) {
// extension is installed.
}
I know this an old question but this way was introduced in Chrome 15 and so I thought Id list it for anyone only now looking for an answer.
Here is an other modern approach:
const checkExtension = (id, src, callback) => {
let e = new Image()
e.src = 'chrome-extension://'+ id +'/'+ src
e.onload = () => callback(1), e.onerror = () => callback(0)
}
// "src" must be included to "web_accessible_resources" in manifest.json
checkExtension('gighmmpiobklfepjocnamgkkbiglidom', 'icons/icon24.png', (ok) => {
console.log('AdBlock: %s', ok ? 'installed' : 'not installed')
})
checkExtension('bhlhnicpbhignbdhedgjhgdocnmhomnp', 'images/checkmark-icon.png', (ok) => {
console.log('ColorZilla: %s', ok ? 'installed' : 'not installed')
})
I used the cookie method:
In my manifest.js file I included a content script that only runs on my site:
"content_scripts": [
{
"matches": [
"*://*.mysite.co/*"
],
"js": ["js/mysite.js"],
"run_at": "document_idle"
}
],
in my js/mysite.js I have one line:
document.cookie = "extension_downloaded=True";
and in my index.html page I look for that cookie.
if (document.cookie.indexOf('extension_downloaded') != -1){
document.getElementById('install-btn').style.display = 'none';
}
You could have the extension set a cookie and have your websites JavaScript check if that cookie is present and update accordingly. This and probably most other methods mentioned here could of course be cirvumvented by the user, unless you try and have the extension create custom cookies depending on timestamps etc, and have your application analyze them server side to see if it really is a user with the extension or someone pretending to have it by modifying his cookies.
There's another method shown at this Google Groups post. In short, you could try detecting whether the extension icon loads successfully. This may be helpful if the extension you're checking for isn't your own.
Webpage interacts with extension through background script.
manifest.json:
"background": {
"scripts": ["background.js"],
"persistent": true
},
"externally_connectable": {
"matches": ["*://(domain.ext)/*"]
},
background.js:
chrome.runtime.onMessageExternal.addListener(function(msg, sender, sendResponse) {
if ((msg.action == "id") && (msg.value == id))
{
sendResponse({id : id});
}
});
page.html:
<script>
var id = "some_ext_id";
chrome.runtime.sendMessage(id, {action: "id", value : id}, function(response) {
if(response && (response.id == id)) //extension installed
{
console.log(response);
}
else //extension not installed
{
console.log("Please consider installig extension");
}
});
</script>
Your extension could interact with the website (e.g. changing variables) and your website could detect this.
But there should be a better way to do this. I wonder how Google is doing it on their extension gallery (already installed applications are marked).
Edit:
The gallery use the chrome.management.get function. Example:
chrome.management.get("mblbciejcodpealifnhfjbdlkedplodp", function(a){console.log(a);});
But you can only access the method from pages with the right permissions.
A lot of the answers here so far are Chrome only or incur an HTTP overhead penalty. The solution that we are using is a little different:
1. Add a new object to the manifest content_scripts list like so:
{
"matches": ["https://www.yoursite.com/*"],
"js": [
"install_notifier.js"
],
"run_at": "document_idle"
}
This will allow the code in install_notifier.js to run on that site (if you didn't already have permissions there).
2. Send a message to every site in the manifest key above.
Add something like this to install_notifier.js (note that this is using a closure to keep the variables from being global, but that's not strictly necessary):
// Dispatch a message to every URL that's in the manifest to say that the extension is
// installed. This allows webpages to take action based on the presence of the
// extension and its version. This is only allowed for a small whitelist of
// domains defined in the manifest.
(function () {
let currentVersion = chrome.runtime.getManifest().version;
window.postMessage({
sender: "my-extension",
message_name: "version",
message: currentVersion
}, "*");
})();
Your message could say anything, but it's useful to send the version so you know what you're dealing with. Then...
3. On your website, listen for that message.
Add this to your website somewhere:
window.addEventListener("message", function (event) {
if (event.source == window &&
event.data.sender &&
event.data.sender === "my-extension" &&
event.data.message_name &&
event.data.message_name === "version") {
console.log("Got the message");
}
});
This works in Firefox and Chrome, and doesn't incur HTTP overhead or manipulate the page.
You could also use a cross-browser method what I have used.
Uses the concept of adding a div.
in your content script (whenever the script loads, it should do this)
if ((window.location.href).includes('*myurl/urlregex*')) {
$('html').addClass('ifextension');
}
in your website you assert something like,
if (!($('html').hasClass('ifextension')){}
And throw appropriate message.
If you have control over the Chrome extension, you can try what I did:
// Inside Chrome extension
var div = document.createElement('div');
div.setAttribute('id', 'myapp-extension-installed-div');
document.getElementsByTagName('body')[0].appendChild(div);
And then:
// On web page that needs to detect extension
if ($('#myapp-extension-installed-div').length) {
}
It feels a little hacky, but I couldn't get the other methods to work, and I worry about Chrome changing its API here. It's doubtful this method will stop working any time soon.
If you're trying to detect any extension from any website,
This post helped: https://ide.hey.network/post/5c3b6c7aa7af38479accc0c7
Basically, the solution would be to simply try to get a specific file (manifest.json or an image) from the extension by specifying its path. Here's what I used. Definitely working:
const imgExists = function(_f, _cb) {
const __i = new Image();
__i.onload = function() {
if (typeof _cb === 'function') {
_cb(true);
}
}
__i.onerror = function() {
if (typeof _cb === 'function') {
_cb(false);
}
}
__i.src = _f;
__i = null;
});
try {
imgExists("chrome-extension://${CHROME_XT_ID}/xt_content/assets/logo.png", function(_test) {
console.log(_test ? 'chrome extension installed !' : 'chrome extension not installed..');
ifrm.xt_chrome = _test;
// use that information
});
} catch (e) {
console.log('ERROR', e)
}
Here is how you can detect a specific Extension installed and show a warning message.
First you need to open the manifest file of the extension by going to chrome-extension://extension_id_here_hkdppipefbchgpohn/manifest.json and look for any file name within "web_accessible_resources" section.
<div class="chromewarning" style="display:none">
<script type="text/javascript">
$.get("chrome-extension://extension_id_here_hkdppipefbchgpohn/filename_found_in_ web_accessible_resources.png").done(function () {
$(".chromewarning").show();
}).fail(function () {
// alert("failed.");
});
</script>
<p>We have detected a browser extension that conflicts with learning modules in this course.</p>
</div>
Chrome Extension Manifest v3:
const isFirefox = chrome.runtime.OnInstalledReason.CHROME_UPDATE != "chrome_update";
For FireFox, I believe chrome.runtime.OnInstalledReason.BROWSER_UPDATE will be "browser_update": https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/OnInstalledReason

navigator.clipboard is undefined

Why is navigator.clipboard always undefined in the following snippet?
var clipboard = navigator.clipboard;
if (clipboard == undefined) {
console.log('clipboard is undefined');
} else {
clipboard.writeText('stuff to write').then(function() {
console.log('Copied to clipboard successfully!');
}, function() {
console.error('Unable to write to clipboard. :-(');
});
}
More on the clipboard API can be found here.
Chrome Version: 68.0.3440.106.
I'm sure this was working at some point, but no longer is. It's confusing because this table suggests that the Clipboard API is implemented in Chrome (has been for some time), but this table of specific API methods suggests that none of the methods of the API is supported??
This requires a secure origin — either HTTPS or localhost (or disabled by running Chrome with a flag). Just like for ServiceWorker, this state is indicated by the presence or absence of the property on the navigator object.
https://developers.google.com/web/updates/2018/03/clipboardapi
This is noted in the spec with [SecureContext] on the interface: https://w3c.github.io/clipboard-apis/#dom-navigator-clipboard
You can check the state of window.isSecureContext to learn if that's the reason a feature is unavailable. Secure contexts | MDN
And yes, you should set up HSTS to make sure HTTP redirects to HTTPS.
you can write an all-in-one wrapper function.
if in secure context (https) : use navigator clipboard api
if not : use the 'out of viewport hidden text area' trick
// return a promise
function copyToClipboard(textToCopy) {
// navigator clipboard api needs a secure context (https)
if (navigator.clipboard && window.isSecureContext) {
// navigator clipboard api method'
return navigator.clipboard.writeText(textToCopy);
} else {
// text area method
let textArea = document.createElement("textarea");
textArea.value = textToCopy;
// make the textarea out of viewport
textArea.style.position = "fixed";
textArea.style.left = "-999999px";
textArea.style.top = "-999999px";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
return new Promise((res, rej) => {
// here the magic happens
document.execCommand('copy') ? res() : rej();
textArea.remove();
});
}
}
use :
copyToClipboard("I'm going to the clipboard !")
.then(() => console.log('text copied !'))
.catch(() => console.log('error'));
ps : do not try it in a repl like jsfiddle/copeden/...
Try this:
if (typeof (navigator.clipboard) == 'undefined') {
console.log('navigator.clipboard');
var textArea = document.createElement("textarea");
textArea.value = linkToGo;
textArea.style.position = "fixed"; //avoid scrolling to bottom
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
toastr.info(msg);
} catch (err) {
toastr.warning('Was not possible to copy te text: ', err);
}
document.body.removeChild(textArea)
return;
}
navigator.clipboard.writeText(linkToGo).then(function () {
toastr.info(`successful!`);
}, function (err) {
toastr.warning('unsuccessful!', err);
});
In localhost, the clipboard is blocked by the chrome browser. You check this by going to the following path
Chrome > settings > privacy and Security > site settings > View permissions and data stored across sites then click on your localhost URL which will mentation on the page and check the permission of the clipboard
A minimal solution for copying tooltips when HTTPS is not yet available and the solution with document.execCommand('copy') does not work.
But it requires that the user selects and copies by hand what is displayed in the alert.
function copyToClipboard(text) {
if(navigator.clipboard) {
navigator.clipboard.writeText(text);
}
else{
alert(text);
}
}
This solutions works at the moment (it includes cross browser support, error handling + clean up).
https://stackoverflow.com/a/33928558/318380
you can use :
change the :
navigator.clipboard.writeText("Content")
to :
navigator['clipboard'].writeText("Content") instead.

record video by front-camera - WP8 - C#

My windows phone app needs to record a video from front-camera and send it to the server through a webservice.
Here while I'm trying to record video from front-camera, I'm getting mirror inverted video. Means front-camera records 180 degree rotated video.
what i think probably the only solution of it is to rotate the recorded video stream to 180 degree back.
Question:
is there any other solution to record proper video by front-camera in wp8?
if not, how to rotate the video stream 180 degree? any c# API to do it..?
Edit:
Here is code that I'm using:
XAML code for VideoBrush
<Canvas x:Name="CanvasLayoutRoot" RenderTransformOrigin="0.5 0.5"
Width="{Binding ActualHeight, ElementName=LayoutRoot}"
Height="{Binding ActualWidth, ElementName=LayoutRoot}"
Margin="-160 0 0 0">
<!--Background="Transparent"-->
<Canvas.Background>
<VideoBrush x:Name="videoBrush" />
</Canvas.Background>
<Canvas.RenderTransform>
<RotateTransform x:Name="rt" />
</Canvas.RenderTransform>
</Canvas>
Initializing camera
public async void InitializeVideoRecorder()
{
try
{
if (videoCapture == null)
{
// below line of code will detect if "Front Camera" is available or not
// if availble, then open it or it will open "Back Camera"
videoCapture = await AudioVideoCaptureDevice.OpenAsync(
AudioVideoCaptureDevice.AvailableSensorLocations.Contains(CameraSensorLocation.Front) ? CameraSensorLocation.Front : CameraSensorLocation.Back,
new Windows.Foundation.Size(640, 480));
videoCapture.RecordingFailed += videoCapture_RecordingFailed;
videoCapture.SetProperty(KnownCameraGeneralProperties.EncodeWithOrientation, videoCapture.SensorRotationInDegrees);
// Initialize the camera if it exists on the phone.
if (videoCapture != null)
{
videoBrush.SetSource(videoCapture);
if (!AudioVideoCaptureDevice.AvailableSensorLocations.Contains(CameraSensorLocation.Front))
{
rt.Angle = videoCapture.SensorRotationInDegrees;
}
else
{
rt.Angle = -(videoCapture.SensorRotationInDegrees);
}
}
else
{
MessageBox.Show("Unable to load Camera. Please try again later.", App.appName, MessageBoxButton.OK);
NavigationService.GoBack();
}
}
}
catch (Exception ex)
{
(new WebServices()).catchExceptions(ex);
NavigationService.GoBack();
}
}
Starting VideoCapture
private async Task StartVideoRecording()
{
try
{
// Gets the application data folder
StorageFolder applicationFolder = ApplicationData.Current.LocalFolder;
StorageFolder transfersFolder = await (await applicationFolder.GetFolderAsync("Shared")).GetFolderAsync("Transfers");
// Create the file specified in the application data folder
videoFileName = selectedQue.response.template_id + "_" + selectedQue.response.id + "_" + selectedQue.response.invite_id +".mp4";
StorageFile storageFile = await transfersFolder.CreateFileAsync(videoFileName, CreationCollisionOption.ReplaceExisting);
// Open a file stream, ready to write video data
randomAccessStream = await storageFile.OpenAsync(FileAccessMode.ReadWrite);
// Video recording to the specified stream
await videoCapture.StartRecordingToStreamAsync(randomAccessStream);
isRecordingStarted = true;
//timer = "0:00";
tbTimer.Text = "0:00";
dt.Start();
}
catch (Exception ex)
{
(new WebServices()).catchExceptions(ex);
}
}
This worked for me in the past, it was just a barcode scanner app that I coded up to fulfill a functional requirement. I put the transform on the <VideoBrush>.
<Grid x:Name="ContentPanel" Margin="12,0,12,0">
<Canvas x:Name="cam_canvas" Width="480" Height="480">
<Canvas.Background>
<VideoBrush x:Name="cam_video_brush" Stretch="None">
<VideoBrush.RelativeTransform>
<CompositeTransform Rotation="90" CenterX="0.5" CenterY="0.5" />
</VideoBrush.RelativeTransform>
</VideoBrush>
</Canvas.Background>
</Canvas>
</Grid>
Finally i solved my problem after 24 hours of efforts with below solution.
The line of code that causing issue by rotating video was below.
videoCapture.SetProperty(KnownCameraGeneralProperties.EncodeWithOrientation, videoCapture.SensorRotationInDegrees);
here videoCapture is object of AudioVideoCaptureDevice
While using front camera, we need to invert the rotation of cameraSensor.
So I've used the above same code (mentioned in question) with one tiny modification in this videoCapture.SetProperty line of code. the correct line of code is as below.
videoCapture.SetProperty(KnownCameraGeneralProperties.EncodeWithOrientation, -(videoCapture.SensorRotationInDegrees));
I just inverted the videoCapture.SensorRotationInDegrees by adding one minus sign (-) before it.
Hope this helps all..

Chromecast Launch, what's with the DIAL parameters? Aren't I runing MY application, not some registered standard?

The following code displays a proper list of available chromecast devices on my network. But when I click on the links, the application never launches. There are a couple of things that I'm quite confused about that may or may not be related to this question:
If I'm making my own custom application, what's with the DIAL parameters and why do I have to pass them? I don't want to write an app for the DIAL standard... this is MY app.
Again related to the DIAL parameters, if I search for devices with any other query other than "YouTube" (a DIAL parameter), the list always comes up blank. I suppose I shouldn't care, as long as the device is listed... but again... the app won't launch.
It should be noted that my sender app is a chrome webpage.
I'm a bit confused as to where my "appid" goes int he launch parameters,'
<html data-cast-api-enabled="true">
<body>
hi!<BR/>
<script>
var cast_api, cv_activity;
if (window.cast && window.cast.isAvailable) {
// Cast is known to be available
initializeApi();
} else {
// Wait for API to post a message to us
window.addEventListener("message", function(event) {
if (event.source == window && event.data &&
event.data.source == "CastApi" &&
event.data.event == "Hello")
{
//document.write("Initialize via message.<br/>");
initializeApi();
//document.write("Api initialized via message.");
};
});
};
initializeApi = function() {
cast_api = new cast.Api();
cast_api.addReceiverListener("YouTube", onReceiverList);
};
var g_list;
onReceiverList = function(list) {
g_list = list;
// If the list is non-empty, show a widget with
// the friendly names of receivers.
// When a receiver is picked, invoke doLaunch with the receiver.
document.write("Receivers: "+list.length+"<br/>");
var t;
for(t=0;t<list.length;t++)
document.write('found:'+list[t].name+' ' +list[t].id+'<br/>');
};
onLaunch = function(activity) {
if (activity.status == "running") {
cv_activity = activity;
// update UI to reflect that the receiver has received the
// launch command and should start video playback.
} else if (activity.status == "error") {
cv_activity = null;
}
};
function launchy(idx)
{
doLaunch(g_list[idx]);
}
doLaunch = function(receiver) {
var request = new window.cast.LaunchRequest(">>>>>what REALLY goes here?<<<<<<< ", receiver);
request.parameters = "v=abcdefg";
request.description = new window.cast.LaunchDescription();
request.description.text = "My Cat Video";
request.description.url = "http://my.website.get.your.own/chomecast/test.php";
cast_api.launch(request, onLaunch);
};
stopPlayback = function() {
if (cv_activity) {
cast_api.stopActivity(cv_activity.activityId);
}
};
</script>
</body>
</html>
The part marked "what really goes here?" is the part that I THINK is wrong... I couldn't be completely wrong. My device is white listed, I have an appid (which I thought might go in that slot)... The documentation merely says ActivityType DIAL Parmeters are valid, mandatory.
The first argument to the LaunchRequest is your App ID, the one that you have received in an email as part of whitelisting process. Also, the "YouTube" in the initialize method should also be replaced with the same App ID.
I strongly suggest you look at the sample that is on GitHub for chrome sender to see how you can send a request to load a media on a cast device.

Cordova multiple callbacks in Windows Phone 8

I have a Cordova plugin which works fine for both Android & iOS. However, it fails when ported to Windows Phone 8 because it seems that multiple outstanding callbacks are not supported in Cordova for Windows Phone.
The problem is this:
When a DispatchCommandResult is called with a PluginResult which has KeepCallback set to true, a further DispatchCommand from a different method will call both its callback and the previous callback (the one with KeepCallback set to true).
Worse still, if the second DispatchCommandResult has a PluginResult which has KeepCallback set to false (the default) then this cancels any further callbacks which have KeepCallback set to true.
Example:
Consider the code below. It's a modification of the Cordova Echo sample.
The echo method will (via DispatchCommandResult) call the javascript 'success' callback with the same string which it was originally called with (after a couple of JSON conversions)
The repeat method does the same as echo except it repeatedly calls the javascript 'success' callback every 5 seconds in a separate thread.
If repeat is called and then at some point after echo is called, the DispatchCommandResult in the echo method will result in both the echo success and the repeat success callbacks being called and then prevent further repeat success callbacks because the KeepCallback was not set to true.
In Android this problem is not an issue because of the callbackId provided by Cordova. However, for Windows Phone, the callbackId is not accessible.
C# code
namespace Cordova.Extension.Commands
{
public class Echo : BaseCommand
{
public void echo(string options)
{
string optVal = JsonHelper.Deserialize<string[]>(options)[0];
DispatchCommandResult(new PluginResult(PluginResult.Status.OK, optVal));
}
public void repeat(string options)
{
string optVal = JsonHelper.Deserialize<string[]>(options)[0];
ThreadStart worker = () =>
{
try
{
while (true)
{
Thread.Sleep(5000);
PluginResult r = new PluginResult(PluginResult.Status.OK, optVal);
r.KeepCallback = true;
DispatchCommandResult(r);
}
}
catch (Exception ex)
{
this.DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ex.Message));
}
};
new Thread(worker).Start();
}
}
}
JavaScript code
function echo() {
function success(message) {
console.log("echo success: " + message);
}
function error(e) {
console.log("echo error: " + e);
}
cordova.exec(success, error, "Echo", "echo", ["Hello"]);
}
function repeat() {
function success(message) {
console.log("repeat success: " + message);
}
function error(e) {
console.log("repeat error: " + e);
}
cordova.exec(success, error, "Echo", "repeat", ["Hello again"]);
}
echo();
.
.
.
repeat();
.
.
.
echo();
Sample output
Log:"echo success: Hello"
Log:"repeat success: Hello again"
Log:"repeat success: Hello again"
Log:"repeat success: Hello again"
Log:"repeat success: Hello again"
Log:"repeat success: Hello"
Log:"echo success: Hello"
Has anyone else had this problem? If so, is there a workaround? Am I doing anything wrong?
I had the same problem with cordova 2.5 and this is what I found.
In the (not yet released) 2.8 version of cordova, if you look at the BaseCommand.cs of the cordovalib files. You can see a CurrentCommandCallbackId that can be used to keep track of the callback you want to call.
Then if you set the KeepCallback to false, you can dispatch the command to the wanted callback.
The current release of PhoneGap is the 2.7.0, so to use this you'll have to clone the 2.8 version of cordova and copy the content of Plugins, cordova and cordivalib of the templates/standalone folder.
Once done, you can use this new feature with something like:
private void DispatchMessage(PluginResult.Status status, string message, bool keepCallback, string callBackID)
{
PluginResult res = new PluginResult(status, message);
res.KeepCallback = keepCallback;
DispatchCommandResult(res, callBackID);
}
However, once Phonegap 2.8 will be release, it will be safer to update your App with an official version of Cordova.