On Cordova 2.0 app - readAsText breaks on iOS6 ... - file

I'm working on a Phonegap/Cordova app, use Cordova 2.0, and after iOS 6 is available - we suddenly begun to experience a problem. It's in the readAsText method of the file object.
Here is the part of the code. We use the facebook SDK to release Facebook Single Sign-On, and so we have a file, written down in a folder. Then we attempt to read it and take the token from it.
And so - on iOS 4 and iOS5 it's working - i.e. you'll see the two alerts - 111 and 222. But on iOS6 the second alert doesn't happen. Or in other words - the onloadend callback never triggers, although I see that the file is there.
// start the file interaction:
window.requestFileSystem(
LocalFileSystem.PERSISTENT,
0,
function(fileSystem) {
fileSystem.root.getFile(
"FacebookData/facebookData",
null,
function(fileEntry) {
fileEntry.file(
function(file) {
alert('111');
var reader = new FileReader();
reader.onloadend = function(evt) {
alert('222');
// do something with the file ..
}; // end of onloadend
reader.readAsText(file);
},
fail
); // end fileEntry.file
},
fail
); // end getfile
},
fail
); // end window.requestFileSystem
The function "fail" doesn't trigger at all, and also - all of this is inside a try-catch - but it doesn't throw an exception too.
And also - on iOS 4/5 it happens only once, but on iOS 6 it happens several times, as if you've clicked several times on a button and then the code executes.
Has anyone met a bug like this?

Known issue, apparently there is a fix there :
https://issues.apache.org/jira/browse/CB-1219
https://github.com/apache/incubator-cordova-js/pull/22
But I didn't test it yet.

Related

Loading PIXI textures, handling failures

