AAssetManager_openDir crashing app on start - android-ndk

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;
}

Related

Downloading multiple files from Google cloud storage using nodejs fails without errors

My code successfully downloads some of the files but not all. Execution just stops in the middle without any errors and the last file may be only partially downloaded. It always fails to download some files even if I change the number of files or if I use different files. File size doesn't seem to matter.
I've tried many things but it seems that I'm not able to catch any exceptions or errors when it stops. I've tried using try-catch and process.on events but not able to catch anything.
I'm pretty sure few months ago I used this kind of code to download hundreds of files without any problems.
Here is a simplified version of my current code.
const { Storage } = require('#google-cloud/storage');
const storage = new Storage({ keyFilename: 'D:/myProject/myKeyFile.json' });
var folder = 'D:/myProject/downloadedFiles';
var bucketName = 'bucket_1';
async function downloadFile(fileName) {
var fullPath = folder + '/' + fileName;
const options = {
destination: fullPath,
};
await storage.bucket(bucketName).file(fileName).download(options);
console.log(`gs://${bucketName}/${fileName} downloaded to ${fullPath}.`);
}
async function downloadFiles() {
var filenames = ['file1', 'file2', 'file3', 'file4', 'file5', 'file6'];
for(var i = 0; i < filenames.length; i++){
await downloadFile(filenames[i], i).catch(console.error);
}
}
downloadFiles().catch(console.error);
It turns out the download only fails on that specific computer, so my code is not the problem. My guess it is network related, maybe because a network switch was replaced some time ago.

How to delete all files and subdirectories in a directory with Node.js

I am working with node.js and need to empty a folder. I read a lot of deleting files or folders. But I didn't find answers, how to delete all files AND folders in my folder Test, without deleting my folder Test` itself.
I try to find a solution with fs or extra-fs. Happy for some help!
EDIT 1: Hey #Harald, you should use the del library that #ziishaned posted above. Because it's much more clean and scalable. And use my answer to learn how it works under the hood :)
EDIT: 2 (Dec 26 2021): I didn't know that there is a fs method named fs.rm that you can use to accomplish the task with just one line of code.
fs.rm(path_to_delete, { recursive: true }, callback)
// or use the synchronous version
fs.rmSync(path_to_delete, { recursive: true })
The above code is analogous to the linux shell command: rm -r path_to_delete.
We use fs.unlink and fs.rmdir to remove files and empty directories respectively. To check if a path represents a directory we can use fs.stat().
So we've to list all the contents in your test directory and remove them one by one.
By the way, I'll be using the synchronous version of fs methods mentioned above (e.g., fs.readdirSync instead of fs.readdir) to make my code simple. But if you're writing a production application then you should use asynchronous version of all the fs methods. I leave it up to you to read the docs here Node.js v14.18.1 File System documentation.
const fs = require("fs");
const path = require("path");
const DIR_TO_CLEAR = "./trash";
emptyDir(DIR_TO_CLEAR);
function emptyDir(dirPath) {
const dirContents = fs.readdirSync(dirPath); // List dir content
for (const fileOrDirPath of dirContents) {
try {
// Get Full path
const fullPath = path.join(dirPath, fileOrDirPath);
const stat = fs.statSync(fullPath);
if (stat.isDirectory()) {
// It's a sub directory
if (fs.readdirSync(fullPath).length) emptyDir(fullPath);
// If the dir is not empty then remove it's contents too(recursively)
fs.rmdirSync(fullPath);
} else fs.unlinkSync(fullPath); // It's a file
} catch (ex) {
console.error(ex.message);
}
}
}
Feel free to ask me if you don't understand anything in the code above :)
You can use del package to delete files and folder within a directory recursively without deleting the parent directory:
Install the required dependency:
npm install del
Use below code to delete subdirectories or files within Test directory without deleting Test directory itself:
const del = require("del");
del.sync(['Test/**', '!Test']);

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.

mem-fs-editor: How to copy relative symlinks?

I've got a directory which contains a lot of files and one (or more) symlinkname -> . symlink. I want to copy the contents of the entire directory to a new location. the following code copies everything just fine, though it skips the symlink. Adding globOptions.follow = true only makes it loop indefinitely, which makes sense since it will try to dereference it. How can I just make it copy all the content + symlinks without trying to follow them?
this.fs.copy(
this.destinationPath() + '/**',
this.destinationPath('build/html'),
{
globOptions: {
follow: true // This will make the copy loop infinitely, which makes sense.
}
}
});
After finding out that Yeoman is avoiding bad UX by excluding support for symlinks (see Simon Boudrias' comment), I knew I had to work around this issue. I did the following workaround, please note that this should only be applied if you're unable to avoid symlinks like I am.
var fs = require('fs');
// Find out if there are symlinks
var files = fs.readdirSync(this.destinationPath());
for (var i = 0; i < files.length; i++) {
var path = this.destinationPath(files[i]),
stats = fs.lstatSync(path);
if (stats.isSymbolicLink()) {
// Find the target of the symlink and make an identical link into the new location
var link = fs.readlinkSync(path);
fs.symlinkSync(link, this.destinationPath('build/html/' + files[i]));
}
}

intel XDK directory browsing

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);

Resources