Is there any way of loading local resource files in dart? (not flutter) - dart

I want to load the bytes of a file into a variable while testing my flutter application.
I can't use the assets directory as those are bundled with the app and require WidgetsFlutterBinding.ensureInitialized();
I tried searching the file manually with the path package, but this did not seem to work and was rather hacky. That is why i'm searching for a more official approach.

I was thinking way to complicated ...
As Chuck Batson commented, you can just use the path from the projects root for passing it into the (dart:io) File:
File loadResource(String relativePath) {
final filePath = path.join("test", "resources", relativePath);
return File(filePath);
}
(Notice: The above code makes use of the path package for constructing a file path.)

Related

How to get the file path to an asset included in a Dart package?

I am writing a Dart package (not Flutter). I have included a few bitmap images as public assets, e.g., lib/assets/empty.png. When this package is running as a command-line app for an end-user, how can I get the file path to these assets on the user's system?
Use-case: My Dart package calls out to FFMPEG, and I need to tell FFMPEG where to find these asset files on the system that's using my package. For example, the call to FFMPEG might look like:
ffmpeg -i "path/to/lib/assets/empty.png" ...
Accessing a Dart package's assets can happen in two modalities:
Running a Dart CLI app with the dart tool and accessing a dependency's assets, or
Running an executable CLI app
The difference between these two situations is that when you're running a CLI app using the dart tool, all of your dependencies are available as structured packages in a local cache on your system. However, when you're running an executable, all relevant code is compiled into a single binary, which means you no longer have access at runtime to your dependencies' packages, you only have access to your dependencies' tree-shaken, compiled code.
Accessing assets when running with dart
The following code will resolve a package asset URI to a file system path.
final packageUri = Uri.parse('package:your_package/your/asset/path/some_file.whatever');
final future = Isolate.resolvePackageUri(packageUri);
// waitFor is strongly discouraged in general, but it is accepted as the
// only reasonable way to load package assets outside of Flutter.
// ignore: deprecated_member_use
final absoluteUri = waitFor(future, timeout: const Duration(seconds: 5));
final file = File.fromUri(absoluteUri);
if (file.existsSync()) {
return file.path;
}
This resolution code was adapted from Tim Sneath's winmd package: https://github.com/timsneath/winmd/blob/main/lib/src/metadatastore.dart#L84-L106
Accessing assets when running an executable
When compiling a client app to an executable, that client app simply cannot access any asset files that were stored with the dependent package. However, there is a work around that may work for some people (it did for me). You can store Base64 encoded versions of your assets in your Dart code, within your package.
First, encode each of your assets into a Base64 string and store those strings somewhere in your Dart code.
const myAsset = "iVBORw0KGgoAAA....kJggg==";
Then, at runtime, decode the string back to bytes, and then write those bytes to a new file on the local file system. Here's the method I used in my case:
/// Writes this asset to a new file on the host's file system.
///
/// The file is written to [destinationDirectory], or the current
/// working directory, if no destination is provided.
String inflateToLocalFile([Directory? destinationDirectory]) {
final directory = destinationDirectory ?? Directory.current;
final file = File(directory.path + Platform.pathSeparator + fileName);
file.createSync(recursive: true);
final decodedBytes = base64Decode(base64encoded);
file.writeAsBytesSync(decodedBytes);
return file.path;
}
This approach was suggested by #passsy
Have a look at the dcli package.
It has a 'pack' command designed to solve exactly this problem.
It encodes assets into dart files that can be unpacked at runtime.

Loading txt file as an asset for a dart package

In flutter it's easy to load a .txt asset at runtime by specifying it or its folder in the pubspec.yaml file and then loading it with rootBundle. However, i'm working on a pure dart package, and I'm struggling to work out how to get the package to load a .txt file relative to it's own directory structure.
When I use the package in a separate dart command line application i'm working on, the relative path that I specified in one of the package source code files causes an error to be thrown that the txt file doesn't exist. I understand why this error is being thrown, because the relative path is interpreted as being from the command line application's root directory instead of the package's root directory, but i'm unsure of how to solve this without specifying the absolute path for the .txt file. I'd rather not specify the absolute path as it makes the package less portable.
Is there anything similar to flutter's asset loading for a pure dart package?
I think you need the resolveSymbolicLinks or resolveSymbolicLinksSync methods to decode the relative path and then use the resolved path to read the txt file:
import 'dart:io';
void main() async {
String file = '../lib/main.dart';
var path = Uri.parse('.').resolveUri(Uri.file(file)).toFilePath();
print(path);
if (path == '') path = '.';
var resolved = await File(path).resolveSymbolicLinks();
print(resolved);
File(resolved).readAsString().then((String contents) {
print(contents);
});
}

Storing css an graphics outside .asar