I'm working on a map project under React, using react-leaflet, and leaflet-pixi-overlay. Markers are implemented using the PIXI overlay (React 16.13.1, pixi.js 5.3.0, leaflet 1.6.0, leaflet-pixi-overlay 1.8.1).
I am struggling a bit with the PIXI documentation. I would like to use this PIXI.Texture.fromURL method (http://pixijs.download/release/docs/PIXI.Texture.html#.fromURL)
However neither my VS Code environment, nor my compiled source can access this method.
I am using instead PIXI.Texture.from(imageUrl), as well as PIXI.Texture.fromLoader(imageUrl). Both seem to work, but I don't get the difference between the two? The docs don't show these as being promises, yet they seem to work well with an async await?
Then, when a load fails, I don't see how to tell that things went wrong. Actually what I don't see is how to tell that things went right!
If I do:
let failed = false;
let newTexture;
try {
newTexture = await PIXI.Texture.from(url);
} catch (err) {
console.log(`FAILED loading texture from ${url}, err=${err}`);
failed = true;
}
console.log(`valid=${texture.valid}`);
Then:
texture.valid is always false, even when the texture loaded and displays just fine
no error is ever thrown when the url points to nowhere
Any pointers, is there a site with good (recent as of 2020) PIXI references? Am I missing something basic? Thanks.
Edit 07/06/2020:
Issues were largely due to both my IDE and webpack not 'seeing' that I had update pixi.js to 5.3.0, restart of both gave me access to Texture.fromURL.
The Texture.from call is a synchronous one. My understanding is that by default, it will load a 'valid' texture of 1x1 px in case of failure. Texture.fromURL was added to provide an async solution, see https://github.com/pixijs/pixi.js/issues/6514
Looks to me like Texture.fromURL still needs a bit of work, as it doesn't seem to ever return on a failed fetch (at least for relative paths, which is what I use). I see the same thing when using the following approach:
const texture = PIXI.Texture.from(url, {
resourceOptions: { autoLoad: false }}
);
await texture.baseTexture.resource.load();
With a bad relative path, the load function never returns in my test environment.
Then, when a load fails, I don't see how to tell that things went wrong. Actually what I don't see is how to tell that things went right! If I do:
...
Then:
texture.valid is always false, even when the texture loaded and displays just fine
no error is ever thrown when the url points to nowhere
Ok, first thing: please use the newest version of PIXI which is now 5.3.0: https://github.com/pixijs/pixi.js/releases/tag/v5.3.0
Texture.fromUrl was added in this PR: https://github.com/pixijs/pixi.js/pull/6687/files . Please read description of this PR: https://github.com/pixijs/pixi.js/pull/6687 - user bigtimebuddy describes 3 ways to load Texture synchronously. From this you should understand why it didnt worked in your code.
Also see: https://gamedev.stackexchange.com/questions/175313/determine-when-a-pixi-texture-is-loaded-to-clone-it
About error handling, catching errors and checking if Texture is "valid": please try running following example (modified version of yours) :
let failed = false;
let newTexture;
try {
newTexture = await PIXI.Texture.fromURL('https://loremflickr.com/100/100');
// to see how failure works comment above line and uncomment line below:
// newTexture = await PIXI.Texture.fromURL('http://not-existing-site-0986756.com/not_existing.jpg');
} catch (err) {
console.log(`FAILED loading texture`);
console.log(err);
failed = true;
}
console.log('failed: ' + (failed ? 'yes' : 'no'));
console.log(`valid=${typeof newTexture !== 'undefined' ? newTexture.valid : 'variable newTexture is undefined'}`);
console.log(newTexture ? newTexture : 'n/a');
And lastly about method not found in IDE:
I would like to use this PIXI.Texture.fromURL method (http://pixijs.download/release/docs/PIXI.Texture.html#.fromURL)
However neither my VS Code environment, nor my compiled source can access this method.
I use PhpStorm (but other IntelliJ editor should be similar - for example: WebStorm) and it finds this method:
/**
* Useful for loading textures via URLs. Use instead of `Texture.from` because
* it does a better job of handling failed URLs more effectively. This also ignores
* `PIXI.settings.STRICT_TEXTURE_CACHE`. Works for Videos, SVGs, Images.
* #param {string} url The remote URL to load.
* #param {object} [options] Optional options to include
* #return {Promise<PIXI.Texture>} A Promise that resolves to a Texture.
*/
Texture.fromURL = function (url, options) {
var resourceOptions = Object.assign({ autoLoad: false }, options === null || options === void 0 ? void 0 : options.resourceOptions);
var texture = Texture.from(url, Object.assign({ resourceOptions: resourceOptions }, options), false);
var resource = texture.baseTexture.resource;
// The texture was already loaded
if (texture.baseTexture.valid) {
return Promise.resolve(texture);
}
// Manually load the texture, this should allow users to handle load errors
return resource.load().then(function () { return Promise.resolve(texture); });
};
Do you use the development build of Pixi, or production one? ( https://github.com/pixijs/pixi.js/releases ).
Update 2020-07-06:
Your comment:
One thing still not clear to me though: when using an approach based on PIXI.Loader, do the sprites using a given texture get automatically refreshed once the texture has been loaded, or is there a manual refresh process required?
If you use "PIXI.Loader" approach then you can set the "load" callback - in which you should have all resources / textures already loaded. See: https://pixijs.download/dev/docs/PIXI.Loader.html
First you define which resources need to be loaded:
// Chainable `add` to enqueue a resource
loader.add('bunny', 'data/bunny.png')
.add('spaceship', 'assets/spritesheet.json');
loader.add('scoreFont', 'assets/score.fnt');
and then you define the callback:
// The `load` method loads the queue of resources, and calls the passed in callback called once all
// resources have loaded.
loader.load((loader, resources) => {
// resources is an object where the key is the name of the resource loaded and the value is the resource object.
// They have a couple default properties:
// - `url`: The URL that the resource was loaded from
// - `error`: The error that happened when trying to load (if any)
// - `data`: The raw data that was loaded
// also may contain other properties based on the middleware that runs.
sprites.bunny = new PIXI.TilingSprite(resources.bunny.texture);
sprites.spaceship = new PIXI.TilingSprite(resources.spaceship.texture);
sprites.scoreFont = new PIXI.TilingSprite(resources.scoreFont.texture);
});
You can try this way and inside this callback you can observe that texture of each resource is valid - for example: resources.bunny.texture.valid - it should be true.
Also, as you see in that doc, you can use other more advanced features like middleware or other callbacks for error handling etc.

cn1PostMessage is undefined on Android. PostMessage is not working

I created a webview (BrowserComponent) and added a listener:
BComp.addWebEventListener(BrowserComponent.onMessage, e->{
Display.getInstance().callSerially(()->{
Dialog.show("Message", (String)e.getSource(), "OK", null);
});
});
Then, in the JavaScript of the embedded website, I called cn1PostMessage and postMesage. This works well in the simulator! But when building the application, on Android, it does nothing (cn1PostMessage is undefined and postMessage is not received by the main program).
var msg = "test";
if(window.cn1PostMessage) {
window.cn1PostMessage(msg);
} else {
window.parent.postMessage(msg, '*');
// Tried: window.postMessage(msg, '*');
// Tried: window.top.postMessage(msg, '*');
}
What can I do?
Thanks!
I just tried building the BrowserComponentPostMessageSample, and it seemed to work fine on my Galaxy S8, Android 8.
If you're finding that window.cn1PostMessage is undefined, then either there was a javascript error in page load that prevented that callback from being installed, or your code is running before the CodenameOne initialization code has run.
I have just added support for the "android.webContentsDebuggingEnabled" display property, which will make the app's web views debuggable using Chrome's remote development tools. This will make it easier for your to track down such issues. See usage example:
Display.getInstance().setProperty("android.webContentsDebuggingEnabled", "true");
This will be available in Friday's update (Dec. 6/19).
In the mean time, I recommend starting with the BrowserComponentPostMessageSample and modifying it to suit your needs from there.
Alternatively, if you can post a test case to demonstrate the issue, I can look at it.

AngularJS testing with Protractor- tests that used to pass now failing due to Waits timing out

About 6 months or so ago I started developing an automated test suite for an AngularJS application developed by my company, using Protractor.
After I had been working on this for a couple of months, some other work came up which I had to prioritise over the test suite, and so I haven't looked at it since around the end of November/ December last year.
When I stopped working on it, I made sure that everything that I had done up to that date was in a fully working state (commented/ removed the tests I had started working on but hadn't finished, etc), and committed that git branch. At this point, I was able to run all of the tests I had written up until then using the command protractor conf.js, and I could see that they were all passing as expected.
I recently checked my testing branch out again, as I have a day or two in between other projects, and thought I could make use of the time by working on the testing again.
The first thing I did once I had checked out the testing branch, was to try running my test scripts again, to ensure everything I had implemented so far was still working.
However, while most of the tests do still pass, a few of them are now failing due to time outs, even though I had made sure that all of the timing elements were working correctly before I shelved the testing for a while.
I have tried increasing the times that my tests should sleep or wait for things at the points at which they are failing, but this doesn't seem to have made a difference.
The particular tests that are now failing due to time outs are:
1.
it('should navigate to the Config/Platform page & check the values are all correct', function() {
browser.waitForAngularEnabled(false);
browser.actions().mouseMove(configMenuBtn).perform();
browser.wait(EC.visibilityOf(pageConfigPlatformBtn), 8000).then(browser.sleep(5000).then( /*ERF(14/11/2017 # 1630) browser.sleep() required to give DialogMgr service time to complete */
pageConfigPlatformBtn.click().then(function(){
browser.sleep(10000); /*ERF(14/11/2017 # 1640) This line is needed- because of how the form HTML is created, it needs time to be replaced by configured HTML that is displaying the required fields */
var eth0Mode = element(by.model('modelinstances.platform.eth_0_mode'));
var eth0Address = element(by.model('modelinstances.platform.static_ip.eth_0_address'));
var eth0Netmask = element(by.model('modelinstances.platform.static_ip.eth_0_netmask'));
var eth0gateway = element(by.model('modelinstances.platform.static_ip.eth_0_gateway'));
var eth1mode = element(by.model('modelinstances.platform.eth_1_mode'));
var eth1Address = element(by.model('modelinstances.platform.static_ip.eth_1_address'));
var eth1netmask = element(by.model('modelinstances.platform.static_ip.eth_1_netmask'));
var eth1gateway = element(by.model('modelinstances.platform.static_ip.eth_1_gateway'));
expect(browser.getCurrentUrl()).toMatch(moxaConfigPlatformUrlRegExpPattern);
expect(eth0Mode.getAttribute('value')).toBe("Static IP");
expect(eth0Address.getAttribute('value')).toBe("192.168.1.127");
expect(eth0Netmask.getAttribute('value')).toBe("255.255.255.0");
expect(eth0gateway.getAttribute('value')).toBe("192.168.1.1");
expect(eth1mode.getAttribute('value')).toBe("Static IP");
expect(eth1Address.getAttribute('value')).toBe("192.168.2.127");
expect(eth1netmask.getAttribute('value')).toBe("255.255.255.0");
expect(eth1gateway.getAttribute('value')).toBe("");
})));
})
The failure message for this test is:
App should navigate to the Config/Platform page & check the values are all correct
Message:
Failed: Wait timed out after 8002ms
Stack:
TimeoutError: Wait timed out after 8002ms
2.
it('should navigate to the Config/Date/Time page', function() {
browser.waitForAngularEnabled(false);
browser.actions().mouseMove(configMenuBtn).perform();
browser.wait(EC.visibilityOf(pageConfigDateTimeBtn), 2000).then(browser.sleep(1000).then( /*ERF(14/11/2017 # 1630) browser.sleep() required to give DialogMgr service time to complete */
pageConfigDateTimeBtn.click().then(function() {
expect(browser.getCurrentUrl()).toBe(VM + '/#/config/systemtime');
})));
})
The failure message for this test is:
App should navigate to the Config/Date/Time page
Message:
Failed: Wait timed out after 2023ms
Stack:
TimeoutError: Wait timed out after 2023ms
3.
it('should navigate to the Tag Browser page (final test)', function() {
console.log("Start final Tag Browser page test");
browser.waitForAngularEnabled(false);
browser.wait(EC.visibilityOf(pagesMenuBtn), 10000).then(
browser.actions().mouseMove(pagesMenuBtn).perform().then(
browser.wait(EC.visibilityOf(pageConfigDateTimeBtn), 2000).then(browser.sleep(1000)).then( /*ERF(14/11/2017 # 1650) browser.sleep() required to give DialogMgr service time to complete */
browser.wait(EC.visibilityOf(pageTagBrowserBtn), 12000).then(
pageTagBrowserBtn.click().then(
function() {
console.log("Tag Browser menu button clicked");
}).then(
browser.wait(EC.visibilityOf(tagBrowserPageTagsLink), 20000).then(
function(){
console.log("End Tag Browser page test (then call)");
expect(browser.getCurrentUrl()).toBe(VM + '/#/pages/tagbrowser');
}
)
)
)
)
)
);
});
The failure message for this test is:
App should navigate to the Tag Browser page (final test)
Message:
Failed: Wait timed out after 2009ms
Stack:
TimeoutError: Wait timed out after 2009ms
I have tried increasing the times that the wait() calls are being passed, but this hasn't resolved the issue.
I have read in the past that automated testing can be quite flakey, and that changes to the environment in which they're run can cause them to fail- so I'm guessing it's possible that because my computer will have changed since the tests were last run successfully (i.e. new software installed), this may be causing the tests to fail...?
Is there a method of 'best practice' for resolving this sort of issue with automated testing, or is just a case of having to go back and tweak my test scripts until they start passing again?
It's probably worth mentioning that all of my test are written in a spec.js file, and that these tests which failed are the last 3 of 18 test scripts in that file (i.e. the first 15 all still pass).
Anyone have any ideas how I can resolve this/ get my tests passing again?

Cordova Windows Phone 8 Play Local File Sound

How can I play a local mp3 file in the www folder?
Example: I need to play the following file : 'www/audio/button.mp3'. So:
1) I install the Cordova media and the media capture plugin.
2) I add the following code in the DeviceReady event handler :
var media=null;
function onDeviceReady()
{
alert("ready");
addSoundEffects();
}
function addSoundEffects(){
var soundUrl=getMediaUrl("/audio/button.mp3");
media=new Media(soundUrl,mediaLoaded,mediaError);
alert('after');
}
function getMediaUrl(s){
if(device.platform.toLowerCase() === "android") return "/android_asset/www" + s;
return 'www'+s;
}
function mediaLoaded(){
alert('Media loaded correctly');
}
function mediaError(e) {
alert('Media Error');
alert(JSON.stringify(e));
}
3) I run the application on my windows phone device, but it just stopped on the media=new Media(soundUrl,mediaLoaded,mediaError); row. I can see the "after" alert, but the function above doesn't call mediaLoaded neither mediaError, i don't know what to do.
NOTE: I think that the path is not the problem, otherwise it should just call the mediaError callback. I notice that the 'Media' variable is undefined, i don't know if can help.
Thanks for answer, i have been working on this from 3 hours and i can't find anything on google!
try to add '/' before www. It works in my apps

Cortana ran into an issue

I have created a javascript application (aka UWA) in order to play with my Belkin wemo and then turn on or turn off the ligth with Cortana. The following function is well called but Cortana ends up with an issue. If I remove the call to the HTTP call, the program works fine. Who can tell me what's wrong with the following function because no more details are exposed unfortunately (of course in the real program is replaced with the right URL):
function setWemo(status) {
WinJS.xhr({ url: "<url>" }).then(function () {
var userMessage = new voiceCommands.VoiceCommandUserMessage();
userMessage.spokenMessage = "Light is now turned " + status;
var statusContentTiles = [];
var statusTile = new voiceCommands.VoiceCommandContentTile();
statusTile.contentTileType = voiceCommands.VoiceCommandContentTileType.titleOnly;
statusTile.title = "Light is set to: " + status;
statusContentTiles.push(statusTile);
var response = voiceCommands.VoiceCommandResponse.createResponse(userMessage, statusContentTiles);
return voiceServiceConnection.reportSuccessAsync(response);
}).done();
}
Make sure that your background task has access to the WinJS namespace. For background tasks, since there isn't any default.html, base.js won't be getting imported automatically unless you explicitly do it.
I had to update winjs to version 4.2 from here (or the source repository on git), then add that to my project to update from the released version that comes with VS 2015. WinJS 4.0 has a bug where it complains about gamepad controls if you try to import it this way (see this MSDN forum post)
Then I added a line like
importScripts("/Microsoft.WinJS.4.0/js/base.js");
to the top of your script's starting code to import WinJS. Without this, you're probably getting an error like "WinJS is undefined" popping up in your debug console, but for some reason, whenever I hit that, I wasn't getting a debug break in visual studio. This was causing the Cortana session to just hang doing nothing, never sending a final response.
I'd also add that you should be handling errors and handling progress, so that you can periodically send progress reports to Cortana to ensure that it does not time you out (which is why it gives you the error, probably after around 5 seconds):
WinJS.xhr({ url: "http://urlhere/", responseType: "text" }).done(function completed(webResponse) {
... handle response here
},
function error(errorResponse) {
... error handling
},
function progress(requestProgress) {
... <some kind of check to see if it's been longer than a second or two here since the last progress report>
var userProgressMessage = new voiceCommands.VoiceCommandUserMessage();
userProgressMessage.DisplayMessage = "Still working on it!";
userProgressMessage.SpokenMessage = "Still working on it";
var response = voiceCommands.VoiceCommandResponse.createResponse(userProgressMessage);
return voiceServiceConnection.reportProgressAsync(response);
});

Resources