intel XDK directory browsing - node.js

I'm trying to get a way to reach and parse all JSON file from a directory, witch inside an Intel Xdk project. All files in my case stored in '/cards' folder of the project.
I have tried to reach theme with fs.readdirSync('/cards') method, but that wasn't pointed to the location what I expected, and I haven't got luck with 'intel.xdk.webRoot' path.
With the simulator I've managed to get files, with a trick:
fs.readdirSync(intel.xdk.webRoot.replace('localhost:53862/http-services/emulator-webserver/ripple/userapp/', '')+'cards');
(intel.xdk.webRoot contains absolute path to my '/cards' folder)
and its work like a charm, but it isn't working in any real device what I'd like to build it.
I have tried it with iOS7 and Android 4.2 phones.
Please help me to use in a great way the fs.readdirSync() method, or give me some alternate solution.
Thanks and regards,
satire

You can't use nodejs api's on mobile apps. It is a bug that the XDK emulator lets you do it. The bug is fixed in the next release of XDK.
You could write a node program that scans the directory and then writes out a js file with the contents of the directory. You would run the node script on your laptop before packaging the app in the build tab. The output would look like this:
files.js:
dir = {files: ['file1.txt', 'file2.txt']}
Then use a script tag to load it:
And your js can read the dir variable. This assumes that the contents does not change while the app is running.

The location of your application's root directory will vary depending on the target platform and can also vary with the emulator and the debug containers (e.g., App Preview versus App Analyzer). Here's what I've done to locate files within the project:
// getWebPath() returns the location of index.html
// getWebRoot() returns URI pointing to index.html
function getWebPath() {
"use strict" ;
var path = window.location.pathname ;
path = path.substring( 0, path.lastIndexOf('/') ) ;
return 'file://' + path ;
}
function getWebRoot() {
"use strict" ;
var path = window.location.href ;
path = path.substring( 0, path.lastIndexOf('/') ) ;
return path ;
}
I have not been able to test this exhaustively, but it appears to be working so far. Here's an example where I'm using a Cordova media object and want it to play a file stored locally in the project. Note that I have to "special case" the iOS container:
var x = window.device && window.device.platform ;
console.log("platform = ", x) ;
if(x.match(/(ios)|(iphone)|(ipod)|(ipad)/ig)) {
var media = new Media("audio/bark.wav", mediaSuccess, mediaError, mediaStatus) ;
}
else {
var media = new Media(getWebRoot() + "/audio/bark.wav", mediaSuccess, mediaError, mediaStatus) ;
}
console.log("media.src = ", media.src) ;
media.play() ;
Not quite sure if this is what you are looking for...

You will need to use the Cordova build in the Intel XDK, here is information on building with Cordova:
https://software.intel.com/en-us/html5/articles/using-the-cordova-for-android-ios-etc-build-option
And a DirectoryReader example:
function success(entries) {
var i;
for (i=0; i<entries.length; i++) {
console.log(entries[i].name);
}
}
function fail(error) {
alert("Failed to list directory contents: " + error.code);
}
// Get a directory reader
var directoryReader = dirEntry.createReader();
// Get a list of all the entries in the directory
directoryReader.readEntries(success,fail);

Related

Cleanest way to fix Windows 'filename too long' CI tests failure in this code?

