Trying to write to a local file in Android.
Tried import {fileSystemModule} from "#nativescript/core"; but get error 'fileSystemModule' was not found in '#nativescript/core'.
Have also tried import {fileSystemModule} from "#nativescript/core/file-system" but it doesn't exist. I'm using plain Javascript.
Nativescript 8.0.2
The import paths are updated in the recent versions of NativeScript. You can access these directly now without having to go through fileSystemModule. See code below:
import { knownFolders, File, Folder } from '#nativescript/core';
To write to a local file using the latest NativeScript would look like this:
writeToFile(): void {
const folder = knownFolders.documents().getFolder(FOLDER_NAME);
const file = folder.getFile(FILE_NAME.txt);
file.writeText(SOME_STRING_TO_WRITE_TO_FILE);
}
To write to an accessible location in Android, you can use the following:
writeToFile(): void {
const folderPath = path.join(android.os.Environment.getExternalStorageDirectory().getAbsolutePath().toString())
const folder = Folder.fromPath(folderPath);
const file = folder.getFile(FILE_NAME.txt);
file.writeText(SOME_STRING_TO_WRITE_TO_FILE);
}
Related
I am trying to add this code snippet to the wed apis demo project but I tried and failed and there isnt much documentation on how to do it.
var os = require("os");
var bytesAvailable = os.totalmem(); // returns number in bytes
// 1 mb = 1048576 bytes
console.log("Total memory available MB :" + (bytesAvailable/1048576) );
it needs to have a type script file and a javascript file according to the implamentation with the create excel.js demo but im not sure how to go about that process.
FYI everyone looking at this, the developer made a decent tutorial for this but lets just go with im the type of developer who is kinda dumb but competent.
So Basically your gonna want to create a type script file using the index.ts file as a template
once you have a type script file place your custom JS in the onHostRead() part of the script
build it
this will create the js file and make it look similar to the other example files.
create a controller for your custom js like hosthook.cs, this is called the mainfunction in the api demo
add front facing logic to your software. ....so still testing idk If i got it right just yet
This did not work in visual studio code , I used visual studio 2022
dont install the type script nuget package visual studio recommends , its not in the documentation, will break build.
sometimes the people capable are too busy to help so dive deep in the code and get good (talking to myself here)
ipController.cs
using ElectronNET.API;
using ElectronNET.API.Entities;
using Microsoft.AspNetCore.Mvc;
using System.Linq;
namespace ElectronNET_API_Demos.Controllers
{
public class IPController : Controller
{
public IActionResult Index()
{
if (HybridSupport.IsElectronActive)
{
Electron.IpcMain.On("start-hoosthook", async (args) =>
{
var mainWindow = Electron.WindowManager.BrowserWindows.First();
var options = new OpenDialogOptions
{
Properties = new OpenDialogProperty[]
{
OpenDialogProperty.openDirectory
}
};
var folderPath = await Electron.Dialog.ShowOpenDialogAsync(mainWindow, options);
var resultFromTypeScript = await Electron.HostHook.CallAsync<string>("get-ip-address", folderPath);
Electron.IpcMain.Send(mainWindow, "ip-address-found", resultFromTypeScript);
});
}
return View();
}
}
}
ipAddress.ts
// #ts-ignore
import * as Electron from "electron";
import { Connector } from "./connector";
import { IPAddress } from "./ipAddress";
export class HookService extends Connector {
constructor(socket: SocketIO.Socket, public app: Electron.App) {
super(socket, app);
}
onHostReady(): void {
// execute your own JavaScript Host logic here
var os = require("os");
var result = console.log(os.networkInterfaces);
return result;
}
}
ipAddress.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HookService = void 0;
const connector_1 = require("./connector");
class HookService extends connector_1.Connector {
constructor(socket, app) {
super(socket, app);
this.app = app;
}
onHostReady() {
// execute your own JavaScript Host logic here
var os = require("os");
var result = console.log(os.networkInterfaces);
return result;
}
}
exports.HookService = HookService;
//# sourceMappingURL=ipAddress.js.map
My flutter web app creates files (csv and pdf) that should be downloaded on user click. It works fine on PC Chrome but fails on Android Chrome. No downloaded file is shown and a file named ".com.google.Chrome.xxxxxx" is stored (where the suffix is random).
Here is my code:
import 'dart:html' as html;
void saveFile(String name, dynamic data, String type) {
final blob = html.Blob([data], type);
html.AnchorElement(href: html.Url.createObjectUrlFromBlob(blob))
..download = name
..click();
}
I pass either the result of pdf.save() or the csv String into the data parameter.
I also tried this and it works perfectly on the same android Chrome (but I can't set the file name in this case and the automatically generated file name looks awful):
import 'dart:html' as html;
void saveFile(String name, dynamic data, String type) {
final blob = html.Blob([data], type);
html.window.open(html.Url.createObjectUrlFromBlob(blob), '_blank');
}
Any suggestions how to fix this?
I want to copy storage.db to documents or downloads folder. It's very easy to get the file path:
const filePath = application.android.context.getDatabasePath("storage.db").getAbsolutePath();
But, what isn't that easy is to copy that file to a folder users have access to. I searched this whole forum, and I found nothing useful for my case.
I'm using NativeScript 4.0.1 with vanilla JS.
If you want to share the DB file, the easiest way is to use nativescript-share-file plugin, send the file path and it will give you a nice dialog with intent picker, user may choose to Email the file Or save it to local folder etc.,
const shareFile = new ShareFile();
shareFile.open({
path: filePath,
});
I finally found the solution. I've seen so many users trying to achieve this, and I hope this will help all of you.
Add this to your AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Install nativescript-permissions:
npm i nativescript-permissions
Asking for permission:
const permissions = require('nativescript-permissions');
permissions.requestPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, "");
Require the necessary modules:
const fileSystemModule = require("tns-core-modules/file-system");
const application = require("application");
Then, create this function where you need to use it:
function copyFile() {
var myInput = new java.io.FileInputStream(appModule.android.context.getDatabasePath("storage.db").getAbsolutePath());
var myOutput = new java.io.FileOutputStream("/storage/emulated/0/databases/storage.db");
try {
var buffer = java.lang.reflect.Array.newInstance(java.lang.Byte.class.getField("TYPE").get(null), 1024);
var length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
}
catch (err) {
console.info("Error", err);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
exports.copyFile = copyFile;
In my case, the file storage.db will be copied to /storage/emulated/0/databases. If you need to create a folder, just do the following:
try {
var javaFile = new java.io.File("/storage/emulated/0/newfolder");
if (!javaFile.exists()) {
javaFile.mkdirs();
javaFile.setReadable(true);
javaFile.setWritable(true);
}
}
catch (err) {
console.info("Error", err);
}
If the destination folder has a file with the same name as the one you want to copy, you need to remove it first. That's why you should create a specific folder to guarantee it's empty.
I have a video file in my assets folder (like mp4). I want to read that video file as an image stream, like an image stream in the camera package https://pub.dev/documentation/camera/latest/camera/CameraController/startImageStream.html
I want to pass the image to Tflite model.
Something like that:
controller = loadVideo('assets/example.mp4'); // how to do that?!
controller.startImageStream((CameraImage img) {
Tflite.runPoseNetOnFrame(
bytesList: img.planes.map((plane) {
return plane.bytes;
}).toList(),
imageHeight: img.height,
imageWidth: img.width,
numResults: 1,
threshold: 0.1,
).then((recognitions) {
// ...
}
}
I tried to search in the image_picker and video_player packages, but did not find anything.
What I did is to split the images and save them as files and then send it to the tf model. It's not fast (because you make file and then read it) but it is working, tested on android and it should work on IOS :)
I made a PR in the package flutter_export_video_frame, now it have a function in the name of exportImagesFromFile. It is Returning a Stream of images from video file as Stream<File>.
To get the video file from the asset folder I use the following function:
import 'dart:async';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:path/path.dart';
Future<File> getImageFileFromAssets(String path) async {
final byteData = await rootBundle.load('assets/$path');
final fileName = basename(path);
final file = new File('${(await getTemporaryDirectory()).path}/$fileName');
await file.writeAsBytes(byteData.buffer
.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
return file;
}
And then to move it to the posenet/model, there is a function that gets File as input:
var results = await Tflite.runPoseNetOnImage(
path: path,
numResults: 1,
);
One possible improvement to this method is to make it works only on the RAM (after you read the video, of course)
Yes, sure you can do that in one of the following ways:
Use the export_video_frame plugin
Use video_thumbnail plugin
You can specify an exact frame by the time parameter.
In Flutter integration testing, how can we handle ImagePicker? as well as other platform related plugins?
Finally, I got a solution for this question.
this is the code in app.dart:
prepare an image file in assets, for example: images/sample.png.
import 'dart:io';
import 'dart:typed_data';
import 'package:path_provider/path_provider.dart';
import 'package:image_picker_test/main.dart' as app;
import 'package:flutter_driver/driver_extension.dart';
import 'package:flutter/services.dart';
void main() {
// This line enables the extension.
enableFlutterDriverExtension();
const MethodChannel channel =
MethodChannel('plugins.flutter.io/image_picker');
channel.setMockMethodCallHandler((MethodCall methodCall) async {
ByteData data = await rootBundle.load('images/sample.png');
Uint8List bytes = data.buffer.asUint8List();
Directory tempDir = await getTemporaryDirectory();
File file = await File('${tempDir.path}/tmp.tmp', ).writeAsBytes(bytes);
print(file.path);
return file.path;
});
app.main();
}
Frank Yan's solution works fine. Basically he is using MethodChannel as an interceptor of request to ImagePicker
MethodChannel('plugins.flutter.io/image_picker')
In this part he defines which plugin has to be mocked
channel.setMockMethodCallHandler((MethodCall methodCall) async {
ByteData data = await rootBundle.load('images/sample.png');
Uint8List bytes = data.buffer.asUint8List();
Directory tempDir = await getTemporaryDirectory();
File file = await File('${tempDir.path}/tmp.tmp', ).writeAsBytes(bytes);
print(file.path);
return file.path;
});
This function defines what has to be returned from request to image picker plugin. So your program will do these actions each time when user uses image picker. Right here it will just return the image from 'images/sample.png'. In my case I had to put image into assets/image.png in my project root. Anyway you can mock any plugin like that. I had to also mock cropper plugin which is called after image picker ends it's job.
**Note: **mocking is not the best way to go with e2e or as they are called in flutter integration tests. I used it just because there is no workaround (I couldn't find it) at the moment and I am blocked with step of picture upload in my scenario. So be careful with using such approach.
You don't need to call this function anywhere in test. Your app will run with mocked plugin that we define in MethodChannel constuctor MethodChannel('');