I have an Electron App that - when used - needs to be packed as asar. On the other Hand CSS and graphics sometimes need to be changed while in use. Therefore I need to exclude some of the Files from packaging via --ignoreparameter and copy the unpacked Files manually into the Folder so I can change them easily. For that all of the Paths to my CSS need to be rewritten of course.
But then the App does not work in my development environment because those paths do not exist if not packed.
Does anybody know a Solution where I can access my CSS and graphic files in both environments - packed and unpacked?
You could use electron-is-dev to check if the app is running in a development environment or if it's in production. You would then use the file path that corresponds.
Something along the lines of:
const isDev = require('electron-is-dev')
if (isDev) {
//use development path (unpacked)
} else {
// use production path (packed)
}

What is the purpose of buildResources folder in electron-builder building process?

I'm reading through electron and electron-builder docs, but I still do not quite understand what is the purpose of the buildResources folder?
Here's what a configuration doc for electron-builder says:
buildResources = build String - The path to build resources.
Kind of self-explanatory... But how or when they are involved in the build process, especially having that:
...build resources is not packed into the app. If you need to use some
files, e.g. as tray icon, please include required files explicitly
Can we simply put those icon files in an arbitrary folder and then copy over into the app/ manually (since we need to include buildResources manually anyway)?
TL;DR:
As far as I can tell from a quick glance at the source code, the buildResources folder is used to hold additional scripts, plugins, etc. that can be used by the package building software. Electron-builder doesn't generate the packages itself, it uses tools like NSIS.
Explanation:
I've had the same question and unfortunately find an answer for this isn't very straight-forward. The docs entry is pretty useless. I found out that someone asked about it in the GitHub issues but never got an answer.
I decided to dig in the code a bit myself to find out what it does. In NsisTargets.ts, you can see that the buildResources folder can contain custom includes and plugins for NSIS.
// NsisTargets.ts
taskManager.add(async () => {
const userPluginDir = path.join(packager.info.buildResourcesDir, pluginArch)
const stat = await statOrNull(userPluginDir)
if (stat != null && stat.isDirectory()) {
scriptGenerator.addPluginDir(pluginArch, userPluginDir)
}
})
// [...]
taskManager.add(async () => {
const customInclude = await packager.getResource(this.options.include, "installer.nsh")
if (customInclude != null) {
scriptGenerator.addIncludeDir(packager.info.buildResourcesDir)
scriptGenerator.include(customInclude)
}
})
and in pkg.ts it's used to load additional scripts to the pkg builder:
// pkg.ts
if (options.scripts != null) {
args.push("--scripts", path.resolve(this.packager.info.buildResourcesDir, options.scripts))
}
It appears as though buildResources can contain assets/scripts specifically used for the build process. That also explains why the contents of buildResources aren't included in the resulting app.asar file.
So, I'm going to say straight away that the documentation for this option is just awful.
Files included in buildResources will appear in the asar file which you can find documentation about on electron's website.
The option files will include files such as pictures which are not accessible in the asar file.
I.E.
given I have a folder called assets in my build folder I want to include with my app.
"files": [
"./build/**/*"
],
"directories": {
"buildResources": "assets"
}
This will put all folders inside build into the asar file, which you can then unpack by including,
"asarUnpack": "**/assets/*"
This will put the folder assets into the build folder in the app directory.

read file from res folder blackberry

I want to read file from "res" folder on blackberry. The file that i used is a file javascript.
I used this code InputStream in = classs.getResourceAsStream("file.js");. But i get "could not find this path" and I use also
String srcFile = "/res/ressourcesWeb/file.js";
FileConnection srcConn = (FileConnection) Connector.open(srcFile, Connector.READ);
InputStream in = srcConn.openInputStream();
but i got an exception.
Can any one help me to read the file and give me the right path that should I use?
Your res folder has to be inside src folder to be accessed from your code.
src folder is the root folder of your project package. And all folders outside of src folder are invisible for the code at runtime.
Check this post for more details: Blackberry runtime error: FRIDG: could not find img/logo.png
There's file location principle described.
You actually do not need to put your resources under the src folder for them to be accessible from your code.
That is one way to do it, but I don't think it's the best way. Files under the src folder should really be source code, not images, or other resources. For JavaScript resources, it's debatable whether those should be under src or not. Most projects I've seen have used the src folder for only Java source code.
In any case, if you would like to keep your file (or other resources, like images) outside the src folder, you can do so. The BlackBerry plugin for Eclipse actually sets it up like this by default, when you create a new project. There is a res folder at the top level, next to (not under) src.
If you have
src\
src\com\mycompany\myapp\
res\
res\resourcesWeb\
res\resourcesWeb\file.js
Then, you can open the file like this:
String jsPath = "/resourcesWeb/file.js";
InputStream input = getClass().getResourceAsStream(jsPath);
byte [] content = IOUtilities.streamToBytes(input);
String contentAsString = new String(content);
P.S. You also can probably do this:
String jsPath = "/file.js";
InputStream input = getClass().getResourceAsStream(jsPath);
and not specify the path to the resource. Obviously, this will only work if there are no naming conflicts in your resource folders (e.g. you don't have /res/resourcesWeb/file.js and also /res/otherPath/file.js)

Resources