I'm trying to solve this Windows filename issue
Basically our CI job fails, with the 'filename too long' error for Windows.
warning: Could not stat path 'node_modules/data-validator/tests/data/data-examples/ds000247/sub-emptyroom/ses-18910512/meg/sub-emptyroom_ses-18910512_task-noise_run-01_meg.ds/sub-emptyroom_ses-18910512_task-noise_run-01_meg.acq': Filename too long
I've read the docs for Node's path module, which seems like a possible solution. I also read about a Windows prefix (\\?\) to bypass the MAX_PATH...but have no idea how to implement these in a clean way.
This part of the codebase with the tests that are failing. The hardcoded path (testDatasetPath) is likely part of the problem.
function getDirectories(srcpath) {
return fs.readdirSync(srcpath).filter(function(file) {
return (
file !== '.git' && fs.statSync(path.join(srcpath, file)).isDirectory()
)
})
}
var missing_session_files = //array of strings here
const dataDirectory = 'data-validator/tests/data/'
function createDatasetFileList(path) {
const testDatasetPath = `${dataDirectory}${path}`
if (!isNode) {
return createFileList(testDatasetPath)
} else {
return testDatasetPath
}
}
createFileList function
function createFileList(dir) {
const str = dir.substr(dir.lastIndexOf('/') + 1) + '$'
const rootpath = dir.replace(new RegExp(str), '')
const paths = getFilepaths(dir, [], rootpath)
return paths.map(path => {
return createFile(path, path.replace(rootpath, ''))
})
}
tl;dr A GitLab CI Job fails on Windows because the node module filenames become too long. How can I make this nodejs code OS agnostic?
This is a known error in the Windows Environment, however, there is a fix..
If you're using an NTFS based filesystem, you should be able to enable long paths in
Local Computer Policy > Computer Configuration > Administrative Templates > System > Filesystem > NTFS
This is also specified in the document you just linked, and theoretically, should work. However, the path shouldn't really be longer than 32 bits,
This will come with some performance hits, but should get the job done.
Also, you should preferably switch to a better package or search for alternatives. If this is your own package, maybe restructure it?
Finally, if none of these work, move your project folder directly to your data drive, (C:\) this will cut down on the other nested and parent folders.
This is inherently bad, and you may run into issues during deployment, if you choose to do it.

How can I get information about the file that launched my app?

Similar to How to get the arguments for opening file with electron app but the solution there is not working for me.
Using:
OS - Windows 10
Electron - https://github.com/castlabs/electron-releases.git#v1.8.7-vmp1010
electron-builde - v20.28.3
I have a an electron app build with electron-builder, and using the latter I have specified a custom file association, .custom.
So when you double-click on a file with this extension, file.custom, the installed app opens. This file would have some data in it that the app needs, and I'd like to read this data using my app.
Is there any way that my app can detect what launched it, so that I can say "file.custom" launched me, and it's sitting at "C:\Users\Owner\Downloads\,?
The file does not appear in process.argv
You can get a reference to the file using process.argv, example:
var ipc = require('ipc');
var fs = require('fs');
// read the file and send data to the render process
ipc.on('get-file-data', function(event) {
var data = null;
if (process.platform == 'win32' && process.argv.length >= 2) {
var openFilePath = process.argv[1];
data = fs.readFileSync(openFilePath, 'utf-8');
}
event.returnValue = data;
});
source: Source

Open a directory in File Explorer

On ms Windows from node.js code, how can I open a specific directory (ex: c:\documents) in Windows file explorer?
I guess in c#, it would be:
process.Start(#"c:\test")
Try the following, which opens a File Explorer window on the computer running Node.js:
require('child_process').exec('start "" "c:\\test"');
If your path doesn't contain whitespace, you can also get away with 'start c:\\test', but the above - which requires "" as the 2nd argument[1] is the most robust approach.
Note:
The File Explorer window will launch asynchronously, and will receive focus when it does.
This related question asks for a solution that prevents the window from "stealing" focus.
[1] cmd.exe's internal start command by default interprets a "..."-enclosed 1st argument as the window title for the new console window to create (which doesn't apply here). By supplying a (dummy) window title - "" - explicitly, the 2nd argument is reliably interpreted as the target executable / document path.
Would be good to use this package so it would open on diffrent platform
https://www.npmjs.com/package/open-file-explorer
Or just use this part of it
function openExplorerin(path, callback) {
var cmd = ``;
switch (require(`os`).platform().toLowerCase().replace(/[0-9]/g, ``).replace(`darwin`, `macos`)) {
case `win`:
path = path || '=';
cmd = `explorer`;
break;
case `linux`:
path = path || '/';
cmd = `xdg-open`;
break;
case `macos`:
path = path || '/';
cmd = `open`;
break;
}
let p = require(`child_process`).spawn(cmd, [path]);
p.on('error', (err) => {
p.kill();
return callback(err);
});
}
I found another way on the WSL and potentially windows itself.
Note that you have to make sure you're formatting the path for Windows not Linux (WSL).
I wanted to save something on Windows, so in order to do that you use /mnt directory on WSL.
// format the path, so Windows isn't mad at us
// first we specify that we want the path to be compatible with windows style
// then we replace the /mnt/c/ with the format that windows explorer accepts
// the path would look like `c:\\Users\some\folder` after this line
const winPath = path.win32.resolve(dir).replace('\\mnt\\c\\', 'c:\\\\');
// then we use the same logic as the previous answer but change it up a bit
// do remember about the "" if you have spaces in your name
require('child_process').exec(`explorer.exe "${winPath}"`);
This should open the file explorer for you.
A slightly simpler, and more cross-platform solution, would be to use this.
var explorer;
switch (platform()) {
case "win32": explorer = "explorer"; break;
case "linux": explorer = "xdg-open"; break;
case "darwin": explorer = "open"; break;
}
spawn(explorer, [path], { detached: true }).unref();
platform() is from the os module, and spawn is from the child_process module.

Find absolute base path of the project directory

Until now we could get the absolute path of a file to open later as readStream with this code snippet:
var base = path.resolve('.');
var file = base + '/data/test.csv';
fs.createReadStream(file)
Since Meteor 0.6.5 the base path is pointing to .meteor/local/build/programs/...
There is also the Assets API, which but can not give us back a path but only the read document. We but need a stream to process some bigger data files?
Another way to find your project's root directory now is this:
var base = process.env.PWD
Note that this is not the same as process.cwd(). Instead it is the directory where you ran the meteor command, which is typically what you are looking for. Note also that this probably won't be very helpful when running your app from a deployed bundle.
I ran into the same predicament when I updated to 0.6.5.
What I'm currently doing is getting the path like this:
var meteor_root = Npm.require('fs').realpathSync( process.cwd() + '/../' );
This returns on dev mode:
/my/application/.meteor/local/build/programs
and on bundled mode:
/my/application/build/app/programs
So from here I'm getting to my application's "root" path like so:
var application_root = Npm.require('fs').realpathSync( meteor_root + '/../' );
// if running on dev mode
if( Npm.require('path').basename( Npm.require('fs').realpathSync( meteor_root + '/../../../' ) ) == '.meteor' ){
application_root = Npm.require('fs').realpathSync( meteor_root + '/../../../../' );
}
The only case in which this would fail is if you happen to name your application's folder ".meteor" but that's an edge case.
Relative to that you can access whatever else you need to.
Additionally, you can also get direct access to to the assets folder that the meteor bundler creates:
var assets_folder = meteor_root + '/server/assets/' + Npm.require('path').basename( application_root );
This is likely to be temporary as I expect better file/path interaction APIs to be added eventually..
Hope that helps
Since version 1.3, the documented function
Assets.absoluteFilePath(assetPath)
seems to be the best way to get the project path reliably.
Meteor Github
Hey you do not need to hardcode like the above answers... take a look to This package
After install it you can access the root path of your meteor just wih Meteor.rootPath
For Meteor 0.8.3,
__meteor_bootstrap__.serverDir gives out the working directory, when run in server mode.
example
if (Meteor.isServer) {
console.log(__meteor_bootstrap__.serverDir);
}
you could get project basic root path by
process.env.PWD
As of Meteor 1.2.1, this works for me:
var absoluteBasePath = path.resolve('../../../../../.');
The same result using split:
var absoluteBasePath = path.resolve('.').split(path.sep + '.meteor')[0];
Using process.cwd():
var absoluteBasePath = path.resolve(process.cwd(), '../../../../../');
var absoluteBasePath = path.resolve(process.cwd()).split(path.sep + '.meteor')[0];

AAssetManager_openDir crashing app on start

I'm trying to iterate through all the files contained in the assets folder. To get the working directory I use: AAssetManager_openDir. However simply having this in my code causes a crash on startup - android_main doens't even get a look in. Has anybody had similar problems and/or know how to resolve this?
const char* filename = (const char*)NULL;
const char* dirName = "";
AAssetDir* dir = AAssetManager_openDir(assetManager, dirName);
while((filename = AAssetDir_getNextFileName(dir)) != NULL)
{
//action per file
}
AAssetDir_close(dir);
Well I didn't have any luck getting it to work so I tried a different approach.
I compiled a static library of Minizip and, combined with Zlib, opened the APK file (the path of which found via JNIEnv) and found the filenames nestled within, skipping over entries not contained in the assets folder.
Roundabout way to do it but since AAssetManager_openDir isn't working this seemed like the only option.
Still it would be nice if somebody does find the "correct" solution.
const char* dirName = "";
Is probably what is causing the crash.
Instead try:
while(1)
{
const char* filename = AAssetDir_getNextFileName(dir);
if(!filename)
break;
}

Resources